Spring MVC+Thymeleaf模板解析失败导致500错误的完整排查过程
作者:步行cgn
问题现象
Spring MVC 项目访问 http://localhost:8080/usermgt/ 时,页面返回 500 错误,浏览器显示:
HTTP状态 500 - 内部服务器错误 消息 Request processing failed: org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "ServletContext resource [/WEB-INF/thymeleaf/index.html]")
日志里重复出现:
Mapped to ParameterizableViewController [view="index"] Exception processing template "index": Could not open ServletContext resource [/WEB-INF/thymeleaf/index.html]
错误定位
日志其实已经说得很清楚:请求到达了 Controller,视图名 index 也成功返回,问题出在 Thymeleaf 去找模板文件时找不到。
关键行:
Could not open ServletContext resource [/WEB-INF/thymeleaf/index.html]
Thymeleaf 拼出来的路径是 /WEB-INF/thymeleaf/index.html,但项目里这个文件不存在,所以抛出 FileNotFoundException,最终返回 500。
根本原因
Thymeleaf 的 SpringResourceTemplateResolver 按以下规则拼接模板路径:
prefix + viewName + suffix
当前配置是:
<bean id="templateResolver"
class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/thymeleaf/"/>
<property name="suffix" value=".html"/>
</bean>Controller 返回 "index",拼出来就是:
/WEB-INF/thymeleaf/index.html
而实际模板文件放在 src/main/webapp/WEB-INF/templates/index.html,路径不一致,所以找不到。
解决方式
有两种改法,二选一。
方式一:改配置,让 prefix 指向模板实际所在目录
如果模板在 WEB-INF/templates/ 下,把 prefix 改成:
<property name="prefix" value="/WEB-INF/templates/"/>
这样拼接结果变成 /WEB-INF/templates/index.html,和实际文件对上。
方式二:改文件位置,把模板放到 prefix 指定的目录
如果配置保持 /WEB-INF/thymeleaf/,就把模板文件放到:
src/main/webapp/WEB-INF/thymeleaf/index.html
配置不改,文件跟着配置走。
两种方式效果一样,关键是配置里的 prefix 和文件实际位置必须一致。
排查过程中容易忽略的几个点
1. 确认当前生效的是哪个配置文件
日志里出现:
Loaded 33 bean definitions from class path resource [springmvc.xml]
说明实际加载的是 classpath:springmvc.xml,不是默认的 /WEB-INF/springmvc-servlet.xml。
DispatcherServlet 的默认规则是加载 /WEB-INF/<servlet-name>-servlet.xml。如果 web.xml 中配置了:
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>那就改 springmvc.xml,改 springmvc-servlet.xml 是无效的。
2. 确认 target 目录里的文件是最新的
IDEA 部署时用的不是 src/main/webapp,而是 target 下的构建产物。修改模板或 XML 后,要确认:
target/项目名/WEB-INF/templates/index.html target/项目名/WEB-INF/classes/springmvc.xml
里面是最新内容。如果没有,执行 Build → Rebuild Project 后重新部署。
3. 确认访问路径和 Application context
日志里请求的是:
GET "/usermgt/"
说明当前部署的 Application context 是 /usermgt,访问地址应该是:
http://localhost:8080/usermgt/
如果上下文路径改过,访问路径也要跟着改,否则请求到不了 DispatcherServlet,日志里不会有 Initializing Servlet。
修正后的关键配置
<bean id="templateResolver"
class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="cacheable" value="false"/>
</bean>
<bean id="templateEngine"
class="org.thymeleaf.spring6.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
</bean>
<bean id="viewResolver"
class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>对应的文件结构:
src/main/webapp/WEB-INF/ ├── templates/ │ ├── index.html │ └── user_list.html ├── springmvc.xml └── web.xml
重启 Tomcat,访问 http://localhost:8080/usermgt/,页面正常显示。
排查流程总结
遇到 Thymeleaf 模板找不到的 500 错误,按这个顺序排查:
| 步骤 | 检查内容 |
|---|---|
| 1 | 看日志里 Could not open 后面的完整路径 |
| 2 | 对比这个路径和项目里模板文件的实际位置 |
| 3 | 如果路径不匹配,改 prefix 或移动文件 |
| 4 | 确认当前生效的是哪个配置文件(看 Loaded ... from ... 那行) |
| 5 | 确认 target 目录里的文件和配置是最新的 |
| 6 | 确认访问路径和 Application context 一致 |
总结
TemplateInputException 和 FileNotFoundException 本质上都是路径问题。Thymeleaf 按 prefix + viewName + suffix 拼接模板路径,只要配置和文件位置对齐,问题就能解决。
这次排查的关键是三点:
- 看日志里的完整路径,不要只看异常类型。
- 确认改的是真正生效的配置文件,
springmvc.xml和springmvc-servlet.xml只能有一个在起作用。 - 确认
target里的文件是最新的,IDEA 的部署产物不是源码目录。
把这三件事确认清楚,Spring MVC 的模板渲染问题基本都能快速定位。
到此这篇关于Spring MVC+Thymeleaf模板解析失败导致500错误的完整排查过程的文章就介绍到这了,更多相关Spring MVC+Thymeleaf模板解析失败500错误内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
