
本文详解如何在 Thymeleaf 中正确使用 th:block 配合 th:each 和 th:if 渲染深度嵌套的 Map>> 数据结构,生成符合语义、结构清晰的 HTML 表格,避免标签不闭合与非法嵌套错误。
本文详解如何在 thymeleaf 中正确使用 `th:block` 配合 `th:each` 和 `th:if` 渲染深度嵌套的 `map
在 Thymeleaf 模板中, 你遇到的两个典型错误正源于此: ✅ 正确解法是:放弃“动态拼接标签”的思路,转而通过条件渲染单元格内容来实现视觉上的合并效果。参考你的数据结构: 对应的目标表格需满足: 以下是推荐的、语义清晰且完全合法的 Thymeleaf 模板写法: ? 关键要点说明: ? 进阶提示: 通过合理运用 是一个逻辑容器标签,它本身不会被渲染为任何 HTML 元素,仅用于分组和条件控制,是处理复杂循环与条件逻辑的理想工具。但其使用需严格遵循 XML/HTML 语法规范:所有开始标签必须有对应结束标签,且不可跨标签边界拆分结构(如将 的开始与结束分别放在不同 th:block 内)。 内部用 th:block 尝试“分段拼接” )添加 标签(如 闭在第二个),违反 HTML 嵌套规则; 开在第一个 th:block,
th:if 属性——Thymeleaf 不支持在结束标签上使用任何属性指令,该语法直接导致解析失败。Map<string map string>>> result = Map.of(
"First", Map.of(
"time", Map.of("now", "asfas", "past", "lsefa", "future", "saeflkjle"),
"sleifj", Map.of("now", "dsff", "past", "sfesf", "future", "sefasefa")
),
"Second", Map.of(
"time", Map.of("now", "xyz", "past", "abc", "future", "def"),
"sleifj", Map.of("now", "123", "past", "456", "future", "789")
)
);</string>
"First")仅在首行显示于第一列;"time"、"sleifj")的后续行,第一列留空(视觉上实现“跨行合并”效果);"time");"now"、"past"、"future" 的值。
Map Name
Sub Name
Now
Past
Future
First
time
asfas
lsefa
saeflkjle
th:block 作为纯粹的逻辑分组容器,包裹整个外层循环,确保不向 DOM 注入冗余节点;subEntryStat.first(而非 count == 0)更语义化且健壮; 均完整定义,无标签拆分或非法属性,完全符合 HTML 规范; #maps.get(map, key) 替代 map.get('key'),可避免 NullPointerException(当子 Map 缺失某 key 时返回 null 而非报错);th:block 移至 上(即
th:each 直接作用于 ),适用于需为每组数据添加独立
的场景。
若需真正实现 这类原生行合并,需在后端预处理数据(如计算每组子项数量并注入 First rowspan 值),再由模板直接输出。但对多数报表场景,上述“首行显示 + 其余留空”的视觉方案已足够清晰且开发成本最低。th:block 的分组能力与 th:if/th:unless 的条件控制,即可优雅、安全地渲染任意深度嵌套的 Map 结构,无需牺牲模板可维护性与浏览器兼容性。










