服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java实现级联下拉结构的示例代码

Java实现级联下拉结构的示例代码

2023-02-09 14:51执拗的小豆芽 Java教程

在开发过程中,会遇到很多的实体需要将查出的数据处理为下拉或者级联下拉的结构,提供给前端进行展示。本文为大家介绍了java封装下拉和级联下拉的通用工具类,需要的可以参考一下

前言

在开发过程中,会遇到很多的实体需要将查出的数据处理为下拉或者级联下拉的结构,提供给前端进行展示。

在数据库查出的结构中,可能是集合<实体类>的结构,也有可能是List<Map>的结构。

在下拉或者级联下拉的节点数据中,有时候还需要动态的携带其他的参数,已便于前端对某些数据的显示

如区域的级联下拉树中,需要携带经纬度的区域–在选择的时候在地图展示该区域

基于上面的业务场景,构建了下面的工具类,不当的地方请大家多多指教

注:在构建下拉树的时候,会存在父类id的判断,可能没有涵盖到你们的使用情况,自行修改添加

构建统一返回下拉结构

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * Treeselect树结构实体类
 *
 * @author gongl
 */
@ApiModel("下拉树结构")
public class TreeSelect implements Serializable {
    private static final long serialVersionUID = 1L;
 
    /**
     * 节点ID
     */
    @ApiModelProperty("节点id")
    private String id;
 
    /**
     * 节点名称
     */
    @ApiModelProperty("节点名")
    private String label;
 
    /**
     * 下拉节点中携带数据
     */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @ApiModelProperty("节点携带数据")
    private Map<String, Object> dataMap;
 
 
    /**
     * 子节点
     */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @ApiModelProperty("子节点集合")
    private List<TreeSelect> children;
 
 
    public TreeSelect() {
 
    }
 
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getLabel() {
        return label;
    }
 
    public void setLabel(String label) {
        this.label = label;
    }
 
    public List<TreeSelect> getChildren() {
        return children;
    }
 
    public void setChildren(List<TreeSelect> children) {
        this.children = children;
    }
 
    public Map<String, Object> getDataMap() {
        return dataMap;
    }
 
    public void setDataMap(Map<String, Object> dataMap) {
        this.dataMap = dataMap;
    }

构建集合<对象>转下拉树工具类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/**
 * 下拉和级联下拉通用生成工具类
 *
 * @Author gongl
 * @Create 2022-01-12
 */
public class TreeSelectUtils {
    private static final Logger log = LoggerFactory.getLogger(TreeSelectUtils.class);
    /**
     * 默认id名称
     */
    public static final String ID = "id";
    /**
     * 默认父类id名称
     */
    public static final String PARENT = "parentId";
 
