一般在进行数据库查询操作时,查询出来的都是二维数据,都是一条条数据,而对于树形结构展示时并不是很方便,那如何直接将树形结构以递归形式的方式组合成Json字符串呢?话不多说,直接上代码。
/**
* Copyright (C), 2019, XXXXXX有限公司
* FileName: MenuServiceImpl
* Author: Allen
* Date: 2019/5/30
* Description: 菜单服务处理类
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.xueying.seeker.core.service.impl.system;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xueying.seeker.client.dto.MenuDTO;
import com.xueying.seeker.client.dto.MenuTreeDTO;
import com.xueying.seeker.client.query.MenuFindQuery;
import com.xueying.seeker.client.query.MenuQuery;
import com.xueying.seeker.common.util.SimpleConverter;
import com.xueying.seeker.core.dao.MenuDAO;
import com.xueying.seeker.core.entity.MenuDO;
import com.xueying.seeker.core.entity.RoleMenuDO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 〈菜单服务处理类〉
*
* @author Allen
* @date 2019/5/30
* @since 1.0.0
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuDAO, MenuDO> {
/**
* 注入角色菜单
*/
@Autowired
private RoleMenuServiceImpl roleMenuService;
/**
* 根据用户编码查找权限范围内的菜单列表
*
* @param userId 用户编码
* @return 用户权限内的菜单列表
*/
public MenuTreeDTO selectPrivilegeMenuTreeByUserId(Long userId) {
List<MenuDO> menuDOList = baseMapper.findPrivilegeMenuByUserId(userId);
return getChildMenuTree(menuDOList);
}
/**
* 根据菜单编码查找菜单树列表
*
* @param menuFindQuery 菜单查询入参
* @return 菜单编码查找菜单树列表
*/
public MenuTreeDTO selectMenuTreeById(MenuFindQuery menuFindQuery) {
List<MenuDO> menuDOList = baseMapper.findMenuDO(menuFindQuery.getMenuId(), menuFindQuery.getDisplay(),
menuFindQuery.getPublicAttribute());
return getChildMenuTree(menuDOList);
}
/**
* 得到树形结构菜单列表
*
* @param menuDOList 数据库菜单列表
* @return 转换树形菜单列表
*/
private MenuTreeDTO getChildMenuTree(List<MenuDO> menuDOList) {
MenuTreeDTO menu = null;
if (!CollectionUtils.isEmpty(menuDOList)) {
List<MenuTreeDTO> menuTreeDTOList = SimpleConverter.convert(menuDOList, MenuTreeDTO.class);
MenuTreeDTO rootTreeMenu = getRootTreeMenu(menuTreeDTOList);
menu = setChildMenus(menuTreeDTOList, rootTreeMenu);
}
return menu;
}
/**
* 转换树形结构
*
* @param menuTreeDTOList 菜单树列表
* @return 树形结构的菜单树
*/
private MenuTreeDTO getRootTreeMenu(List<MenuTreeDTO> menuTreeDTOList) {
List<MenuTreeDTO> childList = new ArrayList<>();
Map<Long, List<MenuTreeDTO>> collectMenuTree = menuTreeDTOList.stream().collect(Collectors
.groupingBy(MenuTreeDTO::getParentMenuId));
collectMenuTree.forEach((k, v) -> {
if (v.size() == 1) {
if (v.get(0).getMenuLevel() == 1 || v.get(0).getMenuLevel() == 0) {
childList.add(v.get(0));
}
}
});
return childList.get(0);
}
/**
* 转换树形结构
*
* @param menuTreeDTOList 菜单树列表数据
* @param menuTreeDTO 节点树形目录
* @return 树形结构
*/
private MenuTreeDTO setChildMenus(List<MenuTreeDTO> menuTreeDTOList,
MenuTreeDTO menuTreeDTO) {
List<MenuTreeDTO> menuTreeDTOS = menuTreeDTOList.stream().filter(a ->
a.getParentMenuId().equals(menuTreeDTO.getId())).collect(Collectors.toList());
menuTreeDTO.setChildMenus(menuTreeDTOS);
menuTreeDTO.getChildMenus().forEach(t -> {
setChildMenus(menuTreeDTOList, t);
});
return menuTreeDTO;
}
}
其中getChildMenuTree方法就是将树形结构转换成子父关系的Json字符串的实现逻辑,其原理主要是通过java8新特性stream来实现groupingBy分组来达到分层组成对应的Json层级的思想。