
分析requestURL,首先提交的路径是/spu/page/,后面加着四个参数 分别是page(第几页) key (默认是第一页) rows 显示几行(默认是五行数据) key() saleable 上架情况 默认是false 以及key key中主要是带着以上的那些值信息
然后看表的结构
首先需要清除两个关键词就是SKU 和 SPU
SPU = Standard Product Unit (标准产品单位)SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
在商品信息电子化过程中,商品的特性可以由多个“属性|属性值对”进行描述。“属性|属性值对”完全相同的商品,可以抽象成为一个SPU。
另一方面,这些“属性|属性值对”在SPU中固化下来,逐步标准化。
基于SPU的商品信息结构,可以实现丰富的应用,比如商品信息与资讯、评论、以及其它SPU的整合。
例如:iPhone X 可以确定一个产品即为一个SPU。
SKU=Stock Keeping Unit(库存量单位)。
针对电商而言:
1、SKU是指一款商品,每款都有出现一个SKU,便于电商品牌识别商品。
2、一款商品多色,则是有多个SKU,例:一件衣服,有红色、白色、蓝色,则SKU编码也不相同,如相同则会出现混淆,发错货。
例如:iPhone X 64G 银色 则是一个SKU。
总的来说就是一件商品对应一个spu
具体的商品的具体的规格颜色型号各对应一个唯一的sku
看下数据库


可以看到spu是手机的型号 但是sku就更加细了 是spu的子集
创建相应的pojo
package com.leyou.item.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
@Table(name = "tb_spu")
@Data
public class Spu {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long brandId;
private Long cid1;// 1级类目
private Long cid2;// 2级类目
private Long cid3;// 3级类目
private String title;// 标题
private String subTitle;// 子标题
private Boolean saleable;// 是否上架
@JsonIgnore
private Boolean valid;// 是否有效,逻辑删除用
private Date createTime;// 创建时间
@JsonIgnore//返回页面时忽略此字段
private Date lastUpdateTime;// 最后修改时间
@Transient
private String cname;
@Transient
private String bname;
// 省略getter和setter
}
package com.leyou.item.pojo;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name="tb_spu_detail")
@Data
public class SpuDetail {
@Id
private Long spuId;// 对应的SPU的id
private String description;// 商品描述
private String specTemplate;// 商品特殊规格的名称及可选值模板
private String specifications;// 商品的全局规格属性
private String packingList;// 包装清单
private String afterService;// 售后服务
// 省略getter和setter
}
创建mapper
package com.leyou.item.mapper;
import com.leyou.item.pojo.Spu;
import tk.mybatis.mapper.common.Mapper;
/**
* @Author: Pandy
* @Date: 2019/3/22 12:17
* @Version 1.0
*/
public interface SpuMapper extends Mapper<Spu> {
}
package com.leyou.item.mapper;
import com.leyou.item.pojo.SpuDetail;
import tk.mybatis.mapper.common.Mapper;
/**
* @Author: Pandy
* @Date: 2019/3/22 12:17
* @Version 1.0
*/
public interface SpuDetailMapper extends Mapper<SpuDetail> {
}
controller
package com.leyou.item.web;
import com.leyou.common.vo.PageResult;
import com.leyou.item.pojo.Spu;
import com.leyou.item.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.xml.ws.Response;
/**
* @Author: Pandy
* @Date: 2019/3/22 12:19
* @Version 1.0
*/
@RestController
public class GoodsController {
@Autowired
private GoodsService goodsService;
/**
* 分页查询Spu
* @param page
* @param rows
* @param saleable
* @param key
* @return
*/
@GetMapping("/spu/page")
public ResponseEntity<PageResult<Spu>> querySpuByPage(
@RequestParam(value = "page",defaultValue = "1") Integer page,
@RequestParam(value = "rows",defaultValue = "5") Integer rows,
@RequestParam(value = "saleable",required = false) Boolean saleable,
@RequestParam(value = "key",required = false) String key
){
return ResponseEntity.ok(goodsService.querySpuByPage(page,rows,saleable,key));
}
}
注意controller中传递过来的字段
并且我们直接在返回体中调用相应的方法
ResponseEntity :标识整个http相应:状态码、头部信息、响应体内容(spring)
@ResponseBody:加在请求处理方法上,能够处理方法结果值作为http响应体(springmvc)
@ResponseStatus:加在方法上、返回自定义http状态码(spring)
service是最难写 也是最重要的
package com.leyou.item.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.enums.ExceptionEnums;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.pojo.Category;
import com.leyou.item.pojo.Spu;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author: Pandy
* @Date: 2019/3/22 12:18
* @Version 1.0
*/
@Service
public class GoodsService {
@Autowired
private SpuMapper spuMapper;
@Autowired
private CategoryService categoryService;
@Autowired
private BrandService brandService;
@Autowired
private SpuDetailMapper spuDetailMapper;
public PageResult<Spu> querySpuByPage(Integer page, Integer rows, Boolean saleable, String key) {
//分页
PageHelper.startPage(page,rows);
//过滤
Example example = new Example(Spu.class);
Example.Criteria criteria = example.createCriteria();
//搜索字段过滤
if (StringUtils.isNotBlank(key)){
criteria.andLike("title","%"+key+"%");
}
//上下架过滤
if(saleable != null){
criteria.andEqualTo("saleable",saleable);
}
//排序
example.setOrderByClause("last_update_time DESC");
//查询
List<Spu> spus = spuMapper.selectByExample(example);
//判断
if (CollectionUtils.isEmpty(spus)){
throw new LyException(ExceptionEnums.PRODUCT_NOT_FOUND);
}
//解析分类和品牌的名称
loadCategoryAndBrandName(spus);
//解析分页的结果
PageInfo<Spu> info = new PageInfo<>(spus);
return new PageResult<>(info.getTotal(),spus);
}
private void loadCategoryAndBrandName(List<Spu> spus) {
for (Spu spu:spus){
//处理分类名称
List<String> names = categoryService.queryByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()))
.stream().map(Category::getName).collect(Collectors.toList());
//reduce((s,s2)->s+s2);也可以进行拼接
spu.setCname(StringUtils.join(names,"/"));//集合拼成字符串
//处理品牌名称
spu.setBname(brandService.queryById(spu.getBrandId()).getName());
}
}
}
需要在brandService中加入方法
public Brand queryById(Long id){
Brand brand = brandMapper.selectByPrimaryKey(id);
if (brand == null){
throw new LyException(ExceptionEnums.BRAND_NOT_FOUND);
}
return brand;
}
在 category中加入查询多个id的方法
public List<Category> queryByIds(List<Long> ids){
List<Category> categories = categoryMapper.selectByIdList(ids);
if (CollectionUtils.isEmpty(categories)){
throw new LyException(ExceptionEnums.CATEGORY_NOT_FOUND);
}
return categories;
}
注意上面的mapper文件实现的接口
注意在GoodsController中进行的拼接 使用列表 然后使用String的工具类进行相关的拼接完成
将界面上的所有操作都实现了 我们其实遵循前后端分离的思想向前台传递数据与指令 也就是数据和上面的四个值而已 前台会自动进行处理
最终页面正常显示 功能正常

网友评论