Spring Boot中Thymeleaf与JSP能否共存?添加依赖后报错求助
问题描述
我在STS 4(Spring Boot版本3.2.2)中创建了名为SpringJsp的项目,操作步骤如下:
- 在
pom.xml中添加JSP依赖:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>
- 创建文件夹结构:
src/main/webapp/WEB-INF/jsp/ - 在
application.properties中配置JSP视图解析:
spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp
- 在
jsp文件夹中创建testprova.jsp文件,并编写控制器:
package it.springtestjsp; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("") public class MainController { @GetMapping("/testprova") public String test() { return "testprova"; } }
此时JSP页面可正常访问,但添加Thymeleaf依赖后:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
出现以下错误:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Feb 02 18:18:41 CET 2024
There was an unexpected error (type=Internal Server Error, status=500).
日志核心报错:
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [testprova], template might not exist or might not be accessible by any of the configured Template Resolvers
请问Spring应用中Thymeleaf模板与JSP页面能否共存?该如何解决此报错?
问题解答
1. Thymeleaf与JSP可以共存
Spring Boot支持同时使用Thymeleaf和JSP,但添加Thymeleaf依赖后,Thymeleaf会默认成为优先级更高的视图解析器。控制器返回testprova时,框架会优先去Thymeleaf的默认路径(src/main/resources/templates/)查找模板,而非你配置的JSP路径,因此抛出模板找不到的错误。
2. 解决报错的具体方案
方案一:配置多视图解析器并指定优先级
通过自定义配置类,同时注册JSP和Thymeleaf视图解析器,分别指定各自处理的视图前缀和优先级,让框架根据返回值匹配对应解析器。
创建配置类ViewResolverConfig:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.thymeleaf.spring6.view.ThymeleafViewResolver; import org.thymeleaf.spring6.SpringTemplateEngine; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; @Configuration public class ViewResolverConfig { // Thymeleaf视图解析器,优先级更高 @Bean public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine); resolver.setOrder(1); resolver.setViewNames(new String[]{"thymeleaf/*"}); // 处理前缀为thymeleaf/的视图 return resolver; } // JSP视图解析器,优先级较低 @Bean public ViewResolver jspViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/jsp/"); resolver.setSuffix(".jsp"); resolver.setOrder(2); resolver.setViewNames(new String[]{"jsp/*"}); // 处理前缀为jsp/的视图 return resolver; } // Thymeleaf模板引擎配置 @Bean public SpringTemplateEngine springTemplateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(classLoaderTemplateResolver()); return engine; } @Bean public ClassLoaderTemplateResolver classLoaderTemplateResolver() { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setPrefix("templates/"); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML"); resolver.setCharacterEncoding("UTF-8"); return resolver; } }
修改控制器返回值:
- 返回JSP时:
return "jsp/testprova" - 返回Thymeleaf模板时:
return "thymeleaf/xxx"(需在src/main/resources/templates/thymeleaf/下创建对应HTML文件)
方案二:直接指定视图路径
如果无需大量混用两种模板,可在返回视图时直接指定完整路径,强制使用对应解析器:
- 返回JSP:
return "forward:/WEB-INF/jsp/testprova.jsp"; - 返回Thymeleaf模板:
return "testprova";(确保模板在src/main/resources/templates/目录下)
方案三:通过配置文件指定视图范围
在application.properties中添加配置,分别指定Thymeleaf和JSP处理的视图前缀:
spring.thymeleaf.view-names=thymeleaf/* spring.mvc.view.view-names=jsp/*
之后控制器返回值对应加上前缀即可,逻辑与方案一一致。
内容的提问来源于stack exchange,提问作者Andrew dev

