<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在開發過程中,會遇到很多的實體需要將查出的資料處理為下拉或者級聯下拉的結構,提供給前端進行展示。
在資料庫查出的結構中,可能是集合<實體類>的結構,也有可能是List<Map>的結構。
在下拉或者級聯下拉的節點資料中,有時候還需要動態的攜帶其他的引數,已便於前端對某些資料的顯示
如區域的級聯下拉樹中,需要攜帶經緯度的區域–在選擇的時候在地圖展示該區域
基於上面的業務場景,構建了下面的工具類,不當的地方請大家多多指教
注:在構建下拉樹的時候,會存在父類別id的判斷,可能沒有涵蓋到你們的使用情況,自行修改新增
/** * 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; }
/** * 下拉和級聯下拉通用生成工具類 * * @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; } } }
/** * 下拉和級聯下拉通用生成工具類 * * @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級聯下拉內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45