需求一:这种不需要传任何参数
一、数据库存储的菜单结果:
parentid为0的都是根节点,也就是一级菜单,后面的子菜单的parentid为父菜单的ID。
二、MenuDTO类(菜单类)的结构:
@Date public class MenuDTO { private Integer id; private String content; private Integer parentid; private Date createtime; private Integer num; private List<MenuDTO> childs;
三、业务层:采用递归方法,遍历成树级结构菜单
//获得树级结构菜单 public List<MenuDTO> getMenuList() throws IOException { //拿到菜单的所有数据 List<MenudTO> list=menuMapper.getMenuList(); //存储根节点的菜单,即一级菜单 List<MenuDTO> rootlist=new ArrayList<>(); //遍历所有数据,找到根节点菜单 for (MenuDTO menuDTO: list) { if(menuDTO.getParentid().equals(0)){ //找到根节点菜单的时候,寻找这个根节点菜单下的子节点菜单。 findChilds(menuDTO,list); //添加到根节点的列表中 rootlist.add(menuDTO); } } return rootlist; } private void findChilds(MenuDTO root,List<MenuDTO> list){ List<MenuDTO> childlist=new ArrayList<>(); //遍历所有数据,找到是入参父节点的子节点的数据,然后加到childlist集合中。 for (MenuDTO menu : list) { if (root.getId().equals(menu.getParentid())) childlist.add(menu); } //若子节点不存在,那么就不必再遍历子节点中的子节点了 直接返回。 if(childlist.size()==0) return; //设置父节点的子节点列表 root.setChilds(childlist); //若子节点存在,接着递归调用该方法,寻找子节点的子节点。 for (MenuDTO childs : childlist) { findChilds(childs, list); } }
需求二:这种需要传任何参数,可以传多个
一、分类实体类
public class ChildNodeCategoryDto { /** * 分类ID */ private Integer catId; /** * 分类父ID */ private Integer parentId; /** * 分类名称 */ private String catName; /** * 分类级别 */ private String catLevel; /** * 分类缩略图 */ private String catThumb; /** * 子分类列表 */ List<ChildNodeCategoryDto> childCategory = new ArrayList<ChildNodeCategoryDto>();
二、业务层:采用递归方法,遍历成树级结构分类
public List<ChildNodeCategoryDto> getGoodsCategory(String ids) { List<ChildNodeCategoryDto> list = new ArrayList<ChildNodeCategoryDto>(); GoodsCategoryDto dto = new GoodsCategoryDto(); //查询所有的分类 dto.setPlatformCode("0001"); dto.setIsShow(1); List<EcsCategory> ecsCategoryList = ecsCategoryMapper.findAllByShowAndPlatformCodeOrderBySortOrder(dto); for (EcsCategory ecsCategory : ecsCategoryList) { ChildNodeCategoryDto childNodeCategory = new ChildNodeCategoryDto(); childNodeCategory.setCatId(ecsCategory.getCatId()); childNodeCategory.setParentId(ecsCategory.getParentId()); childNodeCategory.setCatName(ecsCategory.getCatName()); childNodeCategory.setCatLevel(ecsCategory.getCatCode()); childNodeCategory.setCatThumb(ecsCategory.getCatThumb()); list.add(childNodeCategory); } //查询根节点数据 List<ChildNodeCategoryDto> rootLists = new ArrayList<ChildNodeCategoryDto>(); String[] strArray = ids.split(","); for(int i = 0; i<strArray.length ;i++) { Integer catId = Integer.parseInt(strArray[i]); //先找到所有的一级菜单 for (ChildNodeCategoryDto childNodeCategoryResponse : list) { if (childNodeCategoryResponse.getCatId().equals(catId)) { rootLists.add(childNodeCategoryResponse); getChild(childNodeCategoryResponse, list); } } } } return rootLists;
private void getChild(ChildNodeCategoryDto category, List<ChildNodeCategoryDto> list) { // 存放子菜单的集合 List<ChildNodeCategoryDto> childList = new ArrayList<ChildNodeCategoryDto>(); category.setChildCategory(childList); for (ChildNodeCategoryDto childNodeCategoryResponse : list) { if (childNodeCategoryResponse.getParentId().equals(category.getCatId())) { childList.add(childNodeCategoryResponse); getChild(childNodeCategoryResponse, list); } } }
需求三:关于Java1.8递归根据父节点查询所有子节点
一、模型
@Data public class Menu { private String id; private String name; private String pid; private List<Menu> childMenu; }
二、递归获取某个父节点下面的所有子节点
/** * 递归获取某个父节点下面的所有子节点 * * @param childMenu 要返回的结果 * @param menuList 数据库查询出来的所有机构集合 * @param pid 父id * 注:本身的机构节点不会添加进去 */ private static void getParentNode(List<Menu> childMenu, List<Menu> menuList, String pid) { menuList.stream() //过滤出父id等于参数的id .filter(menu -> StringUtils.isNotBlank(menu.getPid()) && menu.getPid().equals(pid)) .forEach(menu -> { //递归遍历下一级 getParentNode(childMenu, menuList, menu.getId()); //添加 childMenu.add(menu); }); }
三、根据子节点查询所有父节点
/** * 递归获取某个子节点下面的所有父节点 * * @param childMenu 要返回的结果 * @param menuList 数据库查询出来的所有机构集合 * @param id 节点id * TODO 注:本身的机构节点会添加进去 */ private static void getChildNode(List<Menu> childMenu, List<Menu> menuList, String id) { menuList.stream() .filter(menu -> StringUtils.isNotBlank(id) && id.equals(menu.getId())) .forEach(menu -> { getChildNode(childMenu, menuList, menu.getPid()); childMenu.add(menu); }); }
四、测试
public static void main(String args[]) { List<Menu> menuList = new ArrayList<Menu>(); Menu mu = new Menu(); mu.setId("1"); mu.setName("阿里巴巴"); mu.setPid("0"); Menu mu1 = new Menu(); mu1.setId("2"); mu1.setName("开发部"); mu1.setPid("1"); Menu mu2 = new Menu(); mu2.setId("3"); mu2.setName("业务部"); mu2.setPid("2"); Menu mu3 = new Menu(); mu3.setId("4"); mu3.setName("销售部"); mu3.setPid("2"); Menu mu4 = new Menu(); mu4.setId("5"); mu4.setName("运营部"); mu4.setPid("1"); Menu mu5 = new Menu(); mu5.setId("6"); mu5.setName("采购部"); mu5.setPid("5"); Menu mu6 = new Menu(); mu6.setId("7"); mu6.setName("保卫部"); mu6.setPid("5"); Menu mu7 = new Menu(); mu7.setId("8"); mu7.setName("人事部"); mu7.setPid("7"); Menu mu8 = new Menu(); mu8.setId("9"); mu8.setName("财务部"); mu8.setPid("1"); menuList.add(mu); menuList.add(mu1); menuList.add(mu2); menuList.add(mu3); menuList.add(mu4); menuList.add(mu5); menuList.add(mu6); menuList.add(mu7); menuList.add(mu8); List<Menu> menus = new ArrayList<>(); getMenu(menus, menuList, "2"); menus.stream() .map(menu -> menu.getId() + " " + menu.getName()) .forEach(System.out::println); }
总结:
先拿到所有的菜单数据,然后遍历菜单数据,找到根节点,找到根节点。然后调用找到子节点的方法,在子节点方法中递归调用自己,
也就是说如果这个节点有子节点,那么递归调用方法找到子节点的子节点,直到某个节点下面没有子节点。