Java转树形结构案例(菜单管理)

2018-05-31  本文已影响0人  LeonardoEzio

实体类(一) 映射数据库

@Entity
@Table
public class SysMenu  {

    private Long id;

     /** 菜单名称 */
    @NotBlank(message="菜单名称不能为空")
    private String name;

    /** 菜单URL */
    @NotBlank(message="菜单url不能为空")
     private String url;

    /** 父菜单ID */
    private Long parentId;

    /** 是否可见(0:否,1:是) */
    private Integer displayFlag;
}

实体类(二) 转换结构使用

public class SysMenuVO {

    private Long Id;

    /** 菜单名称 */
    private String name;

    /** 菜单URL */
    private String url;

    /** 父菜单ID */
    private Long parentId;

    /** 是否可见(0:否,1:是) */
    private Integer displayFlag;

    private List<SysMenuVO> childMenus;
}

Controller层

@Controller
@RequestMapping("sys/menu")
public class SystemMenuController extends BaseController {

private Logger logger = LoggerFactory.getLogger(ContractArchiveController.class);

@Autowired
private SystemMenuService systemMenuService;

    @RequestMapping("findAll")
    @ResponseBody
    public ResultBean<List<SysMenuVO>> findAllMenu(){
        List<SysMenuVO> allMenu = systemMenuService.findAllMenu();
        ResultBean<List<SysMenuVO>> menuResult = new ResultBean<>(allMenu);
        menuResult.setCode(ResultBean.SUCCESS);
        menuResult.setMessages("all menu return successful");
        return menuResult;
    }
}

Service层

@Service
public class SystemMenuService {

    @Autowired
    private SystemMenuRepository systemMenuRepository;

    //获取所有菜单
    public List<SysMenuVO> findAllMenu(){
        return this.getMenusFromDb();
    }

    private List<SysMenuVO> getMenusFromDb(){
        SysMenu searchStandard = new SysMenu();
        //这里采用SpringDataJpa的Specification查询,不懂的可以百度
        Specification<SysMenu> specification = getSpecification(searchStandard);
        //按父级菜单的id排序获取查询结果集
        Sort orders = new Sort(Sort.Direction.ASC,"parentId");
        List<SysMenu> resultMenu =(List<SysMenu>)systemMenuRepository.findAll(specification,orders);
        //获取树形结构的结果
        List<SysMenuVO> menuTree = genMenuTree(resultMenu);
        return menuTree;
    }

    private Specification<SysMenu> getSpecification(SysMenu sysMenu){
        Specification<SysMenu> specification = new Specification<SysMenu>() {
             @Override
            public Predicate toPredicate(Root<SysMenu> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                //只获取没有删除的菜单
                predicates.add(cb.equal(root.<String>get("delFlag"), Constants.DEL_FLAG_ZERO));
                if(null != sysMenu.getParentId()) {
                    predicates.add(cb.equal(root.<Long>get("parentId"), sysMenu.getParentId()));
                }
                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
        return specification;
    }

    private List<SysMenuVO> genMenuTree(List<SysMenu> sysMenus) {
        //将数据转成树形结构
        Map<Long, List<SysMenuVO>> menuMap = new HashMap<>();
        for(SysMenu menu : sysMenus) {
            Long parentId = menu.getParentId();
            List<SysMenuVO> tmpList = menuMap.get(parentId) == null ? new ArrayList<SysMenuVO>() : menuMap.get(parentId);
            SysMenuVO vo = new SysMenuVO();
            BeanUtils.copyProperties(menu, vo);
            tmpList.add(vo);
            menuMap.put(parentId, tmpList);
        }
        //设置一个根节点
        SysMenuVO vo = new SysMenuVO();
        vo.setId(Constants.ROOT_MENU_PARENT_ID);
        this.setMenuChidren(vo, menuMap);
        return vo.getChildMenus();
    }

    private void setMenuChidren(SysMenuVO sysMenuVO, Map<Long,List<SysMenuVO>> menuMap) {
        //获取根节点下面子菜单集合
        List<SysMenuVO> childMenus = menuMap.get(sysMenuVO.getId());
        if(CollectionUtils.isNotEmpty(childMenus)) {
            //将子菜单集合set进根菜单
            sysMenuVO.setChildMenus(childMenus);
            for(SysMenuVO vo : childMenus) {
                //设置每一个子菜单下的子菜单集合
                setMenuChidren(vo, menuMap);
            }
        }
    }
}

注:

本例使用SpringDataJpa 和 Hibernate 仅供自己学习使用

上一篇下一篇

猜你喜欢

热点阅读