01背景:Thymeleaf 如何定位模板
Thymeleaf 是 Spring Boot 生态里常用的服务端模板引擎。Controller 返回一个
ModelAndView(视图名)后,Thymeleaf 的视图解析器会按下面这条规则拼出模板的
实际路径,再去 classpath 下找文件:
实际模板路径 = prefix + 视图名 + suffix
本项目在 application.properties 里配置了 prefix 和 suffix:
spring.thymeleaf.cache=false
spring.thymeleaf.favicon.enabled=false
spring.thymeleaf.prefix=classpath:templates
spring.thymeleaf.suffix=.html
同时,Controller 返回的视图名自带前导斜杠:
@RestController
public class Controller {
@RequestMapping("upload")
public ModelAndView upload() {
return new ModelAndView("/upload"); // 注意前导斜杠
}
@RequestMapping("spring-upload")
public ModelAndView springUpload() {
return new ModelAndView("/spring-upload");
}
}
模板文件位于 src/main/resources/templates/ 下:upload.html 和 spring-upload.html。
02问题:找不到资源
如果把 prefix 写成带尾斜杠的形式:
# 错误写法:末尾多了一个 /
spring.thymeleaf.prefix=classpath:templates/
访问 /upload 或 /spring-upload 时,会直接报错,提示找不到模板资源。
视图解析失败,日志/响应里出现类似「resource not found」「找不到资源」的错误,模板明明就躺在 templates 目录下却加载不出来。
03根因:双斜杠路径
回到那条拼接规则 prefix + 视图名 + suffix,关键在于视图名本身带了前导斜杠。于是两种写法拼出来的结果完全不同:
# 正确:prefix 无尾斜杠,靠视图名的前导 / 补全分隔
classpath:templates + /upload + .html = classpath:templates/upload.html ✓ 命中模板
# 错误:prefix 有尾斜杠,和视图名的前导 / 叠加成双斜杠
classpath:templates/ + /upload + .html = classpath:templates//upload.html ✗ 路径不存在
classpath:templates//upload.html 里出现了两个连续斜杠,
classpath 资源定位时按这个「不存在的路径」去找文件,自然找不到,于是报「找不到资源」。
本项目视图名统一带前导斜杠(/upload、/spring-upload),
因此 spring.thymeleaf.prefix 永远不能加尾斜杠。二者只需一处提供分隔斜杠。
04正确配置
spring.thymeleaf.cache=false
spring.thymeleaf.favicon.enabled=false
spring.thymeleaf.prefix=classpath:templates
spring.thymeleaf.suffix=.html
| 项 | 值 | 说明 |
|---|---|---|
prefix | classpath:templates | 无尾斜杠,配合视图名前导斜杠使用 |
suffix | .html | 模板文件扩展名 |
正确的解析示例:
| 视图名 | 拼出的路径 | 对应文件 |
|---|---|---|
/upload | classpath:templates/upload.html | templates/upload.html |
/spring-upload | classpath:templates/spring-upload.html | templates/spring-upload.html |
05注意事项与踩坑清单
| 坑 | 现象 | 正确做法 |
|---|---|---|
prefix 带尾斜杠 classpath:templates/ |
拼出 classpath:templates//xxx.html,报「找不到资源」 |
prefix 去掉尾斜杠,写成 classpath:templates |
| 视图名与 prefix 同时带斜杠 | 同上,双斜杠路径 | 约定「视图名带前导 / + prefix 无尾 /」,只需一处补全分隔 |
| 视图名漏写前导斜杠 | 拼出 classpath:templatesupload.html,同样找不到 |
保持视图名带前导斜杠(/upload) |
视图名带前导 /,prefix 就不带尾 /;反过来 prefix 带尾 /,视图名就别带前导 /。本项目的约定是前者。