前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[springboot 开发单体web shop] 7. 多种形式提供商品列表

[springboot 开发单体web shop] 7. 多种形式提供商品列表

作者头像
Isaac Zhang
发布2019-11-22 18:51:22
5810
发布2019-11-22 18:51:22
举报
文章被收录于专栏:奔跑的人生奔跑的人生

上文回顾

上节 我们实现了仿jd的轮播广告以及商品分类的功能,并且讲解了不同的注入方式,本节我们将继续实现我们的电商主业务,商品信息的展示。

需求分析

首先,在我们开始本节编码之前,我们先来分析一下都有哪些地方会对商品进行展示,打开jd首页,鼠标下拉可以看到如下:

首页商品列表示例
首页商品列表示例

可以看到,在大类型下查询了部分商品在首页进行展示(可以是最新的,也可以是网站推荐等等),然后点击任何一个分类,可以看到如下:

分类商品列表示例
分类商品列表示例

我们一般进到电商网站之后,最常用的一个功能就是搜索,搜索钢琴结果如下:

搜索查询结果示例
搜索查询结果示例

选择任意一个商品点击,都可以进入到详情页面,这个是单个商品的信息展示。 综上,我们可以知道,要实现一个电商平台的商品展示,最基本的包含:

  • 首页推荐/最新上架商品
  • 分类查询商品
  • 关键词搜索商品
  • 商品详情展示
  • ...

接下来,我们就可以开始商品相关的业务开发了。

首页商品列表|IndexProductList

开发梳理

我们首先来实现在首页展示的推荐商品列表,来看一下都需要展示哪些信息,以及如何进行展示。

  • 商品主键(product_id)
  • 展示图片(image_url)
  • 商品名称(product_name)
  • 商品价格(product_price)
  • 分类说明(description)
  • 分类名称(category_name)
  • 分类主键(category_id)
  • 其他...

编码实现

根据一级分类查询

遵循开发顺序,自下而上,如果基础mapper解决不了,那么优先编写SQL mapper,因为我们需要在同一张表中根据parent_id递归的实现数据查询,当然我们这里使用的是表链接的方式实现。因此,common mapper无法满足我们的需求,需要自定义mapper实现。

Custom Mapper实现

上节根据一级分类查询子分类一样,在项目mscx-shop-mapper中添加一个自定义实现接口com.liferunner.custom.ProductCustomMapper,然后在resources\mapper\custom路径下同步创建xml文件mapper/custom/ProductCustomMapper.xml,此时,因为我们在上节中已经配置了当前文件夹可以被容器扫描到,所以我们添加的新的mapper就会在启动时被扫描加载,代码如下:

Service实现

serviceproject 创建com.liferunner.service.IProductService接口以及其实现类com.liferunner.service.impl.ProductServiceImpl,添加查询方法如下:

Controller实现

接着,在com.liferunner.api.controller.IndexController中实现对外暴露的查询接口:

Test API

编写完成之后,我们需要对我们的代码进行测试验证,还是通过使用RestService插件来实现,当然,大家也可以通过Postman来测试,结果如下:

根据一级分类查询商品列表
根据一级分类查询商品列表

商品列表|ProductList

如开文之初我们看到的京东商品列表一样,我们先分析一下在商品列表页面都需要哪些元素信息?

开发梳理

商品列表的展示按照我们之前的分析,总共分为2大类:

  • 选择商品分类之后,展示当前分类下所有商品
  • 输入搜索关键词后,展示当前搜索到相关的所有商品

在这两类中展示的商品列表数据,除了数据来源不同以外,其他元素基本都保持一致,那么我们是否可以使用统一的接口来根据参数实现隔离呢? 理论上不存在问题,完全可以通过传参判断的方式进行数据回传,但是,在我们实现一些可预见的功能需求时,一定要给自己的开发预留后路,也就是我们常说的可拓展性,基于此,我们会分开实现各自的接口,以便于后期的扩展。 接着来分析在列表页中我们需要展示的元素,首先因为需要分上述两种情况,因此我们需要在我们API设计的时候分别处理,针对于 1.分类的商品列表展示,需要传入的参数有:

  • 分类id
  • 排序(在电商列表我们常见的几种排序(销量,价格等等))
  • 分页相关(因为我们不可能把数据库中所有的商品都取出来)
    • PageNumber(当前第几页)
    • PageSize(每页显示多少条数据)

2.关键词查询商品列表,需要传入的参数有:

  • 关键词
  • 排序(在电商列表我们常见的几种排序(销量,价格等等))
  • 分页相关(因为我们不可能把数据库中所有的商品都取出来)
    • PageNumber(当前第几页)
    • PageSize(每页显示多少条数据)

需要在页面展示的信息有:

  • 商品id(用于跳转商品详情使用)
  • 商品名称
  • 商品价格
  • 商品销量
  • 商品图片
  • 商品优惠
  • ...

编码实现

根据上面我们的分析,接下来开始我们的编码:

根据商品分类查询

根据我们的分析,肯定不会在一张表中把所有数据获取全,因此我们需要进行多表联查,故我们需要在自定义mapper中实现我们的功能查询.

ResponseDTO 实现

根据我们前面分析的前端需要展示的信息,我们来定义一个用于展示这些信息的对象com.liferunner.dto.SearchProductDTO,代码如下:

Custom Mapper 实现

com.liferunner.custom.ProductCustomMapper.java中新增一个方法接口:

