目录
数据库表:📎product.sql、📎product_detail.sql
当我们从列表中点击某个商品,进入这个商品(SPU)信息展示,然后当我们点击购买时,就会出现下面的页面
一、项目设计
1、项目背景介绍
需要提供的服务
1、需求介绍
查看商品列表
点击过后查看商品详情
“剁手”环节
2、技术方案
通过上面的功能,我们来确定下项目的技术方案:
1.商品列表需要后端分页返回数据。
2.商品支付时需要接入支付宝支付接口。
3.购买成功时需要更新商品信息(库存及购买人数),注意使用redis解决并发问题。
2、领域模型关系介绍
首先是商品展示列点击进入商品详情页
当我们选中商品付款时,这时候会产生一条某个人购买该商品的订单
记录,这时候我们再去调用支付宝的支付接口。
梳理各个模型之间的关系
二、商品模块
1、工程环境搭建
具体包
开发项目的包名为com.youkeda.dewu,模块作用如下
创建数据库,包名为dewudb
2、商品SPU/SKU模型设计
商品页面涉及两个模型(商品模型SPU、商品详情页面SKU)
两个模型的属性和关系
model包下创建模型
- Product(商品)
- ProductDetail(商品详情)
User表
数据库模型
product_intro的长度改为256,表格的初始化数据记得导入
数据库表:📎product.sql、📎product_detail.sql
3、商品数据库设计
系统提供ProductDO、ProductDetailDO
@Data
public class ProductDO {
/**
* 主键
*/
private String id;
/**
* 商品名称
*/
private String name;
/**
* 商品默认展示的价格
*/
private Double price;
/**
* 商品销量
*/
private Integer purchaseNum;
/**
* 商品介绍
*/
private String productIntro;
/**
* 商品图片
*/
private String productImgs;
/**
* 创建时间
*/
private Date gmtCreated;
/**
* 创建日期
*/
private Date gmtModified;
//实现了将Product对象转换为ProductDO对象的功能
public ProductDO(Product product) {
BeanUtils.copyProperties(product, this);
}
//将ProductDO对象转换为Product
public Product convertToModel() {
Product product = new Product();
BeanUtils.copyProperties(this, product);
return product;
}
}
@Data
public class ProductDetailDO {
/**
* 主键
*/
private String id;/**
* 关联商品
*/
private String productId;
/**
* 价格
*/
private Double price;
/**
* 尺码
*/
private Double size;
/**
* 库存
*/
private Integer stock;
/**
* 创建时间
*/
private Date gmtCreated;
/**
* 修改时间
*/
private Date gmtModified;
//将ProducDetail对象转换为ProductDetailDO对象
public ProductDetailDO(ProductDetail productDetail) {
BeanUtils.copyProperties(productDetail, this);
}
//将ProductDetailDO对象转换为ProductDetail对象
public ProductDetail convertToModel() {
ProductDetail productDetail = new ProductDetail();
BeanUtils.copyProperties(this, productDetail);
return productDetail;
}
}
4、商品列表服务
一秒钟法则,通过分页加载数据来减轻加载的数据量
现在我们需要完成前端的分页任务,前端一般会向我们传递需要请求第几页数据,和每一页数据有多少个,因此我们需要在com.youkeda.dewu下创建一个包名为param的文件夹(param包下主要是前端向后端的自定义对象),然后在param下创建一BasePageParam对象,对象属性为
当后端接受到这个参数时,我们需要查询到总数据有多少,然后计算总页数,最后再查询当前页的数据,大家可以看下mode1包下的Paging对象,下面是我们处理分页的实现逻辑
为了完成分页逻辑,设计下ProductService(在这里大家需要将Product的更新和添加基础接口写一下),大家也需要在ProductServiceImpl实现对应接口(大家可以根据需求相应的增加dao层服务,还有后面的章节中需要大家配置自己的mybatis)。
public interface ProductService {
/**
* 增加或修改商品
* @param product 商品
* @return Product
*/
int save(Product product);
/**
* 分页查询商品
* @param param 商品分页参数
* @return PagingData<Product>
*/
Paging<Product> pageQueryProduct(BasePageParam param);
}
现在我们来写下ProductApi--分页查询商品
- URL:
GET/api/product/page
- Request Param
com.youkeda.dewu.param.BasePageParam
- Response:
Result<Paging<Product>>
//定义全局路由前缀
@RequestMapping("/api/product")
@Controller
public class ProductApi {
@Resource
private ProductService productService;
@ResponseBody
@GetMapping("/page")
public Result<Paging<Product>> pageQuery(BasePageParam param) {
Result<Paging<Product>> result = new Result<>();
result.setSuccess(true);
result.setData(productService.pageQueryProduct(param)); //获取产品信息的分页查询,并将该查询结果封装到Result对象中,以便在API接口的响应中返回给前端
return result;
}
}
在商品列表中我们可以点击某个商品进入商品详情页,这时候我们需要一个查询详情的接口,如下(大家也需要实现对应的ProductServiceImpl,这里在ProductDAO中有已经有了
selectByPrimaryKey()方法大家可以利用这个接口)
public interface ProductService {
/**
* 根据主键获取商品
* @param productId 商品主键
* @return Product
*/
Product get(String productId);
}
5、商品详情服务
当我们从列表中点击某个商品,进入这个商品(SPU)信息展示,然后当我们点击购买时,就会出现下面的页面
这个页面就是查询到(SPU)关联的所有(SKU),当选择不同具体商品时,轮播图下方显示的价格也会随着变化
现在我们来设计下ProductDetailService(在这里大家需要将ProductDetaill的更新和添加基础接口写一下),大家也需要在ProductDetailServiceImpl实现对应接口(大家可以根据需求相应的增加dao层服务
public interface ProductDetailService {
/**
* 添加或者修改
* @param productDetail 产品
* @return int
*/
int save(ProductDetail productDetail);
/**
* 获取商品id获取所有商品详情
*
* @param productId 商品主键
* @return ProductDetail
*/
List<ProductDetail> getByProductId(String productId);
}
现在我们来写下ProductDetailApi
分页查询商品
- URL:
GET /api/productdetail/productId
- Request Param:
{
"productId":"productId"
}
- Response:
Result<List<ProductDetail>>