<p>Spring Boot 2.5+ 默认不自动配置 Thymeleaf 视图解析器,需显式配置路径、前缀、后缀和缓存;3.x 要求 Thymeleaf 3.1+ 及 jakarta.* 包名;@Controller 返回 String 失效多因注解误用或扫描失败;自定义 TemplateResolver 需命名 templateResolver 且避免运行时拼接路径。</p>

Spring Boot 2.5+ 默认不自动配置 Thymeleaf 视图解析器
Spring Boot 2.5 起移除了对 spring-boot-starter-thymeleaf 的“零配置”支持,哪怕你加了依赖,ThymeleafViewResolver 也不会自动注册。这不是 bug,是官方明确的变更 —— 它要求你显式声明模板路径、前缀、后缀和缓存策略。
常见错误现象:Whitelabel Error Page,控制台没报错,但访问 /index 返回 404;或者抛出 TemplateInputException: Error resolving template "index"。
- 确认已添加依赖:
spring-boot-starter-thymeleaf(不是thymeleaf单独 jar) - 检查
application.properties是否设置了基础路径:spring.thymeleaf.prefix=classpath:/templates/和spring.thymeleaf.suffix=.html - 确保 HTML 模板放在
src/main/resources/templates/(不是static/或public/) - 开发阶段建议关缓存:
spring.thymeleaf.cache=false,否则改完 HTML 不生效
Thymeleaf 3.1+ 与 Spring Boot 3.x 的兼容要点
Spring Boot 3.x 基于 Jakarta EE 9+,所有包名从 javax.* 升级为 jakarta.*。Thymeleaf 3.1 开始才完全支持 Jakarta,用旧版(如 3.0.x)会直接启动失败,报 NoClassDefFoundError: javax/servlet/Filter。
使用场景:升级 Spring Boot 2.7 → 3.2 时最容易踩这个坑,尤其团队里有人手动引入了老版本 thymeleaf-spring5。
立即学习“Java免费学习笔记(深入)”;
- 必须用
thymeleaf-spring6(对应 Spring Boot 3.x),Maven 里删掉任何thymeleaf-spring5依赖 -
spring-boot-starter-thymeleaf3.2.x 默认带的是 Thymeleaf 3.1.x,无需额外指定版本 - 如果用了自定义
TemplateResolver,确认构造函数参数类型是ITemplateResolver,而非已废弃的ServletContextTemplateResolver
@Controller 返回 String 时为啥不走 Thymeleaf?
返回值是 String 且没加 @ResponseBody,按理该被视图解析器处理,但实际返回纯文本或 404 —— 很可能控制器类没被 Spring 扫描到,或者方法签名干扰了视图解析逻辑。
典型错误:方法返回 String,但参数里有 @RequestBody 或返回值加了 @ResponseBody;或者类上漏了 @Controller(写了 @RestController 却想渲染页面)。
-
@RestController = @Controller + @ResponseBody,它强制走 JSON 序列化,无视 Thymeleaf - 确保控制器类上有
@Controller,不是@RestController - 方法不要同时有
@ResponseBody和返回视图名;也不要参数用@RequestBody(那是接收 JSON 的) - 简单验证:在方法里加
System.out.println("hit");,看是否执行 —— 不执行说明没被扫描或映射失败
自定义 TemplateResolver 需绕开的两个硬限制
想动态切换模板目录、加版本号前缀、或读取 classpath 外的模板时,常会手写 TemplateResolver Bean。但 Spring Boot 的自动配置会和它冲突,导致解析器被覆盖或初始化顺序错乱。
性能影响:每次请求都 new 一个 ClassLoaderTemplateResolver 是常见反模式,它会反复加载模板,拖慢首屏渲染。
- 不要在配置类里直接 new
SpringTemplateResolver并设setCacheable(false)—— 改用spring.thymeleaf.cache=false全局控制 - 如果必须自定义,Bean 名必须叫
templateResolver(小写),否则 Spring Boot 自动配置仍会注入默认实例 - 避免在
setPrefix()里拼接变量,比如"file:" + System.getProperty("user.home") + "/templates/"—— 这会导致热部署失效,且容器环境路径不可控










