标签:parentId tac color depend boolean type templates map lse
package com.ytkj.rose.util; import org.springframework.util.StringUtils; import javax.validation.constraints.NotNull; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; public class TreeUtils { /** * 集合转树结构 * * @param collection 目标集合 * @param clazz 集合元素类型 * @return 转换后的树形结构 */ public static <T> Collection<T> toTree(@NotNull Collection<T> collection, @NotNull Class<T> clazz) { return toTree(collection, null, null, null, clazz); } /** * 集合转树结构 * * @param collection 目标集合 * @param id 节点编号字段名称 * @param parent 父节点编号字段名称 * @param children 子节点集合属性名称 * @param clazz 集合元素类型 * @return 转换后的树形结构 */ public static <T> Collection<T> toTree(@NotNull Collection<T> collection, String id, String parent, String children, @NotNull Class<T> clazz) { try { if (collection == null || collection.isEmpty()) return null;// 如果目标集合为空,直接返回一个空树 if (StringUtils.isEmpty(id)) id = "id"; // 如果被依赖字段名称为空则默认为id if (StringUtils.isEmpty(parent)) parent = "parent"; // 如果依赖字段为空则默认为parent if (StringUtils.isEmpty(children)) children = "children"; // 如果子节点集合属性名称为空则默认为children // 初始化根节点集合, 支持 Set 和 List Collection<T> roots; if (collection.getClass().isAssignableFrom(Set.class)) { roots = new HashSet<>(); } else { roots = new ArrayList<>(); } // 获取 id 字段, 从当前对象或其父类 Field idField; try { idField = clazz.getDeclaredField(id); } catch (NoSuchFieldException e1) { idField = clazz.getSuperclass().getDeclaredField(id); } // 获取 parentId 字段, 从当前对象或其父类 Field parentField; try { parentField = clazz.getDeclaredField(parent); } catch (NoSuchFieldException e1) { parentField = clazz.getSuperclass().getDeclaredField(parent); } // 获取 children 字段, 从当前对象或其父类 Field childrenField; try { childrenField = clazz.getDeclaredField(children); } catch (NoSuchFieldException e1) { childrenField = clazz.getSuperclass().getDeclaredField(children); } // 设置为可访问 idField.setAccessible(true); parentField.setAccessible(true); childrenField.setAccessible(true); // 找出所有的根节点 for (T c : collection) { Object parentId = parentField.get(c); if (isRootNode(parentId)) { roots.add(c); } } // 从目标集合移除所有根节点 collection.removeAll(roots); // 遍历根节点, 依次添加子节点 for (T root : roots) { addChild(root, collection, idField, parentField, childrenField); } // 关闭可访问 idField.setAccessible(false); parentField.setAccessible(false); childrenField.setAccessible(false); return roots; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 为目标节点添加孩子节点 * * @param node 目标节点 * @param collection 目标集合 * @param idField ID 字段 * @param parentField 父节点字段 * @param childrenField 字节点字段 */ private static <T> void addChild(@NotNull T node, @NotNull Collection<T> collection, @NotNull Field idField, @NotNull Field parentField, @NotNull Field childrenField) throws IllegalAccessException { Object id = idField.get(node); Collection<T> children = (Collection<T>) childrenField.get(node); // 如果子节点的集合为 null, 初始化孩子集合 if (children == null) { if (collection.getClass().isAssignableFrom(Set.class)) { children = new HashSet<>(); } else children = new ArrayList<>(); } for (T t : collection) { Object o = parentField.get(t); if (id.equals(o)) { // 将当前节点添加到目标节点的孩子节点 children.add(t); // 重设目标节点的孩子节点集合,这里必须重设,因为如果目标节点的孩子节点是null的话,这样是没有地址的,就会造成数据丢失,所以必须重设,如果目标节点所在类的孩子节点初始化为一个空集合,而不是null,则可以不需要这一步,因为java一切皆指针 childrenField.set(node, children); // 递归添加孩子节点 addChild(t, collection, idField, parentField, childrenField); } } } /** * 判断是否是根节点, 判断方式为: 父节点编号为空或为 0, 则认为是根节点. 此处的判断应根据自己的业务数据而定. * @param parentId 父节点编号 * @return 是否是根节点 */ private static boolean isRootNode(Object parentId) { boolean flag = false; if (parentId == null) { flag = true; } else if (parentId instanceof String && (StringUtils.isEmpty(parentId) || parentId.equals("0"))) { flag = true; } else if (parentId instanceof Integer && Integer.valueOf(0).equals(parentId)) { flag = true; } return flag; } }
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
bean:
package com.ytkj.rose.bean; import java.util.ArrayList; import java.util.List; public class TMenu { private Integer id; private Integer pid; private String name; private String icon; private String url; private List<TMenu> children=new ArrayList<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getPid() { return pid; } public void setPid(Integer pid) { this.pid = pid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public List<TMenu> getChildren() { return children; } public void setChildren(List<TMenu> children) { this.children = children; } @Override public String toString() { return "TMenu{" + "id=" + id + ", pid=" + pid + ", name=‘" + name + ‘\‘‘ + ", icon=‘" + icon + ‘\‘‘ + ", url=‘" + url + ‘\‘‘ + ", children=" + children + ‘}‘; } }
controller:
@RequestMapping("/main") public String main(HttpSession session) { logger.debug("跳转到主面"); List<TMenu> menuList=tMenuService.getMenuAll(); session.setAttribute("menuList",menuList); return "main"; }
service:
package com.ytkj.rose.service; import com.ytkj.rose.bean.TMenu; import java.util.List; public interface TMenuService { List<TMenu> getMenuAll(); }
serviceImpl
package com.ytkj.rose.service.impl; import com.ytkj.rose.bean.TMenu; import com.ytkj.rose.mapper.TMenuMapper; import com.ytkj.rose.service.TMenuService; import com.ytkj.rose.util.TreeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; @Service public class TMenuServiceImpl implements TMenuService { Logger logger= LoggerFactory.getLogger(TAdminServiceImpl.class); @Autowired TMenuMapper tMenuMapper; @Override public List<TMenu> getMenuAll() { List<TMenu> list = tMenuMapper.selectAll(); Collection<TMenu> tMenus = TreeUtils.toTree(list, "id", "pid", "children", TMenu.class); logger.debug("菜单={}",tMenus); return (List<TMenu>) tMenus; } }
mapper:
package com.ytkj.rose.mapper; import com.ytkj.rose.bean.TMenu; import java.util.List; public interface TMenuMapper { List<TMenu> selectAll(); }
mapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ytkj.rose.mapper.TMenuMapper"> <select id="selectAll" resultType="com.ytkj.rose.bean.TMenu" > select * from t_menu </select> </mapper>
jsp页面:
<%-- Created by IntelliJ IDEA. User: 3600X Date: 2020/2/29 Time: 14:53 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <div class="col-sm-3 col-md-2 sidebar" style="top: 52px"> <div class="tree"> <ul style="padding-left:0px;" class="list-group"> <c:forEach items="${menuList}" var="parent"> <c:if test="${empty parent.children}"> <li class="list-group-item tree-closed"> <a href="${PATH}/${parent.url}"><i class="glyphicon glyphicon-dashboard"></i>${parent.name}</a> </li> </c:if> <c:if test="${not empty parent.children}"> <li class="list-group-item tree-closed"> <span><i class="${parent.icon}"></i> ${parent.name}<span class="badge" style="float:right">${parent.children.size()}</span></span> <ul style="margin-top:10px;display:none;"> <c:forEach items="${parent.children}" var="child"> <li style="height:30px;"> <a href="${PATH}/${child.url}"><i class="glyphicon glyphicon-user"></i> ${child.name}</a> </li> </c:forEach> </ul> </li> </c:if> </c:forEach> </ul> </div> </div>
页面效果:
标签:parentId tac color depend boolean type templates map lse
原文地址:https://www.cnblogs.com/yscec/p/12386835.html