失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > JSD-2204-(业务逻辑开发)-发酷鲨商城front模块-开发购物车功能-Day09

JSD-2204-(业务逻辑开发)-发酷鲨商城front模块-开发购物车功能-Day09

时间:2022-05-09 13:00:04

相关推荐

JSD-2204-(业务逻辑开发)-发酷鲨商城front模块-开发购物车功能-Day09

1.开发酷鲨商城front模块

1.1按分类id查询spu列表

用户会根据分类树中的分类的名称,查询它需要的商品类别

点击商品分类名称时,实际上我们获得了它的分类id(categoryId)

我们可以根据这个id到pms_spu表中查询商品信息

并进行分页显示

这个查询目标仍然为mall-pms数据库,是product模块管理的范围

所以我们在业务逻辑层中编写利用dubbo调用即可,还是不需要写mapper

下面就在业务逻辑层中创建FrontProductServiceImpl

@Service@Slf4jpublic class FrontProductServiceImpl implements IFrontProductService {@DubboReferenceprivate IForFrontSpuService dubboSpuService;@Overridepublic JsonPage<SpuListItemVO> listSpuByCategoryId(Long categoryId, Integer page, Integer pageSize) {// IForFrontSpuService实现类中已经完成了分页查询的细节,我们直接调用即可JsonPage<SpuListItemVO> list=dubboSpuService.listSpuByCategoryId(categoryId,page,pageSize);// 返回 list!!!return list;}@Overridepublic SpuStandardVO getFrontSpuById(Long id) {return null;}@Overridepublic List<SkuStandardVO> getFrontSkusBySpuId(Long spuId) {return null;}@Overridepublic SpuDetailStandardVO getSpuDetail(Long spuId) {return null;}@Overridepublic List<AttributeStandardVO> getSpuAttributesBySpuId(Long spuId) {return null;}}

业务逻辑层实现类先只实现按分类id分页查询的功能即可

创建FrontSpuController编写调用代码如下

@RestController@RequestMapping("/front/spu")@Api(tags = "前台商品spu模块")public class FrontSpuController {@Autowiredprivate IFrontProductService frontProductService;// localhost:10004/front/spu/list/3@GetMapping("/list/{categoryId}")@ApiOperation("根据分类id分页查询spu列表")@ApiImplicitParams({@ApiImplicitParam(value = "分类id",name="categoryId",example = "3",required = true,dataType = "long"),@ApiImplicitParam(value = "页码",name="page",example = "1",required = true,dataType = "int"),@ApiImplicitParam(value = "每页条数",name="pageSize",example = "2",required = true,dataType = "int")})public JsonResult<JsonPage<SpuListItemVO>> listSpuByPage(@PathVariable Long categoryId, Integer page,Integer pageSize){JsonPage<SpuListItemVO> jsonPage=frontProductService.listSpuByCategoryId(categoryId,page,pageSize);return JsonResult.ok(jsonPage);}}

然后在Nacos\Seata\Redis启动的前提下

顺序启动Product\Front

进行测试

http://localhost:10004/doc.html

1.2实现查询商品详情页

上面章节完成了查询spu列表

在商品列表中选中商品后,会显示这个商品的详情信息

商品详情页我们需要显示的信息包括

根据spuId查询spu信息根据spuId查询spuDetail详情根据spuId查询当前Spu包含的所有属性根据spuId查询对应的sku列表

继续编写FrontProductServiceImpl其他没有实现的方法

@Service@Slf4jpublic class FrontProductServiceImpl implements IFrontProductService {@DubboReferenceprivate IForFrontSpuService dubboSpuService;// 消费skuService的相关服务:根据spuId查询sku列表@DubboReferenceprivate IForFrontSkuService dubboSkuService;// 消费指定商品查询所有参数选项的相关服务:根据spuId查询参数列表@DubboReferenceprivate IForFrontAttributeService dubboAttributeService;@Overridepublic JsonPage<SpuListItemVO> listSpuByCategoryId(Long categoryId, Integer page, Integer pageSize) {// IForFrontSpuService实现类中已经完成了分页查询的细节,我们直接调用即可JsonPage<SpuListItemVO> list=dubboSpuService.listSpuByCategoryId(categoryId,page,pageSize);// 返回 list!!!return list;}// 根据spuId查询Spu对象信息@Overridepublic SpuStandardVO getFrontSpuById(Long id) {//SpuStandardVO是标准的查询spu的返回值SpuStandardVO spuStandardVO=dubboSpuService.getSpuById(id);return spuStandardVO;}// 根据SpuId查询sku列表@Overridepublic List<SkuStandardVO> getFrontSkusBySpuId(Long spuId) {// SkuStandardVO是标准的查询sku的返回值List<SkuStandardVO> list=dubboSkuService.getSkusBySpuId(spuId);return list;}// 根据spuId查询spuDetail对象@Overridepublic SpuDetailStandardVO getSpuDetail(Long spuId) {SpuDetailStandardVO spuDetailStandardVO=dubboSpuService.getSpuDetailById(spuId);return spuDetailStandardVO;}// 根据spuId查询当前商品所有参数列表@Overridepublic List<AttributeStandardVO> getSpuAttributesBySpuId(Long spuId) {List<AttributeStandardVO> list=dubboAttributeService.getSpuAttributesBySpuId(spuId);return list;}}

其中根据spuId查询所有对应属性的功能,是需要多表联查实现的

根据spuId查询参数选项的思路

1.根据spu_id去pms_spu表查询category_id

2.根据category_id去pms_category表查询分类对象

3.根据category_id去pms_category_attribute_template表查询attribute_template_id

4.根据attribute_template_id去pms_attribute_template表查询attribute_template数据行

5.根据attribute_template_id去pms_attribute表查询对应所有属性信息行

实际上,上面的联表查询可以简化为3表联查,结果相同

SELECT pa.id,pa.template_id, pa.name,pa.description,pa.type,pa.value_list,pa.unitFROM pms_spu psJOIN pms_category pc ON ps.category_id=pc.idJOIN pms_category_attribute_template pcat ONpc.id=pcat.category_idJOIN pms_attribute_template pat ON pcat.attribute_template_id= pat.idJOIN pms_attribute pa ON pa.template_id=pat.idWHERE ps.id=1

业务逻辑层正常调用

FrontSpuController添加两个方法

根据spuId查询spu详情根据spuId查询参数列表的

@RestController@RequestMapping("/front/spu")@Api(tags = "前台商品spu模块")public class FrontSpuController {@Autowiredprivate IFrontProductService frontProductService;// localhost:10004/front/spu/list/3@GetMapping("/list/{categoryId}")@ApiOperation("根据分类id分页查询spu列表")@ApiImplicitParams({@ApiImplicitParam(value = "分类id",name="categoryId",example = "3",required = true,dataType = "long"),@ApiImplicitParam(value = "页码",name="page",example = "1",required = true,dataType = "int"),@ApiImplicitParam(value = "每页条数",name="pageSize",example = "2",required = true,dataType = "int")})public JsonResult<JsonPage<SpuListItemVO>> listSpuByPage(@PathVariable Long categoryId, Integer page,Integer pageSize){JsonPage<SpuListItemVO> jsonPage=frontProductService.listSpuByCategoryId(categoryId,page,pageSize);return JsonResult.ok(jsonPage);}// 根据spuId查询spu信息// localhost:10004/front/spu/1@GetMapping("/{spuId}")@ApiOperation("根据spuId查询spu信息")@ApiImplicitParam(value = "spuId",name="spuId",example = "1",required = true,dataType = "long")public JsonResult<SpuStandardVO> getFrontSpuById(@PathVariable Long spuId){SpuStandardVO spuStandardVO=frontProductService.getFrontSpuById(spuId);return JsonResult.ok(spuStandardVO);}// 根据spuId查询所有参数选项@GetMapping("/template/{id}")@ApiOperation("根据spuId查询所有参数选项")@ApiImplicitParam(value = "spuId",name="id",example = "1",required = true,dataType = "long")public JsonResult<List<AttributeStandardVO>> getAttributesBySpuId(@PathVariable Long id){List<AttributeStandardVO> list=frontProductService.getSpuAttributesBySpuId(id);return JsonResult.ok(list);}}

创建FrontSkuController添加一个方法

根据spuId查询sku列表

@RestController@RequestMapping("/front/sku")@Api(tags="商品前台sku模块")public class FrontSkuController {@Autowiredprivate IFrontProductService frontProductService;// 根据spuId查询sku列表// localhost:10004/front/sku/1@GetMapping("/{spuId}")@ApiOperation("根据spuId查询sku列表")@ApiImplicitParam(value = "spuId",name="spuId",example = "1",required = true,dataType = "long")public JsonResult<List<SkuStandardVO>> getSkuListBySpuId(@PathVariable Long spuId){List<SkuStandardVO> list=frontProductService.getFrontSkusBySpuId(spuId);return JsonResult.ok(list);}}

FrontSpuDetailController添加一个方法

根据spuId查询spuDetail

@RestController@RequestMapping("/front/spu/detail")@Api(tags = "前台spuDetail模块")public class FrontSpuDetailController {@Autowiredprivate IFrontProductService frontProductService;// 根据spuId查询spuDetail信息@GetMapping("/{spuId}")@ApiOperation("根据spuId查询spuDetail信息")@ApiImplicitParam(value = "spuId",name = "spuId",example = "1",required = true,dataType = "long")public JsonResult<SpuDetailStandardVO> getSpuDetailBySpuId(@PathVariable Long spuId){SpuDetailStandardVO spuDetailStandardVO=frontProductService.getSpuDetail(spuId);return JsonResult.ok(spuDetailStandardVO);}}

nacos\seata\redis保持启动

启动product重起front

访问10004测试

2.登录流程回顾

2.1用户\角色\权限

用户是一个基本的单位

我们登录时都是在登录用户的

我们再登录后需要明确这个用户具有哪些角色

用户和角色的关系是多对多

用户是一张表,角色也是一张表,因为它们是多对多的关系所以要有一张保存用户和角色关系的中间表

角色也不能直接决定这个用户能做什么操作,有哪些权限

需要再关联权限表决定

角色和权限也是多对多的关系,也要有中间表

如果项目开发的权限比较全面,可能会出现临时用户权限关系表

2.2Spring Security

Spring Security框架用于实现登录,内置加密,验证,放行等各种功能,可靠性强

同时还可以将当前登录用户的信息保存

特别的,对于用户具备的权限,有特殊的管理

在控制器运行前,可以使用注解来判断当前登录用户是否具备某个权限

@PreAuthorize("[权限名称]")

SpringSecurity在运行该方法之前进行核查

如果不具备这个权限会返回403状态码

2.3关于单点登录

2.3.1普通登录的问题

SSO是单点登录的缩写

微服务架构下,要解决单点登录实现会话保持的问题

首先我们分析一下普通登录和微服务登录的区别

先是单体项目登录之后的操作流程

主要依靠服务器的session保存用户信息

客户端发请求时,将sessionid同时发往服务器,根据sessionid就能确认用户身份

分布式或微服务项目中,服务器不再只有一个

那么就会出现下面的问题

上面的图片,表示我们在微服务系统中登录时遇到的问题

我们在用户模块中登录,只是将用户信息保存在用户模块的session中

而这个session不会和其他模块共享

所以在我们访问购物车模块或其他模块时,通过sessionid并不能获得在用户模块中登录成功的信息

这样就丢失的用户信息,不能完成业务

市面上现在大多使用JWT来实现微服务架构下的会话保持

也就是在一个服务器上登录成功后,微服务的其他模块也能识别用户的登录信息

这个技术就是单点登录

2.4单点登录解决方案

2.4.1Session共享

Session共享是能够实现单点登录效果的

这种方式的核心思想是将用户的登录信息共享给其他模块

适用于小型的,用户量不大的微服务项目

将登录成功的用户信息共享给Redis

其他模块根据sessionId获得Redis中保存的用户信息即可

这样做最大的缺点就是内存严重冗余,不适合大量用户的微服务项目

JWT单点登录

token令牌

Json Web Token

这种登录方式,最大的优点就是不占用内存

生成的JWT由客户端自己保存,不占用服务器内存

在需要表明自己用户身份\信息时,将JWT信息保存到请求头中发送请求即可

2.3.2Jwt登录流程图

SSO(Single Sign On):单点登录

2.4开发购物车功能

2.4.1新增sku到购物车

我们开发完成了显示商品详情的功能

可以通过选中具体规格之后确定要购买的sku信息

再点击"添加到购物车"按钮

就应该将选中的sku的信息保存在购物车中

打开mall-order-webapi模块

创建mapper\service.impl\controller包

当前mall-order模块,管理的数据库是mall-oms数据库

业务逻辑分析

判断用户是否登录,只有登录后才能将商品新增到购物车验证购物车信息的完整性(SpringValidation)业务逻辑层要判断新增的sku是否在当前用户的购物车表中已经存在 如果不存在是新增sku流程如果已经存在,是修改数量的流程

2.4.2开发持久层

持久层要按上面分析的业务逻辑,开发多个方法

1.判断当前登录用户购物车中是否包含指定skuid商品的方法

2.新增sku到购物车表中

3.修改购物车指定sku数量的方法

在mapper包中创建OmsCartMapper接口,编写代码如下

@Repositorypublic interface OmsCartMapper {// 判断当前用户的购物车中是否已经包含指定商品的skuOmsCart selectExistsCart(@Param("userId") Long userId,@Param("skuId") Long skuId);// 新增sku信息到购物车int saveCart(OmsCart omsCart);// 修改购物车中sku的数量int updateQuantityById(OmsCart omsCart);}

对应的OmsCartMapper.xml文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN" "/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.tedu.mall.order.mapper.OmsCartMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="cn.tedu.mall.pojo.order.model.OmsCart"><id column="id" property="id" /><result column="user_id" property="userId" /><result column="sku_id" property="skuId" /><result column="title" property="title" /><result column="main_picture" property="mainPicture" /><result column="price" property="price" /><result column="quantity" property="quantity" /><result column="gmt_create" property="gmtCreate" /><result column="gmt_modified" property="gmtModified" /><result column="bar_code" property="barCode"/><result column="data" property="data"/></resultMap><!-- 定义查询时所有列名的sql片段 --><sql id="SimpleQueryFields"><if test="true">id,user_id,sku_id,title,main_picture,price,quantity,gmt_create,gmt_modified</if></sql><!-- 判断当前用户的购物车中是否已经包含指定商品的sku --><select id="selectExistsCart" resultMap="BaseResultMap">select<include refid="SimpleQueryFields"/>fromoms_cartwhereuser_id=#{userId}andsku_id=#{skuId}</select><!-- 新增购物车中sku的信息 --><insert id="saveCart" useGeneratedKeys="true" keyProperty="id" >insert into oms_cart(user_id,sku_id,title,main_picture,price,quantity) values(#{userId},#{skuId},#{title},#{mainPicture},#{price},#{quantity})</insert><!-- 修改购物车中sku的数量 --><update id="updateQuantityById">updateoms_cartsetquantity=#{quantity}whereid=#{id}</update></mapper>

2.4.3开发业务逻辑层

创建OmsCartServiceImpl类实现IOmsCartService接口

实现其中方法,先实现新增购物车的方法即可

在编写业务逻辑层具体代码前,先在该类中编写一个从SpringSecurity上下文中获取用户信息的方法

随笔

杨过学生签到

尹志平班主任考勤管理

小龙女授课老师课程管理

张无忌年级组长考试管理

张三丰校长课表管理

​学生管理

​教师管理

如果觉得《JSD-2204-(业务逻辑开发)-发酷鲨商城front模块-开发购物车功能-Day09》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。