Spring Boot+Thymeleaf同代码不同输出:嵌套循环渲染异常求助
嘿,这个问题确实有点诡异,不过咱们一步步拆解来看——先给你吃个定心丸:Thymeleaf的循环(包括嵌套循环)根本不需要额外依赖,只要你已经引入了Spring Boot的Thymeleaf starter,所有循环、表达式相关的功能都是开箱即用的,所以依赖配置肯定不是问题根源。
接下来咱们重点排查你这个“两个启动类导致渲染差异”的核心矛盾:
最可能的原因:Spring Boot组件扫描范围不匹配
Spring Boot默认只会扫描启动类所在包及其子包下的所有组件(控制器、服务、Repository等等)。如果你的两个带main方法的启动类在不同的包路径下,而你的控制器又不在对应启动类的扫描范围内,那问题就来了:
- 比如启动类A在
com.myproject.app1,控制器在com.myproject.controller(和app1平级),那启动A时,Spring根本找不到你的控制器,会用默认的映射或者干脆没有处理/请求的控制器,自然不会往Model里放myList,Thymeleaf找不到变量就不会生成列表项。 - 而另一个启动类B可能刚好和控制器在同一个根包下(比如都在
com.myproject),所以能正常扫描到控制器,渲染就正常。
其次要排查:模型数据是否正确传递
如果两个启动类都能扫描到控制器,但其中一个控制器的逻辑有问题:
- 比如启动类对应的控制器没有初始化
myList,或者在处理GET请求时没有把myList放入Model中; - 或者
myList本身是空集合,Thymeleaf遇到空集合时,th:each会直接跳过,不会生成任何<li>元素,就会出现你看到的空<ol>。
快速排查步骤
检查启动类的包与扫描范围
打开那个有问题的启动类,看看它的@SpringBootApplication注解:- 如果控制器在不同的包,你需要手动指定扫描范围,比如:
@SpringBootApplication(scanBasePackages = "com.myproject") - 最稳妥的方式是把所有启动类都放在项目的根包下(比如
com.myproject),这样Spring会自动扫描所有子包的组件。
- 如果控制器在不同的包,你需要手动指定扫描范围,比如:
验证控制器是否被加载
启动有问题的应用,查看控制台日志,找类似这样的输出:Mapped "{[/],methods=[GET]}" onto public String com.myproject.controller.xxxController.index(...)如果没有这条日志,说明控制器根本没被Spring注册,就是扫描范围的问题。
确认Model数据是否存在
在控制器的处理方法里加一行日志,输出myList的状态:System.out.println("当前myList的内容:" + myList);启动应用后,访问页面并提交请求,看看控制台输出的
myList是不是空的,或者有没有正确添加内容。检查启动类的注解差异
对比两个启动类的注解,看看有没有其中一个加了@ComponentScan、@EnableAutoConfiguration等特殊配置,导致扫描范围或bean加载逻辑不同。
最后再强调一遍:Thymeleaf的循环功能不需要额外依赖,你的pom.xml里只要有下面这一段就够了:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
按照上面的步骤排查,应该能很快找到问题所在!
内容的提问来源于stack exchange,提问作者Moe

