如何将BitBucket返回的文件路径字符串排序生成分层目录结构?
实现方案
Files.walk() 是JDK针对本地文件系统Path对象设计的遍历方法,不适用你当前拿到的BitBucket返回的字符串路径场景,也不需要写死多层循环,用构建目录树+递归渲染的方案就能实现任意深度的嵌套目录展示,逻辑非常稳定。
核心步骤就3步:
- 定义树结构存储节点:每个目录节点保存两类数据,一是名下的子目录映射(目录名对应子节点),二是目录下直属的文件列表
- 遍历所有平铺路径,按
/拆分成路径段,从根节点开始逐层挂载:中间路径段对应目录,不存在就新建节点,最后一段对应文件,挂到当前层级的文件列表 - 深度优先遍历构建完成的目录树,递归生成嵌套的
<ul>/<li>HTML结构,直接输出到响应流即可
直接替换你原有代码里的循环输出部分即可,完整可运行代码如下:
resp.setContentType("text/html;charset=utf-8"); PrintWriter writer = resp.getWriter(); writer.print("<html><body><p>Repository: " + repo.getName() + "</p><ul>"); // 初始化根节点 Map<String, Map<String, Object>> rootDirs = new HashMap<>(); List<String> rootFiles = new ArrayList<>(); // 遍历所有平铺路径,构建目录树 for (int i = 0; i < callback.getFiles().size(); i++) { String fullPath = callback.getFiles().get(i).toString(); String[] pathSegments = fullPath.split("/"); Map<String, Map<String, Object>> currentLevelDirs = rootDirs; List<String> currentLevelFiles = rootFiles; for (int j = 0; j < pathSegments.length; j++) { String segment = pathSegments[j]; // 路径最后一段为文件,直接加入当前层级文件列表 if (j == pathSegments.length - 1) { currentLevelFiles.add(segment); break; } // 中间段为目录,不存在则新建节点 if (!currentLevelDirs.containsKey(segment)) { Map<String, Object> newDirNode = new HashMap<>(); newDirNode.put("dirs", new HashMap<String, Map<String, Object>>()); newDirNode.put("files", new ArrayList<String>()); currentLevelDirs.put(segment, newDirNode); } // 进入下一级目录继续处理 Map<String, Object> nextLevelNode = currentLevelDirs.get(segment); currentLevelDirs = (Map<String, Map<String, Object>>) nextLevelNode.get("dirs"); currentLevelFiles = (List<String>) nextLevelNode.get("files"); } } // 递归渲染嵌套目录结构 renderDirectoryNode(rootDirs, rootFiles, writer); writer.print("</ul></body></html>");
在当前Servlet类中添加如下私有递归方法,用来逐层输出HTML:
private void renderDirectoryNode(Map<String, Map<String, Object>> dirs, List<String> files, PrintWriter writer) { // 先渲染所有子目录 for (Map.Entry<String, Map<String, Object>> dirEntry : dirs.entrySet()) { String dirName = dirEntry.getKey(); Map<String, Object> dirNode = dirEntry.getValue(); writer.println("<li>" + dirName + "<ul>"); renderDirectoryNode( (Map<String, Map<String, Object>>) dirNode.get("dirs"), (List<String>) dirNode.get("files"), writer ); writer.println("</ul></li>"); } // 再渲染当前目录下所有直属文件 for (String fileName : files) { writer.println("<li><a href=\"/\">" + fileName + "</a></li>"); } }
补充提示:如果仓库里的文件/目录名包含
<、>、&这类HTML特殊字符,输出前建议做转义处理,避免页面结构错乱或者XSS风险,可以直接用Apache commons-text里的StringEscapeUtils.escapeHtml4()包裹目录名、文件名后再输出。
这个方案不需要提前预判目录嵌套深度,哪怕有十几层子目录也能正常渲染,比硬编码多层循环的可维护性高很多。
内容的提问来源于stack exchange,提问作者MillieJA
相关产品推荐
相关产品推荐

