使用spring-jpa完成类目递归查询 package com.example.controller;import com.example.dao.CategoryRepository;import com.example.entity.Category;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.we
package com.example.controller; import com.example.dao.CategoryRepository; import com.example.entity.Category; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; /** * 测试类目的递归算法 * Created by skh on 2017/12/29 */ @RestController public class CategoryController { @Autowired private CategoryRepository categoryRepository; //查询所有类目 //select * from category @RequestMapping("/findAll") public List系统树结构递归findAll() { List list = categoryRepository.findAll(); return list; } //查询单个类目 //select * from category where id=#{categoryId} @RequestMapping("/findOne") public Category findOne(int categoryId) { Category category = categoryRepository.findOne(categoryId); return category; } //查询该类目下的子节点(平级) //select * from category where parentId=#{categoryId} @RequestMapping("/getChildrenParallelCategory") public List getChildrenParallelCategory(@RequestParam(defaultValue = "0") int categoryId) { List list = categoryRepository.findByParentId(categoryId); return list; } //查询该类目下所有的子节点(递归) @RequestMapping("/getCategoryAndDeepChildrenCategory") public List getCategoryAndDeepChildrenCategory(@RequestParam(defaultValue = "0") int categoryId) { List categoryList = new ArrayList<>(); categoryList = findChildCategory(categoryList, categoryId); return categoryList; } //查询该类目下所有的子节点id(递归) @RequestMapping("/getCategoryAndDeepChildrenCategoryIds") public List getCategoryAndDeepChildrenCategoryIds(@RequestParam(defaultValue = "0") int categoryId) { List categoryList = new ArrayList<>(); categoryList = findChildCategory(categoryList, categoryId); List categoryIdList = new ArrayList<>(); for (Category categoryItem : categoryList) { categoryIdList.add(categoryItem.getId()); } return categoryIdList; } //递归算法,算出子节点 private List findChildCategory(List categoryList, Integer categoryId) { Category category = categoryRepository.findOne(categoryId); if (category != null) { categoryList.add(category); } //查找子节点,递归算法一定要有一个退出的条件 List list = categoryRepository.findByParentId(categoryId); //遍历子节点列表 for (Category categoryItem : list) { findChildCategory(categoryList, categoryItem.getId()); } return categoryList; } }
package com.soyea.service; import com.google.common.base.Function; import com.google.common.collect.*; import com.soyea.dao.SysAclMapper; import com.soyea.dao.SysAclModuleMapper; import com.soyea.dao.SysDeptMapper; import com.soyea.dto.AclDto; import com.soyea.dto.AclModuleLevelDto; import com.soyea.dto.DeptLevelDTO; import com.soyea.model.SysAcl; import com.soyea.model.SysAclModule; import com.soyea.model.SysDept; import com.soyea.util.LevelUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 系统树结构 * Created by skh on 2018/1/3 */ @Service @Transactional public class SysTreeService { @Autowired private SysDeptMapper sysDeptMapper; @Autowired private SysAclModuleMapper sysAclModuleMapper; @Resource private SysCoreService sysCoreService; @Resource private SysAclMapper sysAclMapper; /** * 获取指定用户的树结构的权限列表 () * @param userId * @return */ public List userAclTree(int userId) { //获取当前用户的权限列表 ListuserAclList = sysCoreService.getUserAclList(userId); List aclDtoList = Lists.newArrayList(); for (SysAcl acl : userAclList) { //遍历权限列表,设置每个权限DTO属性. AclDto dto = AclDto.adapt(acl); dto.setHasAcl(true); dto.setChecked(true); aclDtoList.add(dto); } //将权限列表转为树结构 return aclListToTree(aclDtoList); } /** * 获取指定角色的树结构的权限列表 * @param roleId * @return */ public List roleTree(int roleId) { // 1、当前用户已分配的权限点 List userAclList = sysCoreService.getCurrentUserAclList(); // 2、当前角色分配的权限点 List roleAclList = sysCoreService.getRoleAclList(roleId); //当前用户已分配的权限点Id列表 Set userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet()); //当前角色已分配的权限点ID列表 Set roleAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet()); //获取所有权限 List allAclList = sysAclMapper.getAll(); // 3、当前系统所有权限列表 List aclDtoList = Lists.newArrayList(); for (SysAcl acl : allAclList) { //遍历所有权限,判断当前用户是否有权限操作该权限,判断当前角色是否选中该权限 AclDto dto = AclDto.adapt(acl); if (userAclIdSet.contains(acl.getId())) { dto.setHasAcl(true); } if (roleAclIdSet.contains(acl.getId())) { dto.setChecked(true); } aclDtoList.add(dto); } return aclListToTree(aclDtoList); } /** * 返回树形权限列表 * @param aclDtoList * @return */ public List aclListToTree(List aclDtoList) { if (CollectionUtils.isEmpty(aclDtoList)) { return Lists.newArrayList(); } //获取所有的权限模块的树列表 List aclModuleLevelList = aclModuleTree(); //将所有权限List根据moduleId分类, key:acl_moduleId -> value:List Multimap moduleIdAclMap = ArrayListMultimap.create(); for(AclDto acl : aclDtoList) { if (acl.getStatus() == 1) { //当权限有效才加入Map moduleIdAclMap.put(acl.getAclModuleId(), acl); } } bindAclsWithOrder(aclModuleLevelList, moduleIdAclMap); return aclModuleLevelList; } /** * 使用递归将 相应权限模块下的权限列表 绑定到 相应权限模块下 * @param aclModuleLevelList * @param moduleIdAclMap */ public void bindAclsWithOrder(List aclModuleLevelList, Multimap moduleIdAclMap) { if (CollectionUtils.isEmpty(aclModuleLevelList)) { //退出条件. return; } //遍历所有的权限模块 for (AclModuleLevelDto dto : aclModuleLevelList) { List aclDtoList = (List )moduleIdAclMap.get(dto.getId()); //获取相应权限模块下的权限列表 if (CollectionUtils.isNotEmpty(aclDtoList)) { //排序 Collections.sort(aclDtoList, aclSeqComparator); dto.setAclList(aclDtoList); } bindAclsWithOrder(dto.getAclModuleList(), moduleIdAclMap); //放在外面是因为,有可能某个权限模块下没有权限,但是它还有子权限模块 } } /** * 获取权限模块树列表 * @return */ public List aclModuleTree() { List aclModuleList = sysAclModuleMapper.getAllAclModule(); //将List ->List List dtoList = Lists.newArrayList(); for (SysAclModule aclModule : aclModuleList) { dtoList.add(AclModuleLevelDto.adapt(aclModule)); } return aclModuleListToTree(dtoList); } /** * 将权限模块DTO列表转化为树列表 * @param dtoList * @return */ public List aclModuleListToTree(List dtoList) { if (CollectionUtils.isEmpty(dtoList)) { return Lists.newArrayList(); } // level -> [aclmodule1, aclmodule2, ...] Map > Multimap levelAclModuleMap = ArrayListMultimap.create(); List rootList = Lists.newArrayList(); for (AclModuleLevelDto dto : dtoList) { levelAclModuleMap.put(dto.getLevel(), dto); if (LevelUtil.ROOT.equals(dto.getLevel())) { rootList.add(dto); } } //排序 Collections.sort(rootList, aclModuleSeqComparator); transformAclModuleTree(rootList, LevelUtil.ROOT, levelAclModuleMap); return rootList; } /** * 递归权限模块树 * @param dtoList * @param level * @param levelAclModuleMap */ public void transformAclModuleTree(List dtoList, String level, Multimap levelAclModuleMap) { for (int i = 0; i < dtoList.size(); i++) { AclModuleLevelDto dto = dtoList.get(i); String nextLevel = LevelUtil.calculateLevel(level, dto.getId()); List tempList = (List ) levelAclModuleMap.get(nextLevel); if (CollectionUtils.isNotEmpty(tempList)) { //递归退出的条件. Collections.sort(tempList, aclModuleSeqComparator); dto.setAclModuleList(tempList); //设置子模块列表 transformAclModuleTree(tempList, nextLevel, levelAclModuleMap); } } } /** * 获取部门树 * * @return */ public List deptTree() { //查询所有部门 List deptList = sysDeptMapper.getAllDept(); //将deptList转换成deptDtoList List dtoList = Lists.newArrayList(); for (SysDept dept : deptList) { DeptLevelDTO dto = DeptLevelDTO.adapt(dept); dtoList.add(dto); } return deptListToTree(dtoList); } /** * 将部门列表转换为树结构 * @param deptLevelList * @return */ private List deptListToTree(List deptLevelList) { if (CollectionUtils.isEmpty(deptLevelList)) { return Lists.newArrayList(); } // level -> [DeptLevelDTO1, DeptLevelDTO2, ...] Multimap 等价于 Map > // 该map用来实现,将部门按照level来区分. Multimap levelDeptMap = ArrayListMultimap.create(); List rootList = Lists.newArrayList(); //根部门列表 //封装数据 获取levelDeptMap和rootList for (DeptLevelDTO dto : deptLevelList) { levelDeptMap.put(dto.getLevel(), dto); if (LevelUtil.ROOT.equals(dto.getLevel())) { rootList.add(dto); } } // 将跟部门列表按照seq从小到大排序 Collections.sort(rootList, deptSeqComparator); // 递归生成树 transformDeptTree(rootList, LevelUtil.ROOT, levelDeptMap); return rootList; } /** * 递归部门树 算法 * 通过level值来处理不同层级的部门 * @param deptLevelList 需要处理的数据 * @param level 当前需要处理的level值 * @param levelDeptMap 根据level值,封装好的Map */ private void transformDeptTree(List deptLevelList, String level, Multimap levelDeptMap) { //一层一层处理 先处理根部门列表 for (int i = 0; i < deptLevelList.size(); i++) { // 遍历该层的每个元素 DeptLevelDTO deptLevelDTO = deptLevelList.get(i); // 获取下一层的level String nextLevel = LevelUtil.calculateLevel(level, deptLevelDTO.getId()); // 处理下一层 获取子部门列表 List tempDeptList = (List ) levelDeptMap.get(nextLevel); if (CollectionUtils.isNotEmpty(tempDeptList)) { // 排序 Collections.sort(tempDeptList, deptSeqComparator); // 设置子部门列表 deptLevelDTO.setDeptList(tempDeptList); // 进入到下一层处理 transformDeptTree(tempDeptList, nextLevel, levelDeptMap); } } } /** * 部门比较器,根据seq排序 */ private Comparator deptSeqComparator = new Comparator () { public int compare(DeptLevelDTO o1, DeptLevelDTO o2) { return o1.getSeq() - o2.getSeq(); } }; /** * 权限模块比较器 */ public Comparator aclModuleSeqComparator = new Comparator () { public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) { return o1.getSeq() - o2.getSeq(); } }; /** * 权限比较器 */ public Comparator aclSeqComparator = new Comparator () { public int compare(AclDto o1, AclDto o2) { return o1.getSeq() - o2.getSeq(); } }; }