【项目实战】 ---- 实现商品无限级分类显示
目录
- 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方法CategoryServiceImpl.java
在查找子目录方法中的最后添加subCategoryVoList.sort()进行排序
// 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
}
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长