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

1. 实现思路

先查出一级目录 -> 查出子目录,一直到查到的是null (由外向内查找)

文档要求
Alt

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<CategoryVo> subCategories;
}

1.2 显示所有的根目录类别数据

ICategoryService.java

public interface ICategoryService {
	ResponseVo<List<CategoryVo>> selectAll();
}

CategoryServiceImpl.java

@Service
public class CategoryServiceImpl implements ICategoryService {

	@Autowired
	private CategoryMapper categoryMapper;

	@Override
	public ResponseVo<List<CategoryVo>> selectAll() {
		// 返回给前端的列表信息
		List<CategoryVo> categoryVoList = new ArrayList<>();
		// 一次性查找出所有的类别信息
		List<Category> 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<List<CategoryVo>> selectAll() {
		List<Category> categories = categoryMapper.selectAll();
		// stream + lambda
		List<CategoryVo> 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<List<CategoryVo>> selectAll() {
		return categoryService.selectAll();
	}
}

结果显示
在这里插入图片描述

1.3 显示二级目录类别数据

以下注释中的内容都是针对只单纯显示二级目录而言

CategoryServiceImpl.java

@Service
public class CategoryServiceImpl implements ICategoryService {

	@Autowired
	private CategoryMapper categoryMapper;

	@Override
	public ResponseVo<List<CategoryVo>> selectAll() {
		List<Category> categories = categoryMapper.selectAll();
		// stream + lambda
		List<CategoryVo> 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<CategoryVo> categoryVoList, List<Category> categoryList) {
	// 遍历所有根目录
	for (CategoryVo categoryVo : categoryVoList) {
		// 创建一个子类别前端类别列表,在每一次迭代的时候就创建一个
		List<CategoryVo> 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;
}

结果显示
Alt

1.4 显示所有的类别数据

在findSubCategory最后再加入findSubCategory方法即可,注意第一个参数的不同

CategoryServiceImpl.java

private void findSubCategory(List<CategoryVo> categoryVoList, List<Category> categoryList) {
		for (CategoryVo categoryVo : categoryVoList) {
			List<CategoryVo> 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<CategoryVo> 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<CategoryVo> categoryVoList, List<Category> categoryList) {
		for (CategoryVo categoryVo : categoryVoList) {
			List<CategoryVo> 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
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值