El menú del árbol general de Java devuelve la clase de herramienta TreeMenuUtil

Este artículo ha participado en el evento "Ceremonia de creación de recién llegados" para comenzar juntos el camino de la creación de oro.

1. Clase de entidad

submenú de childrenalmacenamiento

import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author eleven
 * @date 2022/4/12 16:39
 * @apiNote 系统字典表
 */
@Data
public class SysDict {
    @TableId(type = IdType.AUTO)
    @ExcelProperty("id")
    private Integer id;
    @ExcelProperty("父级id")
    private Integer parentId;
    @ExcelProperty("名称")
    private String name;
    @ExcelProperty("值")
    private String value;
    @ExcelProperty("编码")
    private String dictCode;

    @JsonFormat(timezone = "Asia/ShangHai",pattern = "yyy-MM-dd HH:mm:ss" )
    @DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    private String createBy;

    @JsonFormat(timezone = "Asia/ShangHai",pattern = "yyy-MM-dd HH:mm:ss" )
    @DateTimeFormat(pattern = "yyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    private String updateBy;

    private Integer delFlag;
    @TableField(exist = false)
    private List<SysDict> children;
}

复制代码

2. Escriba el método para volver al menú de árbol

public class SysDictTreeTest{
    public List<SysDict> getAllList() {
        //从数据库中获取数据
        List<SysDict> sysDictList = sysDictMapper.selectList(new QueryWrapper<>());
        return getTreeDict(sysDictList);
    }
    private List<SysDict> getTreeDict(List<SysDict> list){
        List<SysDict> rootList = list.stream()
            .filter(f -> f.getParentId() == 0)
            .collect(Collectors.toList());
        list.removeAll(rootList);
        if(CollUtil.isNotEmpty(rootList)){
            for (SysDict sysDict : rootList) {
                setChildList(sysDict,list);
            }
        }
        return rootList;
    }

