码迷,mamicode.com
首页 > Web开发 > 详细

jsp 树形结构

时间:2020-03-01 00:51:21      阅读:84      评论:0      收藏:0      [点我收藏+]

标签: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>

页面效果:

技术图片

 

jsp 树形结构

标签:parentId   tac   color   depend   boolean   type   templates   map   lse   

原文地址:https://www.cnblogs.com/yscec/p/12386835.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!