1、tree表结构
这个表结构新增了tree路径id、tree路径、和层级三个字段,tree路径id方便查询某个节点下的子节点,层级便于查看某层有多少个节点,tree路径便于获取当前节点的路径。
@ApiModel(description = "文件tree")
public class DataShareFileTree implements Serializable {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "当前节点名称")
private String nodeName;
@ApiModelProperty(value = "父id")
private Long parentId;
@ApiModelProperty(value = "父节点名称")
private String parentName;
@ApiModelProperty(value = "tree路径id")
private String treePathId;
@ApiModelProperty(value = "tree路径")
private String treePath;
@ApiModelProperty(value = "层级")
private Integer nodeLevel;
}
treePathId字段方便查询当前节点下的其他子节点信息
下图为数据展示具体信息事例
2、组装tree结构
将数据库中信息组装为具体的tree结构
//tree结构
public class DataFileTreeNodeDto extends DataShareFileTree {
private List<DataFileTreeNodeDto> nodes = new LinkedList<>();
public DataFileTreeNodeDto(DataShareFileTree tree) {
BeanUtils.copyProperties(tree, this);
}
public DataFileTreeNodeDto() {
}
public List<DataFileTreeNodeDto> getNodes() {
return nodes;
}
public void setNodes(List<DataFileTreeNodeDto> nodes) {
this.nodes = nodes;
}
public void addNode(DataFileTreeNodeDto node){
this.nodes.add(node);
}
}
3、动态新增tree结构
例如:当前路径为:D:\一级目录\二级目录\三级目录\四级目录
//sharePath = "D:\一级目录\二级目录\三级目录\四级目录";
public void saveTree(String sharePath, List<DataShareFileTree> treeList) {
String newsharePath = sharePath.replace("\\\\", "");
List<String> pathList = Arrays.asList(newsharePath.split("\\\\"));
DataFileTreeNodeDto root = arrayToFileTree(treeList).get(0);
String treePath = ",root_,";
if(pathList != null && pathList.size() > 0){
for(int i = 0; i<pathList.size(); i++){
String newNodeName = pathList.get(i);
if (i > 0) {
treePath = treePath + pathList.get(i-1) + ",";
}
AtomicReference<DataFileTreeNodeDto> p = new AtomicReference<>(root);
List<DataFileTreeNodeDto> nodesF = p.get().getNodes();
if(nodesF == null || nodesF.size()==0){
DataFileTreeNodeDto treeNodeDto = p.get();
treeNodeDto.addNode(creatTree(treeNodeDto, newNodeName));
}
int finalI = i;
int count = 0;
String lastNodeName = i == 0 ? "root_" : pathList.get(i-1);
String finalTreePath = treePath;
Optional<DataFileTreeNodeDto> optional = nodesF.stream().filter(n -> {
//判断当前节点是否存在
return doesItExist(n, finalI, newNodeName, lastNodeName, count, finalTreePath);
}).findAny();
if (!optional.isPresent() && i == 0) {
//to create
p.get().addNode(creatTree(p.get(), newNodeName));
}
}
}
}
private List<DataFileTreeNodeDto> arrayToFileTree(List<DataShareFileTree> treeList) {
Map<Long, DataFileTreeNodeDto> treeMap = new HashMap<>();
List<DataFileTreeNodeDto> nodes = treeList.stream().map(n -> {
DataFileTreeNodeDto node = new DataFileTreeNodeDto(n);
treeMap.put(node.getId(), node);
return node;
}).collect(Collectors.toList());
Iterator<DataFileTreeNodeDto> iterator = nodes.iterator();
while (iterator.hasNext()) {
DataFileTreeNodeDto node = iterator.next();
DataFileTreeNodeDto treeNode = treeMap.get(node.getParentId());
if(treeNode != null){
treeNode.addNode(node);
iterator.remove();
}
}
return nodes;
}
private DataFileTreeNodeDto newNodeDto = new DataFileTreeNodeDto();
//i-循环次数,count-tree层数,lastNodeName-上层treeName,newNodeName-本层treeName,treePath-新增路径
private Boolean doesItExist(DataFileTreeNodeDto dto, int i, String newNodeName, String lastNodeName, int count, String treePath){
if (count == i) {
BeanUtils.copyProperties(dto, newNodeDto);
if (dto.getParentName().equals(lastNodeName)) {
if (!dto.getNodeName().equals(newNodeName)) {
return dto.getNodeName().equals(newNodeName);
}
return dto.getNodeName().equals(newNodeName);
}
// return dto.getParentName().equals(lastNodeName);
}
count = count + 1;
List<DataFileTreeNodeDto> nodes = dto.getNodes();
if(nodes == null || nodes.size() == 0){
BeanUtils.copyProperties(dto, newNodeDto);
if (dto.getNodeName().equals(lastNodeName)){
if (treePath.equals(dto.getTreePath()+dto.getNodeName()+","))
dto.addNode(creatTree(dto, newNodeName));
return dto.getNodeName().equals(lastNodeName);
}
return dto.getNodeName().equals(lastNodeName);
}
int finalCount = count;
Optional<DataFileTreeNodeDto> optional = nodes.stream().filter(n -> {
return doesItExist(n, i, newNodeName, lastNodeName, finalCount, treePath);
}).findAny();
if (newNodeDto.getParentName().equals(lastNodeName) && !optional.isPresent() && count == i) {
if (treePath.equals(newNodeDto.getTreePath()))
dto.addNode(creatTree(dto, newNodeName));
}
return optional.isPresent();
}
private DataFileTreeNodeDto creatTree(DataFileTreeNodeDto dto, String newNodeName){
DataShareFileTree tree = new DataShareFileTree();
tree.setNodeName(newNodeName);
tree.setParentId(dto.getId());
tree.setNodeLevel(dto.getNodeLevel()+1);
tree.setParentName(dto.getNodeName());
tree.setTreePath(dto.getTreePath()+dto.getNodeName()+",");
tree.setTreePathId(dto.getTreePathId()+dto.getId()+",");
DataShareFileTree save = treeRepository.save(tree);
DataFileTreeNodeDto treeNodeDto = new DataFileTreeNodeDto(save);
return treeNodeDto;
}