利用java的动态调用类和类属性机制, 编写一个工具类来自动为我们创建一个菜单树, 从而使得我们不用每次遇到树结构都要重复的写一些逻辑, 十分不友好.
public class TreeBuilder{ private static final String SET_METHOD_PREFIX = "set"; private static final String GET_METHOD_PREFIX = "get"; private static final String DEFAULT_ID_NAME = "id"; private static final String DEFAULT_PARENT_ID_NAME = "parentId"; private static final String DEFAULT_CHILDREN_NAME = "children"; public static List builder(String rootId, List dataList) throws Exception { List tree = new ArrayList<>(); for (Object data : dataList) { String parentId = data.getClass().getMethod(generateGetMethodName(DEFAULT_PARENT_ID_NAME)).invoke(data).toString(); if (rootId.equals(parentId)) { // 是根节点的话, 递归查找以该节点id作为parentId的孩子 List children = builder(data.getClass().getMethod(generateGetMethodName(DEFAULT_ID_NAME)).invoke(data).toString(), dataList); // 设置孩子 data.getClass().getMethod(generateSetMethodName(DEFAULT_CHILDREN_NAME), List.class).invoke(data, children); // 保存当前节点 tree.add(data); } } return tree; } public static List builder(String rootId, List dataList,String IDFiledName, String parentIdFiledName, String childrenFiledName) throws Exception { TreeBuilder treeBuilder = new TreeBuilder<>(); return treeBuilder.getTree(rootId, dataList, IDFiledName, parentIdFiledName, childrenFiledName); } public List getTree(String rootId, List dataList) throws Exception { return builder(rootId, dataList); } public List getTree(String rootId, List dataList, String IDFiledName, String parentIdFiledName, String childrenFiledName) throws Exception { List tree = new ArrayList<>(); for (T data : dataList) { String parentId = data.getClass().getMethod(generateGetMethodName(parentIdFiledName)).invoke(data).toString(); if (rootId.equals(parentId)) { // 是根节点的话, 查找以该节点id作为parentId的孩子 List children = getTree(data.getClass().getMethod(generateGetMethodName(IDFiledName)).invoke(data).toString(), dataList, IDFiledName, parentIdFiledName, childrenFiledName); // 设置孩子 data.getClass().getMethod(generateSetMethodName(childrenFiledName), List.class).invoke(data, children); // 保存当前节点 tree.add(data); } } return tree; } private static String generateGetMethodName(String filedName){ return GET_METHOD_PREFIX +filedName.substring(0, 1).toUpperCase() + filedName.substring(1); } private static String generateSetMethodName(String filedName){ return SET_METHOD_PREFIX +filedName.substring(0, 1).toUpperCase() + filedName.substring(1); } }
测试:
class Test{
public static void main(String[] args) throws Exception {
// 创建一个实体类
@Data
@AllArgsConstructor
class Node {
private String id;
private String data;
private String parentId;
private List children;
public Node(String id, String data, String parentId) {
this.id = id;
this.data = data;
this.parentId = parentId;
}
}
// 模拟一份数据库Node表
List nodeList = new ArrayList<>();
nodeList.add(new Node("1", "用户管理", "0"));
nodeList.add(new Node("2", "角色管理", "0"));
nodeList.add(new Node("3", "菜单管理", "0"));
nodeList.add(new Node("4", "工单管理", "0"));
nodeList.add(new Node("5", "登录管理", "0"));
nodeList.add(new Node("6", "日志管理", "0"));
nodeList.add(new Node("7", "用户创建", "1"));
nodeList.add(new Node("8", "用户角色配置", "1"));
nodeList.add(new Node("9", "用户禁用", "1"));
nodeList.add(new Node("10", "角色创建", "2"));
nodeList.add(new Node("11", "角色删除", "2"));
nodeList.add(new Node("12", "角色禁用", "2"));
nodeList.add(new Node("13", "菜单删除", "3"));
nodeList.add(new Node("14", "菜单编辑", "3"));
nodeList.add(new Node("15", "菜单禁用", "3"));
nodeList.add(new Node("16", "创建工单", "4"));
nodeList.add(new Node("17", "修改工单", "4"));
nodeList.add(new Node("18", "登录配置", "5"));
nodeList.add(new Node("19", "登录校验", "5"));
nodeList.add(new Node("20", "系统日志", "6"));
nodeList.add(new Node("21", "登录日志", "6"));
nodeList.add(new Node("22", "普通创建", "7"));
nodeList.add(new Node("23", "特殊创建", "7"));
nodeList.add(new Node("24", "配置A", "8"));
nodeList.add(new Node("25", "配置B", "8"));
nodeList.add(new Node("26", "常规日志", "20"));
nodeList.add(new Node("27", "异常日志", "20"));
// ==== 静态方式调用 ====
List tree = TreeBuilder.builder("0", nodeList);
// 声明字段名称, 如果自己的实体类与默认的字段名称不一样, 从参数中声明一下
List tree0 = TreeBuilder.builder("0", nodeList, "id", "parentId", "children");
// ==== 创建对象方式调用 ====
TreeBuilder builder = new TreeBuilder<>();
List tree1 = builder.getTree("0", nodeList);
// 声明字段名称, 如果自己的实体类与默认的字段名称不一样, 从参数中声明一下
List tree2 = builder.getTree("0", nodeList, "id", "parentId", "children");
return;
}
}