    private void setChildList(SysDict root,List<SysDict> list){
        List<SysDict> childList = list.stream()
            .filter(f -> f.getParentId().equals(root.getId()))
            .collect(Collectors.toList());
        list.removeAll(childList);
        root.setChildren(childList);
        if(CollUtil.isNotEmpty(childList)){
            for (SysDict sysDict : childList) {
                setChildList(sysDict,list);
            }
        }
    }
   
}

复制代码

3. Clase general extraída

1. Extraer clases públicas

Escribir una clase genérica a través de la reflexión.

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author eleven
 * @date 2022/4/15 10:51
 * @apiNote 返回层级菜单
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class TreeMenuUtil<T> {
    /** 顶层节点的值 */
    private String rootValue;
    /** 对应父节点的子属性 */
    private String childKey;
    /** 父节点的属性值 */
    private String rootKey;
    /** 子菜单放置的字段 */
    private String childProperty;
    /** 要过滤的集合 */
    private List<T> list;
    
    /**
     * @apiNote 返回树状菜单
     * @return List
     */
    public List<T> rootMenu(){
        //判断rootValue是否为空,如果为空的话给rootValue赋值
        ifNullRootValueSetValue();
        //筛选出来顶级目录
        List<T> rootList = list.stream()
                .filter(item -> StrUtil.equals(rootValue, getValueByProperty(item, childKey)))
                .collect(Collectors.toList());
        //从数据集合中剔除顶层目录,减少后续遍历次数,加快速度
        list.removeAll(rootList);
        //如果list不为空的话则遍历赋值子菜单
        if (CollUtil.isNotEmpty(rootList)) {
            for (T t : rootList) {
                setChildren(t, list);
            }
            return rootList;
        }else{
            return list;
        }
    }

    /**
     * 判断rootKey是控制的话则赋值
     */
    private void ifNullRootValueSetValue(){
        if(StrUtil.isBlank(rootValue)){
            Set<String> rootValueSet = list.stream()
                    .map(m -> getValueByProperty(m, rootKey))
                    .collect(Collectors.toSet());
            Set<String> childValueSet = list.stream()
                    .map(m -> getValueByProperty(m, childKey))
                    .collect(Collectors.toSet());
            //将childKey(parentId)中的数据全部赋值过来
            Set<String> resultList = new HashSet<>();
            resultList.addAll(childValueSet);
            //算出childValueSet和rootValueSet的交集
            childValueSet.retainAll(rootValueSet);
            // 算出childValueSet 与交集不同的部分
            resultList.removeAll(childValueSet);
            //如果有差集的话,把第一个数据返回到rootValue中
            if(CollUtil.isNotEmpty(resultList)){
                rootValue = String.valueOf(resultList.toArray()[0]);
            }
        }
    }

    /**
     * 给父级菜单赋值子菜单
     * @param t         父菜单对象
     * @param list      所有数据
     */
    private void setChildren(T t,List<T> list){
        String childPropertyTypeName = getPropertyDescriptor(t, childProperty).getPropertyType().getName();
        Stream<T> childStream = list.stream()
                .filter(item -> isChild(t, item));
        Collection<T> childList = null;
        if(childPropertyTypeName.contains("Set")){
            childList = childStream.collect(Collectors.toSet());
            setValueByProperty(t, (Set<T>) childList);
        }else {
            childList = childStream.collect(Collectors.toList());
            setValueByProperty(t, (List<T>) childList);
        }
        list.removeAll(childList);
        if (CollUtil.isNotEmpty(childList)) {
            for (T item : childList) {
                setChildren(item, list);
            }
        }
    }

    /**
     * 判断当前对象是不是父级对象的子级
     * @param t     父对象
     * @param item  子对象
     * @return
     */
    private boolean isChild(T t,T item){
        String rootValue = getValueByProperty(t, rootKey);
        String childParentValue = getValueByProperty(item, childKey);
        return rootValue.equals(childParentValue);
    }

    /**
     * 通过属性获取属性的值
     * @param t         对象
     * @param key       属性
     * @return
     */
    private String getValueByProperty(T t,String key){
        PropertyDescriptor keyProperty = getPropertyDescriptor(t,key);;
        try {
            Method keyMethod = keyProperty.getReadMethod();
            return String.valueOf(keyMethod.invoke(t));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 给子级属性赋值
     * @param t         对象
     * @param list      子菜单集合     
     */
    private void setValueByProperty(T t,Collection<T> list){
        PropertyDescriptor keyProperty = getPropertyDescriptor(t, childProperty);
        //获取getCurrentPage()方法
        try {
            Method keyMethod = keyProperty.getWriteMethod();
            keyMethod.invoke(t,list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过反射获取中的属性
     * @param t     对象
     * @param key   属性
     * @return
     */
    private PropertyDescriptor getPropertyDescriptor(T t, String key){
        Class clazz = t.getClass();
        try {
            return new PropertyDescriptor(key, clazz);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
复制代码

2. Uso

@Override
public List<SysDict> getAllList() {
    /**
     * 使用构造方法给工具类赋值
     * @param rootValue     顶级菜单的父级值                 这里就是parentId的值 
     * @param childKey      实体类中对应父级菜单的属性        这里是parentId
     * @param rootKey       实体类中父级的属性               这里是id
     * @param childProperty 实体类中对应的放置子菜单的属性     这里是children
     * @param list          所有的树状菜单数据                     
     */
	return new TreeMenuUtil<SysDict>(null,
                                  "parentId",
                                  "id",
                                  "children", 
                                  sysDictMapper.selectList(new QueryWrapper<>()))
        	.rootMenu();
}
复制代码

4. Otras conexiones relacionadas

  1. herramienta de estructura de árbol hutool-TreeUtil
  2. Blogger Otros ajustes del blog Menú jerárquico

Supongo que te gusta

Origin juejin.im/post/7087400204319588382
Recomendado
Clasificación