目录
1 项目结构
这里做测试,写的不标准。。。。。。
2 使用的相关jar包
(让Java甜甜的) hutool-all、commons-beanutils、lombok、(Document) dom4j 四个关键架包。
部分 pom.xml 如下:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
话不多说,上代码。。。。。
3 相关代码
3.1 实体类
Dept.java
/**
* @author W
* @createDate 2022/8/10
* @description: Dept实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private String id;
private String name;
private String parentId;
private List<Dept> children = new ArrayList<>();
}
3.2 相关工具类
3.2.1 将对象转化为map的工具类
ObjectConvertToMapUtil.java
/**
* @author W
* @createDate 2022/8/10
* @description: 对象转化为Map
*/
public class ObjectConvertToMapUtil {
private static final Logger logger = LoggerFactory.getLogger(ObjectConvertToMapUtil.class);
public static Map<String,String> objConvertToMap(Object obj){
Map<String,String> retMap = new TreeMap<String, String>();
try {
if(obj != null){
Map<?,?> map = BeanUtils.describe(obj);
String name = null;
Object value = null;
for(Object key : map.keySet()){
if(key != null ){
name = String.valueOf(key);
if(!name.equals("class")){
value = map.get(key);
retMap.put(name, value == null ? "" : String.valueOf(value));
}
}
}
}
} catch (IllegalAccessException e) {
logger.error(e.getMessage());
} catch (InvocationTargetException e) {
logger.error(e.getMessage());
} catch (NoSuchMethodException e) {
logger.error(e.getMessage());
}
return retMap;
}
}
3.2.2 Xml创建工具类
XmlUtil.java
/**
* @author W
* @createDate 2022/8/10
* @description:
*/
public class XmlUtil {
/**
* 在指定的节点下创建一个节点
* @param parent 父节点
* @param name 要创建的节点名称
* @return
*/
public static Element createChildElement(Element parent, String name) {
return createChildElement(parent,name,null,null);
}
/**
* 在指定的节点下创建一个节点
* @param parent 父节点
* @param name 要创建的节点名称
* @param text 要創建的节点文本
* @return
*/
public static Element createChildElement(Element parent, String name, String text) {
return createChildElement(parent,name,text,null);
}
/**
* 在指定的节点下创建一个节点,并且创建所有给定的属性,如果给定的属性集为空或不包含属性信息,将不创建属性
* @param parent 父节点
* @param name 要创建的节点名称
* @param attrMap 要创建的节点属性
* @return
*/
public static Element createChildElement(Element parent, String name,Map<String,String> attrMap) {
return createChildElement(parent,name,null,attrMap);
}
/**
* 在指定的节点下创建一个节点,并且创建所有给定的属性,如果给定的属性集为空或不包含属性信息,将不创建属性
* @param parent 父节点
* @param name 要创建的节点名称
* @param text 要創建的节点文本
* @param attrMap 要创建的节点属性
* @return
*/
public static Element createChildElement(Element parent, String name, String text, Map<String,String> attrMap) {
Element child = parent.addElement(name);
if(StrUtil.isNotBlank(text)){
child.setText(text);
}
if(attrMap != null && attrMap.size() > 0){
for(String key : attrMap.keySet()){
child.addAttribute(key, attrMap.get(key));
}
}
return child;
}
}
3.3 功能实现
构造数据
public static List<Dept> getDeptAll(){
Dept dept = new Dept("1","一层","0",null);
Dept dept1 = new Dept("2","二层1","1",null);
Dept dept2 = new Dept("3","二层2","1",null);
Dept dept3 = new Dept("21","三层1","2",null);
Dept dept4 = new Dept("22","三层2","2",null);
Dept dept5 = new Dept("31","三层3","3",null);
Dept dept6 = new Dept("32","三层4","3",null);
Dept dept7 = new Dept("211","四层1","21",null);
Dept dept8 = new Dept("212","四层2","21",null);
Dept dept9 = new Dept("221","四层3","22",null);
Dept dept10 = new Dept("222","四层4","22",null);
Dept dept11 = new Dept("311","四层5","31",null);
Dept dept12 = new Dept("312","四层6","31",null);
Dept dept13 = new Dept("321","四层7","32",null);
Dept dept14 = new Dept("322","四层8","32",null);
Dept dept15 = new Dept("A","一层","0",null);
Dept dept16 = new Dept("B","二层1","A",null);
Dept dept17 = new Dept("C","二层2","A",null);
Dept dept18 = new Dept("BA","三层1","B",null);
Dept dept19 = new Dept("BB","三层2","B",null);
Dept dept20 = new Dept("CA","三层3","C",null);
Dept dept21 = new Dept("CB","三层4","C",null);
List<Dept> deptList = new ArrayList<>();
deptList.add(dept);
deptList.add(dept1);
deptList.add(dept2);
deptList.add(dept3);
deptList.add(dept4);
deptList.add(dept5);
deptList.add(dept6);
deptList.add(dept7);
deptList.add(dept8);
deptList.add(dept9);
deptList.add(dept10);
deptList.add(dept11);
deptList.add(dept12);
deptList.add(dept13);
deptList.add(dept14);
deptList.add(dept15);
deptList.add(dept16);
deptList.add(dept17);
deptList.add(dept18);
deptList.add(dept19);
deptList.add(dept20);
deptList.add(dept21);
return deptList;
}
数据结构图,如下
3.3.1 Java通过递归获得树形结构
- 实现方法
/**
*
* @param deptAll 所有的集合
* @param deptRoots 所有根节点的集合
*/
public static void getDeptTree(List<Dept> deptAll,List<Dept> deptRoots){
if(CollectionUtil.isNotEmpty(deptRoots)){
for (Dept root : deptRoots) {
List<Dept> children = deptAll.stream().filter(item -> item.getParentId().equals(root.getId())).collect(Collectors.toList());
if(CollectionUtil.isNotEmpty(children)){
root.setChildren(children);
getDeptTree(deptAll,children);
}
}
}
}
- 测试方法
@GetMapping("/getTree")
public ResponseResult getTree(){
List<Dept> deptAll = GetLeafNode.getDeptAll();
List<Dept> deptRoots = deptAll.stream().filter(item -> "0".equals(item.getParentId())).collect(Collectors.toList());
GetLeafNode.getDeptTree(deptAll,deptRoots);
return ResponseResult.success("树形结构",deptRoots);
}
- 测试结果
3.3.2 根据父节点获取最底层节点
- 实现方法
/**
* 获取叶子节点
* @param deptMap 所有的元素集合(根据父级ID进行了分组)
* @param parentId 父 id
* @param toLowerChildrenSet 存放叶子节点的集合
* @return
*/
public static Set<Dept> getMinimumChildren(Map<String, List<Dept>> deptMap,String parentId,Set<Dept> toLowerChildrenSet){
// 存放parentId下所有的子节点
Set<Dept> result = new HashSet<>();
// 获取当前父节点下所有的子节点
List<Dept> deptNodes = deptMap.get(parentId);
if(CollectionUtil.isEmpty(deptNodes)){
return null;
}
for (Dept dept : deptNodes) {
Set<Dept> lowerChildrenSet = getMinimumChildren(deptMap, dept.getId(), result);
if(CollectionUtil.isEmpty(lowerChildrenSet)){
// 如果返回null,表示当前遍历的dept节点为最底层的节点
result.add(dept);
}
}
// 将当前获取的根节存放到上一个父id对应的根节点集合
toLowerChildrenSet.addAll(result);
return result;
}
- 测试方法
@GetMapping("/getNodes")
public ResponseResult getNodes(){
List<Dept> deptAll = GetLeafNode.getDeptAll();
// 1.获得最底层子节点数据,即叶子节点
Set<Dept> toLowerChildren = new HashSet<>();
// 按照父节点分组
Map<String, List<Dept>> deptMap = deptAll.stream().collect(Collectors.groupingBy(Dept::getParentId));
// 获取parentId="0"的所有子节点
List<Dept> depts = deptMap.get("0");
for (Dept dept : depts) {
if(CollectionUtil.isNotEmpty(deptMap.get(dept.getId()))){
GetLeafNode.getMinimumChildren(deptMap,dept.getId(),toLowerChildren);
}else {
toLowerChildren.add(dept);
}
}
return ResponseResult.success("根据父节点获得最底层节点",toLowerChildren);
}
- 测试结果
3.3.3 树形xml
- 实现方法
/**
* 获取树形的xmlDoc
* @param tree
* @param deptRoots 树形集合
*/
public static void getTreeXmlDoc(Element tree,List<Dept> deptRoots){
if(CollectionUtil.isNotEmpty(deptRoots)){
for (Dept deptRoot : deptRoots) {
Map<String, String> deptMap = ObjectConvertToMapUtil.objConvertToMap(deptRoot);
deptMap.remove("children");
Element nodeParent = XmlUtil.createChildElement(tree, "dept", deptMap);
if(CollectionUtil.isNotEmpty(deptRoot.getChildren())){
getTreeXmlDoc(nodeParent,deptRoot.getChildren());
}
}
}
}
- 测试方法
@GetMapping("/getTreeXml")
public ResponseResult getTreeXml(){
List<Dept> deptAll = GetLeafNode.getDeptAll();
List<Dept> deptRoots = deptAll.stream().filter(item -> "0".equals(item.getParentId())).collect(Collectors.toList());
// 2.获得树形结构
GetLeafNode.getDeptTree(deptAll,deptRoots);
Document xmlDOC = DocumentHelper.createDocument();
Element root = xmlDOC.addElement("root");
Element tree = XmlUtil.createChildElement(root, "tree");
GetLeafNode.getTreeXmlDoc(tree,deptRoots);
return ResponseResult.success("树形xml",xmlDOC.asXML());
}
- 测试结果