    /**
     * 默认label名称
     */
    public static final String LABEL = "name";
 
 
    /**
     * 单层下拉结构
     *
     * @param collection 目标集合
     * @param id         节点编号字段
     * @param label      节点名字段
     * @param clazz      集合元素类型
     * @param args       需要携带的参数
     * @return 转换后的下拉结构 TreeSelect
     */
    public static <E> List<TreeSelect> singleTree(Collection<E> collection, String id, String label,
                                                  Class<?> clazz, String... args) {
        try {
            if (collection == null || collection.isEmpty()) {
                return null;
            }
            Field idField;
            try {
                idField = clazz.getDeclaredField(id);
            } catch (NoSuchFieldException e1) {
                idField = clazz.getSuperclass().getDeclaredField(id);
            }
            Field labelField;
            try {
                labelField = clazz.getDeclaredField(label);
            } catch (NoSuchFieldException e1) {
                labelField = clazz.getSuperclass().getDeclaredField(label);
            }
            idField.setAccessible(true);
            labelField.setAccessible(true);
            List<TreeSelect> list = new ArrayList<>();
            for (E e : collection) {
                TreeSelect select = new TreeSelect();
                select.setId(String.valueOf(idField.get(e)));
                select.setLabel(String.valueOf(labelField.get(e)));
                list.add(select);
                dynamicData(select, e, clazz, args);
            }
            idField.setAccessible(false);
            labelField.setAccessible(false);
            return list;
        } catch (Exception e) {
            log.error("单层下拉异常:", e);
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 集合转树结构(默认树结构字段)
     *
     * @param collection 目标集合
     * @param clazz      集合元素类型
     * @param args       需要携带的参数
     * @return 转换后的树形结构 TreeSelect
     */
    public static <E> List<TreeSelect> toTree(@NotNull Collection<E> collection, @NotNull Class<?> clazz,
                                              String... args) {
        return toTree(collection, null, null, null, clazz, args);
    }
 
    /**
     * 集合转树结构(自定义名称字段)
     *
     * @param collection 目标集合
     * @param label      节点名字段
     * @param clazz      集合元素类型
     * @param args       需要携带的参数
     * @return 转换后的树形结构 TreeSelect
     */
    public static <E> List<TreeSelect> toTree(@NotNull Collection<E> collection, @NotEmpty String label,
                                              @NotNull Class<?> clazz, String... args) {
        return toTree(collection, null, null, label, clazz, args);
    }
 
    /**
     * 集合转树结构(默认父类id字段为parentId,其他自定义)
     *
     * @param collection 目标集合
     * @param id         节点编号字段
     * @param label      节点名字段
     * @param clazz      集合元素类型
     * @param args       需要携带的参数
     * @return 转换后的树形结构  TreeSelect
     */
    public static <E> List<TreeSelect> toTree(@NotNull Collection<E> collection, @NotEmpty String id, @NotEmpty String label,
                                              @NotNull Class<?> clazz, String... args) {
        return toTree(collection, id, null, label, clazz, args);
    }
 
    /**
     * 集合转树结构(自定义树结构的字段)
     *
     * @param collection 目标集合
     * @param id         节点编号字段
     * @param parent     父节点编号字段
     * @param label      节点名字段
     * @param clazz      集合元素类型
     * @param args       需要携带的参数
     * @return 转换后的树形结构  TreeSelect
     */
    public static <E> List<TreeSelect> toTree(@NotNull Collection<E> collection, String id, String parent, String label,
                                              @NotNull Class<?> clazz, String... args) {
        try {
            if (collection == null || collection.isEmpty()) {
                return null;
            }
            //可以默认名称
            if (StringUtils.isEmpty(id)) {
                id = ID;
            }
            if (StringUtils.isEmpty(parent)) {
                parent = PARENT;
            }
            if (StringUtils.isEmpty(label)) {
                label = LABEL;
            }
            //是对象
            return collectionObj(collection, id, parent, label, clazz, args);
        } catch (Exception e) {
            log.error("多层下拉树异常:", e);
            return null;
        }
    }
 
 
    /**
     * 集合对象的封装
     */
    private static <E> List<TreeSelect> collectionObj(@NotNull Collection<E> collection, String id, String parent, String label,
                                                     @NotNull Class<?> clazz, String... args) throws NoSuchFieldException, IllegalAccessException {
        // 初始化根节点集合
        List<TreeSelect> list = 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);
        }
        // 获取 label 字段, 从当前对象或其父类
        Field labelField;
        try {
            labelField = clazz.getDeclaredField(label);
        } catch (NoSuchFieldException e1) {
            labelField = clazz.getSuperclass().getDeclaredField(label);
        }
        idField.setAccessible(true);
        parentField.setAccessible(true);
        labelField.setAccessible(true);
        // 找出所有的根节点
        for (E e : collection) {
            Object parentId = parentField.get(e);
            if (isParentNode(parentId, idField, collection)) {
                TreeSelect select = new TreeSelect();
                select.setId(String.valueOf(idField.get(e)));
                select.setLabel(String.valueOf(labelField.get(e)));
                list.add(select);
                dynamicData(select, e, clazz, args);
            }
        }
        // 依次添加子节点
        for (TreeSelect select : list) {
            addChild(select, collection, idField, parentField, labelField, clazz, args);
        }
        idField.setAccessible(false);
        parentField.setAccessible(false);
        labelField.setAccessible(false);
        return list;
    }
 
 
    /**
     * 添加跟随下拉的字段
     *
     * @param treeSelect 当前节点
     * @param e
     * @param clazz
     * @param args       需要跟随的字段
     * @throws IllegalAccessException
     * @throws NoSuchFieldException
     */
    private static <E> void dynamicData(@NotNull TreeSelect treeSelect, @NotNull Object e, @NotNull Class<E> clazz, String... args) throws IllegalAccessException, NoSuchFieldException {
        if (args.length > 0) {
            Map<String, Object> dataMap = new HashMap<>();
            for (String arg : args) {
                Field field;
                try {
                    field = clazz.getDeclaredField(arg);
                } catch (NoSuchFieldException e1) {
                    field = clazz.getSuperclass().getDeclaredField(arg);
                }
                field.setAccessible(true);
                dataMap.put(arg, field.get(e));
                field.setAccessible(false);
            }
            treeSelect.setDataMap(dataMap);
        }
    }
 
 
    /**
     * 为目标节点添加孩子节点
     *
     * @param node        目标节点
     * @param collection  目标集合
     * @param idField     ID 字段
     * @param parentField 父节点字段
     * @param labelField  字节点字段
     */
    private static <E> void addChild(@NotNull TreeSelect node, @NotNull Collection<E> collection,
                                     @NotNull Field idField, @NotNull Field parentField, @NotNull Field labelField,
                                     @NotNull Class<?> clazz, String... args) throws IllegalAccessException, NoSuchFieldException {
        //父节点的id
        String id = node.getId();
        //子节点集合
        List<TreeSelect> children = new ArrayList<>();
        for (E e : collection) {
            String parentId = String.valueOf(parentField.get(e));
            if (id.equals(parentId)) {
                // 将当前节点添加到目标节点的孩子节点
                TreeSelect treeSelect = new TreeSelect();
                treeSelect.setId(String.valueOf(idField.get(e)));
                treeSelect.setLabel(String.valueOf(labelField.get(e)));
                dynamicData(treeSelect, e, clazz, args);
                children.add(treeSelect);
                // 递归添加子节点
                addChild(treeSelect, collection, idField, parentField, labelField, clazz, args);
            }
        }
        node.setChildren(children);
    }
 