同时,在mapper/custom/ProductCustomMapper.xml中实现我们的查询方法:

主要来说明一下这里的<choose>模块,以及为什么不使用if标签。 在有的时候,我们并不希望所有的条件都同时生效,而只是想从多个选项中选择一个,但是在使用IF标签时,只要test中的表达式为 true,就会执行IF 标签中的条件。MyBatis 提供了 choose 元素。IF标签是与(and)的关系,而 choose 是或(or)的关系。 它的选择是按照顺序自上而下,一旦有任何一个满足条件,则选择退出。

Service 实现

然后在servicecom.liferunner.service.IProductService中添加方法接口:

在实现类com.liferunner.service.impl.ProductServiceImpl中,实现上述方法:

在这里,我们使用到了一个mybatis-pagehelper插件,会在下面的福利讲解中分解。

Controller 实现

继续在com.liferunner.api.controller.ProductController中添加对外暴露的接口API:

因为我们的请求中,只会要求商品分类id是必填项,其余的调用方都可以不提供,但是如果不提供的话,我们系统就需要给定一些默认的参数来保证我们的系统正常稳定的运行,因此,我定义了com.liferunner.api.controller.BaseController,用于存储一些公共的配置信息。

Test API

测试的参数分别是:categoryId : 51 ,sortby : price,pageNumber : 1,pageSize : 5

根据分类id查询
根据分类id查询

可以看到,我们查询到7条数据,总页数totalPage为2,并且根据价格从小到大进行了排序,证明我们的编码是正确的。接下来,通过相同的代码逻辑,我们继续实现根据搜索关键词进行查询。

根据关键词查询

Response DTO 实现

使用上面实现的com.liferunner.dto.SearchProductDTO.

Custom Mapper 实现

com.liferunner.custom.ProductCustomMapper中新增方法:

mapper/custom/ProductCustomMapper.xml中添加查询SQL:

Service 实现

com.liferunner.service.IProductService中新增查询接口:

com.liferunner.service.impl.ProductServiceImpl实现上述接口方法:

上述方法和之前searchProductList(Integer categoryId, String sortby, Integer pageNumber, Integer pageSize)唯一的区别就是它是肯定搜索关键词来进行数据查询,使用重载的目的是为了我们后续不同类型的业务扩展而考虑的。

Controller 实现

com.liferunner.api.controller.ProductController中添加关键词搜索API:

Test API

测试参数:keyword : 西凤,sortby : sell,pageNumber : 1,pageSize : 10

测试关键词结果
测试关键词结果

根据销量排序正常,查询关键词正常,总条数32,每页10条,总共3页正常。

福利讲解

在本节编码实现中,我们使用到了一个通用的mybatis分页插件mybatis-pagehelper,接下来,我们来了解一下这个插件的基本情况。

mybatis-pagehelper

如果各位小伙伴使用过:MyBatis 分页插件 PageHelper, 那么对于这个就很容易理解了,它其实就是基于Executor 拦截器来实现的,当拦截到原始SQL之后,对SQL进行一次改造处理。 我们来看看我们自己代码中的实现,根据springboot编码三部曲:

1.添加依赖

有同学就要问了,为什么引入的这个依赖和我原来使用的不同?以前使用的是:

答案就在这里:依赖传送门

spring-boot-pagehelper
spring-boot-pagehelper

我们使用的是springboot进行的项目开发,既然使用的是springboot,那我们完全可以用到它的自动装配特性,作者帮我们实现了这么一个自动装配的jar,我们只需要参考示例来编写就ok了。

2.改配置

3.改代码

如下示例代码:

在我们查询数据库之前,我们引入了一句PageHelper.startPage(pageNumber, pageSize);,告诉mybatis我们要对查询进行分页处理,这个时候插件会启动一个拦截器com.github.pagehelper.PageInterceptor,针对所有的query进行拦截,添加自定义参数和添加查询数据总数。(后续我们会打印sql来证明。)

当查询到结果之后,我们需要将我们查询到的结果通知给插件,也就是PageInfo<?> pageInfo = new PageInfo<>(searchProductDTOS);com.github.pagehelper.PageInfo是对插件针对分页做的一个属性包装,具体可以查看属性传送门)。

至此,我们的插件使用就已经结束了。但是为什么我们在后面又封装了一个对象来对外进行返回,而不是使用查询到的PageInfo呢?这是因为我们实际开发过程中,为了数据结构的一致性做的一次结构封装,你也可不实现该步骤,都是对结果没有任何影响的。

SQL打印对比

我们可以看到,我们的SQL中多了一个SELECT count(0),第二条SQL多了一个LIMIT参数,在代码中,我们很明确的知道,我们并没有显示的去搜索总数和查询条数,可以确定它就是插件帮我们实现的。

源码下载

Github 传送门 Gitee 传送门

下节预告

下一节我们将继续开发商品详情展示以及商品评价业务,在过程中使用到的任何开发组件,我都会通过专门的一节来进行介绍的,兄弟们末慌!

gogogo!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 上文回顾
  • 需求分析
  • 首页商品列表|IndexProductList
    • 开发梳理
      • 编码实现
        • 根据一级分类查询
    • 商品列表|ProductList
      • 开发梳理
        • 编码实现
          • 根据商品分类查询
          • 根据关键词查询
      • 福利讲解
        • mybatis-pagehelper
          • SQL打印对比
          • 源码下载
          • 下节预告
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档