Thymeleaf页面二次遍历同一列表触发空指针异常如何解决
Thymeleaf同列表二次遍历触发空指针问题修复
问题复现代码
<div class="sections"> <div th:each = "section: ${chapter.getSections()}" th:text= "${section.getTitle()}"/> </div> . . // 后续代码段 . // 此处尝试调用section.getContent()时触发空指针异常 <div th:each = "section: ${chapter.getSections()}" th:insert="${section.getContent()}"/>
触发原因
- 核心原因1:
chapter.getSections()返回的是一次性消费的遍历结构,而非可重复遍历的持久化集合。比如返回值为Iterator、Stream类型,或是ORM框架(JPA/MyBatis等)未完全初始化的懒加载代理集合,第一次th:each遍历完后迭代器指针已移动到末尾,第二次遍历无法正常获取元素,取值时直接返回null。 - 核心原因2:列表中部分Section实例的
content属性本身为null。th:insert要求传入的模板片段引用不能为null,第一次遍历仅调用getTitle()未触发空值,第二次遍历调用getContent()时传入null直接触发空指针。
修复方案
- 后端层调整
getSections()返回值:禁止返回Iterator、Stream类一次性遍历结构,统一转换为ArrayList等可重复遍历的普通集合再传入视图层;如果是ORM懒加载关联属性,确保视图渲染前完成集合初始化,不要透传未初始化的持久化代理对象。 - 视图层遍历前增加非空校验:使用Thymeleaf安全调用符
?.和th:if做判空拦截,避免空值传入th:insert,示例代码:
<div th:each="section: ${chapter.getSections()}" th:if="${section?.content != null}" th:insert="${section.getContent()}"/>
- 复用集合时提前定义页面级变量:通过
th:with在公共作用域提前把sections集合存为页面变量,避免重复调用getSections()触发重复生成迭代器、重复查库的问题,示例代码:
<!-- 根节点处提前定义可复用的页面变量 --> <div th:with="sectionList = ${chapter.getSections()}"> <!-- 第一次遍历渲染标题 --> <div class="sections"> <div th:each="section: ${sectionList}" th:text="${section.getTitle()}"/> </div> <!-- 其他页面代码 --> <!-- 第二次遍历渲染内容,增加判空 --> <div th:each="section: ${sectionList}" th:if="${section?.content != null}" th:insert="${section.getContent()}"/> </div>
内容的提问来源于stack exchange,提问作者tito
相关产品推荐
相关产品推荐