    /**
     * 判断是否是根节点, 判断方式为:
     * 1、父节点编号为空或为 0, 则认为是根节点
     * 2、父节点在集合中不存在父节点
     *
     * @param parentId 父节点编号
     * @return 是否是根节点
     */
    private static <E> boolean isParentNode(Object parentId, Field idField, @NotNull Collection<E> collection) throws IllegalAccessException {
        if (parentId == null) {
            return true;
        } else if (parentId instanceof String && (StringUtils.isEmpty(String.valueOf(parentId)) || parentId.equals("0"))) {
            return true;
        } else if (parentId instanceof Long && Long.valueOf(0).equals(parentId)) {
            return true;
        } else {
            for (E e : collection) {
                Object o = idField.get(e);
                if (Objects.equals(o, parentId)) {
                    return false;
                }
            }
            return true;
        }
    }
}

构建List<Map>转下拉或下拉树的工具类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * 下拉和级联下拉通用生成工具类
 *
 * @Author gongl
 * @Create 2022-01-12
 */
public class MapToTreeSelectUtils {
    private static final Logger log = LoggerFactory.getLogger(MapToTreeSelectUtils.class);
    /**
     * 数据库默认父类id名称
     */
    public static final String DB_PARENT = "parent_id";
 
    /**
     * 集合转树结构(自定义树结构的字段)
     *
     * @param collection 目标集合
     * @param id         节点编号字段
     * @param parent     父节点编号字段
     * @param label      节点名字段
     * @param args       需要携带的参数
     * @return 转换后的树形结构  TreeSelect
     */
    public static List<TreeSelect> mapToTree(String id, String parent, String label,
                                             @NotNull List<Map<String, Object>> collection, String... args) {
        try {
            if (collection == null || collection.isEmpty()) {
                return new ArrayList<>();
            }
            //可以默认名称
            if (StringUtils.isEmpty(id)) {
                id = TreeSelectUtils.ID;
            }
            if (StringUtils.isEmpty(parent)) {
                parent = DB_PARENT;
            }
            if (StringUtils.isEmpty(label)) {
                label = TreeSelectUtils.LABEL;
            }
            return collectionMap(id, parent, label, collection, args);
        } catch (Exception e) {
            log.error("多层下拉树异常:", e);
            return null;
        }
    }
 
    /**
     * 集合map的封裝
     */
    private static List<TreeSelect> collectionMap(String id, String parent, String label,
                                                  @NotNull List<Map<String, Object>> collection, String... args) throws IllegalAccessException, NoSuchFieldException {
        List<TreeSelect> list = new ArrayList<>();
        // 找出所有的根节点
        for (Map<String, Object> next : collection) {
            Object parentId = next.get(parent);
            if (isParentNodeMap(parentId, id, collection)) {
                TreeSelect select = new TreeSelect();
                select.setId(String.valueOf(next.get(id)));
                select.setLabel(String.valueOf(next.get(label)));
                list.add(select);
                dynamicData(select, next, args);
            }
        }
        // 依次添加子节点
        for (TreeSelect select : list) {
            addChildMap(select, id, parent, label, collection, args);
        }
        return list;
    }
 
 
    /**
     * 添加跟随下拉的字段
     *
     * @param treeSelect 当前节点
     * @param e
     * @param args       需要跟随的字段
     * @throws IllegalAccessException
     * @throws NoSuchFieldException
     */
    private static void dynamicData(@NotNull TreeSelect treeSelect, @NotNull Map<String, Object> e, String... args) throws IllegalAccessException, NoSuchFieldException {
        if (args.length > 0) {
            Map<String, Object> dataMap = new HashMap<>();
            for (String arg : args) {
                dataMap.put(arg, e.get(arg));
            }
            treeSelect.setDataMap(dataMap);
        }
    }
 
