从0开始 独立完成企业级从0开始 独立完成企业级Java电商网站开发(服务端)笔记-后台分类模块功能

主要用于管理后台添加商品分类使用。

controller-backend-****Controller

后台分类功能模块:

获取节点

增加节点

修改名字

获取分类ID

递归子节点ID

...

学习目标:

◆如何设计及封装无限层级的树状数据结构-数据设计

◆递归算法的设计思想

◆如何处理复杂对象排重

◆重写hashcode和equal以及重写注意事项

数据表设计:

/**

* 管理后台-商品分类管理

* 1.新增分类

* 2.更新分类名称

* 3.查询分类(同级)

* 4.查询分类及其分类下的其他子分类(遍历所有子节点-子节点-...)

* 以上操作都必须在登录状态下进行

*/

1.增加分类节点

需要从session中判断用户是否登录(因为是后台,这里用户都是管理者),若未登录则返回强制登录。

前台传递传输:

categoryName-分类名

parentId-所属节点层级,若前台未传,则默认是根节点-0(Controller在接收参数时可通过@RequestParam(value="parentId",defaultValue=0))

逻辑点:

为了数据的安全,需要去校验当前操作的用户是否是管理员,防止用户权限横向越权。

2.更新分类节点名称

3.获取当前分类节点下的信息(平级子节点不递归)

请求参数:CategoryId-请求参数不传则通过@RequestParam将值置位默认的0,即查询跟节点下的平级子节点(查询当前节点下所有的子节点,其实就是查询其他数据的parent_id,这个字段指定了他的上级节点)

如果返回的查询结果集为空,我们是不需要返回给前端,可以让查询为空的结果的消息记录打印到日志里面里面去

private Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class)

日志使用:logger.info("未找到到当前分类的子分类")

4.获取当前分类节点id,并且递归查询子节点id(递归查询所有的子孙节点)

如当前分类节点是0,该节点下有两个子节点0001和0002,其中0001节点自己本身还有0001001和0001010两个子节点。那么逻辑是如果查询节点0001就要返回该0001001和00011010两个子节点;如果查询节点0,就要返回0001节点和0002节点(子节点)以及0001节点下的0001001、0001010节点(孙子节点)

》拿一个categoryId去查询他的子节点,同时判断子节点下是否还有子节点。

逻辑:

a-获取前端传递而来的分类id-categoryId

b-取数据表匹对当前id是否有数据。如果有数据将当前id查询到的数据记录到Set集合中,同时将该id作为查询子节点parentId的参数;

c-上一步拿到的id去数据表中比对字段parentId是否有数据(parentId是数据表中用于跟踪所属上级分类的字段,通过它就可以一层层往上找)

d-如果有数据,就需要循环拿出查询到的数据,并调用自己,一方面是将查询到的数据记录Set集合中,另一方那个面是新拿到的id去看看这个分类id它是不是也有下属数据。

e-依次循环,直到数据查询完毕

通过set类对int类型的数据去重,要重写hashCode和equals()方法,(Set对String类型的去重较好,因为它本身进行了hashCode和equal()重写)

在实体了Pojo中对要排重的变量,重写hashCode()和equals()方法(Generate equal and hashCode())

Tips:在项目中如要用Set集合去比对重复,最好要hashCode和equal()一起重写,保证里面的判断银子是一样的。

实现:返回的是分类id

// 查询本节点的id及孩子节点的id
    public ServerResponse<List<Integer>> selectCategoryAndChildrenById(Integer categoryId){
        Set<Category> categorySet = Sets.newHashSet();  //初始化Set集合(guava包)
        findChildCategory(categorySet,categoryId);// 递归查询节点下的节点-categorySet用于存放结果
        List<Integer> categoryIdList = Lists.newArrayList(); //初始化结果序列,该序列用于保存最后的id
        if(categoryId != null){
            for(Category categoryItem : categorySet){  
			//foreach-循环取出categorySet中存放了值,这个值可能是多层的所以要递归取出
                categoryIdList.add(categoryItem.getId()); // 添加到list结果序列中,用于返回
            }
        }
        return ServerResponse.createBySuccess(categoryIdList);
    }
//递归算法,算出子节点--Set<Category> categorySet 这个是参数也是一个返回集合 ,Integer categoryId-参数
    private Set<Category> findChildCategory(Set<Category> categorySet ,Integer categoryId){
        Category category = categoryMapper.selectByPrimaryKey(categoryId);
		//数据库查询所有的categoryId的数据,注意这里拿的所有的id-即父亲节点
        if(category != null){
            categorySet.add(category);  //结果放入Set集合中,用于下一步的递归取出
        }
        //这里的categoryId是传入数据库和表中的联系所属父亲节点的parentId查询,取当前父节点所有的子节点,如此循环就会得到一些重复的父节点,因此需要Set去重
        List<Category> categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId);
        //查找子节点,递归算法一定要有一个退出的条件,Mybatis不会返回空集,如果用其他的框架要注意空集判断
		for(Category categoryItem : categoryList){
			//取出selectCategoryChildrenByParentId查询到的子节点的id,再递归调用自己,一方面将结果记录set中,另一方面再往下查询该id下的子节点
            findChildCategory(categorySet,categoryItem.getId());
        }
        return categorySet;
    }

接口:

@RequestMapping(value = "get_deep_category.do",method = RequestMethod.GET)
@ResponseBody
public ServerResponse getCategoryParentAndChildren(String categoryId,HttpSession session){
    if ( categoryId ==null){
        return ServerResponse.createByErrorMsg("请求参数不能为空");
    }
    User user = (User)session.getAttribute(Const.CURRENT_USER);
    if (user==null){
        return ServerResponse.createByErrorCodeMsg(ResponseCode.NEED_LOGIN.getCode(),"请登录后在操作");
    }
    if (user.getRole().equals(Const.CUSTOMER)){
        return ServerResponse.createByErrorMsg("当前用户无操作权限");
    }
    return  iCategoryService.getCategoryParentAndChildren(Integer.parseInt(categoryId));
}
发布了64 篇原创文章 · 获赞 110 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/godot06/article/details/104678603