You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 03:15:44