1. 实体类
 
 
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;
@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. 书写返回树状菜单方法
 
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. 抽离出来的通用类
 
1. 抽离公共类
 
 
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;
@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;
    
    
    public List<T> rootMenu(){
        
        ifNullRootValueSetValue();
        
        List<T> rootList = list.stream()
                .filter(item -> StrUtil.equals(rootValue, getValueByProperty(item, childKey)))
                .collect(Collectors.toList());
        
        list.removeAll(rootList);
        
        if (CollUtil.isNotEmpty(rootList)) {
            for (T t : rootList) {
                setChildren(t, list);
            }
            return rootList;
        }else{
            return list;
        }
    }
    
    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());
            
            Set<String> resultList = new HashSet<>();
            resultList.addAll(childValueSet);
            
            childValueSet.retainAll(rootValueSet);
            
            resultList.removeAll(childValueSet);
            
            if(CollUtil.isNotEmpty(resultList)){
                rootValue = String.valueOf(resultList.toArray()[0]);
            }
        }
    }
    
    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);
            }
        }
    }
    
    private boolean isChild(T t,T item){
        String rootValue = getValueByProperty(t, rootKey);
        String childParentValue = getValueByProperty(item, childKey);
        return rootValue.equals(childParentValue);
    }
    
    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 "";
    }
    
    private void setValueByProperty(T t,Collection<T> list){
        PropertyDescriptor keyProperty = getPropertyDescriptor(t, childProperty);
        
        try {
            Method keyMethod = keyProperty.getWriteMethod();
            keyMethod.invoke(t,list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    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. 使用
 
@Override
public List<SysDict> getAllList() {
    
	return new TreeMenuUtil<SysDict>(null,
                                  "parentId",
                                  "id",
                                  "children", 
                                  sysDictMapper.selectList(new QueryWrapper<>()))
        	.rootMenu();
}
 
4. 其他相关连接
 
- hutool-树结构工具-TreeUtil
 - 博主其他博客设置层级菜单