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
- 博主其他博客设置层级菜单