我们实现了商品模块中商品分类相关的功能,这节我们继续商品模块的开发来实现商品详细相关的功能,这些功能在我们梳理出来的功能用例中,我标记了出来。
图片
从功能用例中我们能看到与商品相关的主要功能有:
- 商品列表
- 商品搜索
- 商品详情
我们会实现商品模块的主要功能接口,在其中会实际应用一下我们在搭建项目定制化的响应组件中的Pagination,来简化分页查询相关的操作,在代码实现上也比普通的方式更优雅一些。
商品列表
接下来我们来实现商品列表功能的接口, 当然真正商用级别的购物App,商品列表应该是通过 Lucene或者是ElasticSearch来实现的查找的。我们这里没有这个硬件条件,就先给大家讲一下通过数据库查询实现功能的逻辑吧。
在购物网站上,我们点击每个分类的时候,会展示分类下的商品列表。
这个时候有个内部逻辑,商品都是挂在到三级分类上的,也就是分类的叶子节点上。 那么此时我们开发功能时要能够兼顾下面几点:
- 产品的交互逻辑上可能允许用户点击一级或者二级分类查看商品列表。
- 因不同公司产品逻辑而定,没有绝对,但是我们的功能实现时要支持上面的情况,假设用户选择了一级或者二级分类,我们的程序需要先查出下面的三级分类,再通过这些三级分类查找对应的商品。
以上是业务方面的逻辑,在做本功能的时候我还会演示怎么通过我们之前定义分页组件Pagination,以一个相对优雅的写法写数据库的分页查询。
在 api/controller/commodity.go 中添加商品列表的Controller方法。
我们在Controller方法中除了从URL查询字符串上获取商品的分类ID外,还要获取分页相关的请求参数,用它们创建Pagination对象。Pagination 对象会随着我们的调用一直往下传递,传到DomainService中,在需要的时候通过其上的方法来获取offset 和 limit 等信息。
DomainService 中查询商品列表的逻辑如下:
commodityDao 的 GetThirdLevelCategories 方法就是我们上面说的产品逻辑,拿到一个分类信息后先去获取一下所有的三级分类。
如果分类本身就是三级分类则直接返回,否则还是按照上面说的逻辑把分类下的所有三级分类先找出来。
分页查询简化
查询商品信息时因为需要分页,所以我们在CommodityDomainSvc 里先用Pagination获取分页数据需要的offset 和 limit 参数。
商品数据查询的Dao方法除了返回商品列表数据,还会返回满足条件的总行数,这样我们把总行数再设置到Pagination对象上,因为Pagination是指针类型,它创建子Controller方法,所以我们在Controller中返回响应时直接使用 app.NewResponse(c).SetPagination(pagination) 就能把分页查询需要的信息都写入到响应中。
通过这种方式我们能避免需要分页查询数据的接口对应的AppService、DomainService、Dao方法都带上page、pageSize等参数,只需要在调用Dao方法查询数据前从Pagination对象对应的方法中取出这两个值即可。同理所有方法的返回值中也不用都带着totalRow 这个返回值。