【项目实战】 ---- 实现商品无限级分类显示


目录

  • 1. 实现思路
    • 1.1 数据类型设置
    • 1.2 显示所有的根目录类别数据
    • 1.3 显示二级目录类别数据
    • 1.4 显示所有的类别数据
    • 1.5 根据sort_order字段值大小进行排序

1. 实现思路
先查出一级目录 -> 查出子目录,一直到查到的是null (由外向内查找)
文档要求
【项目实战】 ---- 实现商品无限级分类显示
文章图片

1.1 数据类型设置 根据文档要求,显示回前端的data数据包含了字段id、parentId、name、sortOrder、subCategories
vo.CategoryVo.java
@Data public class CategoryVo { private Integer id; private Integer parentId; private String name; private Integer sortOrder; private List subCategories; }

1.2 显示所有的根目录类别数据 ICategoryService.java
public interface ICategoryService { ResponseVo> selectAll(); }

CategoryServiceImpl.java
@Service public class CategoryServiceImpl implements ICategoryService { @Autowired private CategoryMapper categoryMapper; @Override public ResponseVo> selectAll() { // 返回给前端的列表信息 List categoryVoList = new ArrayList<>(); // 一次性查找出所有的类别信息 List categories = categoryMapper.selectAll(); // 查出parent_id=0 for (Category category : categories) { if(category.getParentId().equals(MallConst.ROOT_PARENT_ID)) { CategoryVo categoryVo = new CategoryVo(); // 将查到的根目录类别信息转换为categoryVo类 BeanUtils.copyProperties(category, categoryVo); categoryVoList.add(categoryVo); } } return ResponseVo.success(categoryVoList); } }

上面的写法也可以写成Lambda写法
@Service public class CategoryServiceImpl implements ICategoryService { @Autowired private CategoryMapper categoryMapper; @Override public ResponseVo> selectAll() { List categories = categoryMapper.selectAll(); // stream + lambda List categoryVoList = categories.stream() // 作用: 设置条件过滤出元素, 筛选出根目录 .filter(e -> e.getParentId().equals(ROOT_PARENT_ID)) // 作用: 映射每个元素对应的结果, 转换为categoryVo类 // 相当于.map(e -> category2CategoryVo(e)) .map(this::category2CategoryVo) // 作用: 将流转换成集合 .collect(Collectors.toList()); } return ResponseVo.success(categoryVoList); }// 将category类转换为前端显示的categoryVo类 private CategoryVo category2CategoryVo(Category category){ CategoryVo categoryVo = new CategoryVo(); // 拷贝属性值, 第一个参数source, 第二个参数target BeanUtils.copyProperties(category, categoryVo); return categoryVo; }

CategoryController.java
@RestController public class CategoryController { @Autowired private ICategoryService categoryService; @GetMapping("/categories") public ResponseVo> selectAll() { return categoryService.selectAll(); } }

结果显示
【项目实战】 ---- 实现商品无限级分类显示
文章图片

1.3 显示二级目录类别数据 以下注释中的内容都是针对只单纯显示二级目录而言
CategoryServiceImpl.java
@Service public class CategoryServiceImpl implements ICategoryService { @Autowired private CategoryMapper categoryMapper; @Override public ResponseVo> selectAll() { List categories = categoryMapper.selectAll(); // stream + lambda List categoryVoList = categories.stream() // 作用: 设置条件过滤出元素, 筛选出根目录 .filter(e -> e.getParentId().equals(ROOT_PARENT_ID)) // 作用: 映射每个元素对应的结果, 转换为categoryVo类 // 相当于.map(e -> category2CategoryVo(e)) .map(this::category2CategoryVo) // 作用: 将流转换成集合 .collect(Collectors.toList()); } // 查询子目录 findSubCategory(categoryVoList, categories); return ResponseVo.success(categoryVoList); }// 查找子目录, 第一个参数: 包含了所有了根目录的列表, 第二个参数: 所有的商品类别信息 private void findSubCategory(List categoryVoList, List categoryList) { // 遍历所有根目录 for (CategoryVo categoryVo : categoryVoList) { // 创建一个子类别前端类别列表,在每一次迭代的时候就创建一个 List subCategoryVoList = new ArrayList<>(); // 遍历所有的商品类别,查找子目录 for (Category category : categoryList) { // 判断条件为: 根目录Id等于商品父类别值,就添加到subCategoryVoList中 if(categoryVo.getId().equals(category.getParentId())) { CategoryVo subCategoryVo = category2CategoryVo(category); subCategoryVoList.add(subCategoryVo); } } // 每一个根目录的商品类别设置属性值subCategoryList categoryVo.setSubCategories(subCategoryVoList); } }// 将category类转换为前端显示的categoryVo类 private CategoryVo category2CategoryVo(Category category){ CategoryVo categoryVo = new CategoryVo(); // 拷贝属性值, 第一个参数source, 第二个参数target BeanUtils.copyProperties(category, categoryVo); return categoryVo; }

结果显示
【项目实战】 ---- 实现商品无限级分类显示
文章图片

1.4 显示所有的类别数据
在findSubCategory最后再加入findSubCategory方法即可,注意第一个参数的不同
【【项目实战】 ---- 实现商品无限级分类显示】CategoryServiceImpl.java
private void findSubCategory(List categoryVoList, List categoryList) { for (CategoryVo categoryVo : categoryVoList) { List subCategoryVoList = new ArrayList<>(); for (Category category : categoryList) { if(categoryVo.getId().equals(category.getParentId())) { CategoryVo subCategoryVo = category2CategoryVo(category); subCategoryVoList.add(subCategoryVo); } } // 注意传入的第一个参数为子类别列表参数,第二个参数仍然为所有商品类别 findSubCategory(subCategoryVoList, categoryList); categoryVo.setSubCategories(subCategoryVoList); } }

结果显示
【项目实战】 ---- 实现商品无限级分类显示
文章图片

1.5 根据sort_order字段值大小进行排序
对根目录的Lambda进行改写,添加sorted方法
在查找子目录方法中的最后添加subCategoryVoList.sort()进行排序
CategoryServiceImpl.java
// stream + lambda List categoryVoList = categories.stream() // 作用: 设置条件过滤出元素, 筛选出根目录 .filter(e -> e.getParentId().equals(ROOT_PARENT_ID)) // 作用: 映射每个元素对应的结果, 转换为categoryVo类 // 相当于.map(e -> category2CategoryVo(e)) .map(this::category2CategoryVo) // 作用: 对sortOrder字段进行从大到小排序 .sorted(Comparator.comparing(CategoryVo::getSortOrder).reversed()) // 作用: 将流转换成集合 .collect(Collectors.toList()); private void findSubCategory(List categoryVoList, List categoryList) { for (CategoryVo categoryVo : categoryVoList) { List subCategoryVoList = new ArrayList<>(); for (Category category : categoryList) { if(categoryVo.getId().equals(category.getParentId())) { CategoryVo subCategoryVo = category2CategoryVo(category); subCategoryVoList.add(subCategoryVo); } } // 注意传入的第一个参数为子类别列表参数,第二个参数仍然为所有商品类别 findSubCategory(subCategoryVoList, categoryList); // 注意这里只是 子目录进行了字段排序,根目录同样也需要写此代码进行排序 // categoryVo1 -> categoryVo1.getSortOrder() 按sortOrder字段从小到大排序,所以最后需要加个reverse subCategoryVoList.sort(Comparator.comparing(CategoryVo::getSortOrder).reversed()); categoryVo.setSubCategories(subCategoryVoList); } }

结果显示
【项目实战】 ---- 实现商品无限级分类显示
文章图片

补充
/**
* 耗时: http(请求微信api) > 磁盘 > 内存
* mysql(内网 + 磁盘)
* @return
*/
// 耗时操作
for (Category category : categories) {
// http网络请求
// sql
}

    推荐阅读