    /**
     * 为目标节点添加孩子节点
     *
     * @param node       目标节点
     * @param collection 目标集合
     * @param id         ID 字段
     * @param parent     父节点字段
     * @param label      字节点字段
     */
    private static void addChildMap(@NotNull TreeSelect node, String id, String parent, String label,
                                    @NotNull List<Map<String, Object>> collection,
                                    String... args) throws IllegalAccessException, NoSuchFieldException {
        //父节点的id
        String nodeId = node.getId();
        //子节点集合
        List<TreeSelect> children = new ArrayList<>();
        for (Map<String, Object> e : collection) {
            String parentId = String.valueOf(e.get(parent));
            if (nodeId.equals(parentId)) {
                // 将当前节点添加到目标节点的孩子节点
                TreeSelect treeSelect = new TreeSelect();
                treeSelect.setId(String.valueOf(e.get(id)));
                treeSelect.setLabel(String.valueOf(e.get(label)));
                dynamicData(treeSelect, e, args);
                children.add(treeSelect);
                node.setChildren(children);
                // 递归添加子节点
                addChildMap(treeSelect, id, parent, label, collection, args);
            }
        }
    }
 
 
    /**
     * 判断是否是根节点, 判断方式为:
     * 1、父节点编号为空或为 0, 则认为是根节点
     * 2、父节点在集合中不存在父节点
     *
     * @param parentId 父节点编号
     * @return 是否是根节点
     */
    private static boolean isParentNodeMap(Object parentId, String id, @NotNull List<Map<String, Object>> collection) {
        if (parentId == null) {
            return true;
        } else if (parentId instanceof String && (StringUtils.isEmpty(String.valueOf(parentId)) || parentId.equals("0"))) {
            return true;
        } else if (parentId instanceof Long && Long.valueOf(0).equals(parentId)) {
            return true;
        } else {
            for (Map<String, Object> e : collection) {
                Object o = e.get(id);
                if (Objects.equals(o, parentId)) {
                    return false;
                }
            }
            return true;
        }
    }
}

到此这篇关于Java实现级联下拉结构的示例代码的文章就介绍到这了,更多相关Java级联下拉内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_47914635/article/details/123551329

延伸 · 阅读

精彩推荐
  • Java教程Spring动态注册多数据源的实现方法

    Spring动态注册多数据源的实现方法

    这篇文章主要介绍了Spring动态注册多数据源的实现方法,小编觉的挺不错的,现分享到脚本之家平台,需要的朋友可以参考下...

    ODMark10022021-03-23
  • Java教程Mybatis Properties 配置优先级详解

    Mybatis Properties 配置优先级详解

    这篇文章主要介绍了Mybatis Properties 配置优先级,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    wanson20155982021-10-08
  • Java教程JDBC实现数据库增删改查功能

    JDBC实现数据库增删改查功能

    这篇文章主要为大家详细介绍了JDBC实现数据库增删改查功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    跑起来要带风!11872021-09-26
  • Java教程Java设计模式之java备忘录模式详解

    Java设计模式之java备忘录模式详解

    这篇文章主要介绍了JAVA设计模式之备忘录模式,简单说明了备忘录模式的概念、原理并结合实例形式分析了java备忘录模式的具体定义及使用方法,需要的朋友...

    大忽悠爱忽悠6952022-01-04
  • Java教程SpringCloud Config使用配置方法

    SpringCloud Config使用配置方法

    这篇文章给大家介绍SpringCloud Config使用及构建配置中心的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参...

    微瞰技术9262021-10-16
  • Java教程Java编程中10个最佳的异常处理技巧

    Java编程中10个最佳的异常处理技巧

    这篇文章主要介绍了Java编程中10个最佳的异常处理技巧,在本文中,将讨论Java异常处理最佳实践,这些Java最佳实践遵循标准的JDK库,和几个处理错误和异常的开...

    junjie2942019-12-08
  • Java教程Java多线程 实例解析

    Java多线程 实例解析

    这篇文章主要介绍了Java多线程 实例解析,需要的朋友可以参考下...

    Java之家5022020-09-09
  • Java教程java 中 poi解析Excel文件版本问题解决办法

    java 中 poi解析Excel文件版本问题解决办法

    这篇文章主要介绍了java 中 poi解析Excel文件版本问题解决办法的相关资料,需要的朋友可以参考下...

    程诺6322020-12-09