【发布时间】:2021-02-01 20:05:42
【问题描述】:
首先我会说我已经查看并尝试了我能找到的每个问题的解决方案。最大的问题是这些解决方案中的大多数都非常陈旧,而 Spring Boot 在过去几年中发生了很大变化。需要明确的是,我已经尝试过this、this、this、this 等等。我还阅读了许多教程。没有任何效果。
我有一个全新的 Spring Boot 应用程序,我正在尝试使用它进行 JSP 渲染。这些是我的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>[2.3.4.RELEASE,3)</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>[2.8.0,3)</version>
</dependency>
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>[2.7,3)</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>[8.0.21,9)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>[2.3.2,)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>[2.3.4.RELEASE,3)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>[9.0.38,)</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>[2.3.4.RELEASE,3)</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
我的项目布局如下:
- source
- production
- java
- [my source code packages]
- resources
- WEB-APP
- jsp
- initialization
- begin.jsp
- [my resource packages]
- test
- java
- resources
“WEB-APP/jsp”只是我尝试过的最新版本。我试过“WEB-INF/jsp”、“META-INF/jsp”、“webapp/jsp”、没有父级(只是“jsp”)等等,结果都一样。
我知道父目录有点不标准,但它在 Maven 中配置正确,我已经确认它不是我的问题的根源:
<build>
<sourceDirectory>source/production/java</sourceDirectory>
<resources>
<resource>
<directory>source/production/resources</directory>
</resource>
</resources>
...
</build>
我的Application类如下:
@SpringBootApplication(scanBasePackages="com.my.project")
@EnableWebMvc
@EnableJpaRepositories("com.my.project.repository")
@EntityScan("com.my.project.model")
public class Application
{
private static final Logger LOGGER = LogManager.getLogger(Application.class);
public Application()
{
}
@Bean
public ViewResolver viewResolver()
{
LOGGER.info("Constructing InternalResourceViewResolver[JstlView]");
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-APP/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
resolver.setRedirectContextRelative(true);
resolver.setRedirectHttp10Compatible(false);
return resolver;
}
public static void main(final String[] args)
{
SpringApplication.run(Application.class, args);
}
}
还有我的控制器:
@Controller
public class InitializationController
{
private static final Logger LOGGER = LogManager.getLogger(InitializationController.class);
@GetMapping("/initialize_application")
public String beginInitialization(ModelMap model)
{
LOGGER.info("Beginning initialization");
...
LOGGER.info("Returning view");
return "initialization/begin";
}
...
}
在启动时,我看到“Constructing InternalResourceViewResolver”日志条目(我的视图解析器 bean 已创建)。当我转到/initialize_application 时,出现以下错误:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sun Oct 18 21:45:26 CDT 2020
There was an unexpected error (type=Not Found, status=404).
再次查看日志,我看到“开始初始化”和“返回视图”,所以我知道 404 是针对我的 JSP 而不是我的控制器。我的控制器正在工作。
我尝试过的其他事情:
- 最初我的应用程序中没有
@EnableWebMvc。没有它,除了我的日志语句之外,日志是空的。当我添加@EnableWebMvc时,现在使用 404 记录:No mapping for GET /WEB-APP/jsp/initialization/begin.jsp(或除“WEB-APP”之外我尝试过的任何其他目录)。 - 我试过用
mvn spring-boot:run直接在纯命令行上运行它 - 我尝试在 IntelliJ IDEA 中使用 Maven 运行配置和命令
spring-boot:run运行它(结果相同) -
<packaging>jar</packaging>和<packaging>war</packaging>我都试过了,但都没有效果,因为既没有制作过 JAR 也没有制作过 WAR。 Maven 直接在target/classes目录之外运行应用程序,而不是创建工件。 - 当我尝试
WEB-INF或META-INF而不是WEB-APP或webapp或其他东西时,我看到了一个记录的警告:Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/initialization/begin.jsp]
我还确认我的 JSP 存在于 target/classes/WEB-APP/jsp(或我尝试过的除“WEB-APP”之外的任何其他目录)中,因此它们确实存在。
我不知道如何继续。我开始认为我需要放弃 Spring Boot 并坚持使用带有 Servlet 配置和 Tomcat 安装的传统样板 Spring Web MVC 应用程序,但我对 Spring Boot 的“只是运行”方面感到非常兴奋。任何帮助将不胜感激。
更新 1
在阅读this Spring documentation about JSP limitations 之后,我现在知道我必须使用<packaging>war</packaging>,并且我现在正在使用它,但它并没有起到任何作用。我开始怀疑这里的根本问题是 maven spring-boot:run 没有创建 WAR 并运行它,它只是将所有内容构建到 target/classes 并从那里运行它。
另外,在找到this old, official Spring boot samples application之后,我稍微改变了我的项目结构:
- source
- production
- java
- [my source code packages]
- resources
- [my resource packages]
- webapp
- META-INF
- WEB-INF
- jsp
- initialization
- begin.jsp
- test
- java
- resources
更新了我的视图解析器配置:
resolver.setPrefix("/jsp/");
resolver.setSuffix(".jsp");
并将其添加到我的 POM 中:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<warSourceDirectory>source/production/webapp</warSourceDirectory>
</configuration>
</plugin>
如果我运行 mvn package,我的 WAR 会正确创建(类和 JSP 都应该在它们应该在的位置),但 mvn spring-boot:run 和 mvn package spring-boot:run 都不起作用 - 我在解析我的 JSP 时仍然遇到 404 错误。
上面链接的旧 Spring Boot 示例应用程序将 JSP 放在 WEB-INF/jsp 中,但我不能这样做,因为这会导致警告 Path with "WEB-INF" or "META-INF": [WEB-INF/jsp/initialization/begin.jsp](仍然是 404)。令人沮丧的是,这个示例应用程序不再存在,也没有任何新的变体。我找不到任何适用于最新版本 Spring Boot 的更新版本。示例应用程序在 2.2.x 中被删除。
【问题讨论】:
-
您是否使用
spring initializr创建项目? -
不是我用那个创建的,不是。
-
不要使用 JSP,而是使用 thymeleaf 之类的东西。话虽这么说,如果你真的想要,正如文档所述,它只在使用战争时才有效,你需要通过 Spring Boot 创建它(所以从你的构建中删除
maven-war-plugin)。您必须将 tomcat 添加为提供的依赖项,否则它将不起作用,并且您还必须包含 jasper(用于编译)。然后您可以部署war 文件或使用java -jar your.war来运行应用程序。同时删除注释,只留下@SpringBootApplication那些注释会干扰自动配置。 -
我不想用Thymeleaf,我想用JSP。我将其设置为
<packaging>war</packaging>(见上文)。关于使用 Spring Boot 而不是maven-war-plugin创建战争的文档在哪里?我没看到,使用<packaging>war</packaging>会自动添加maven-war-plugin。我确实添加了 Tomcat+Jasper 作为提供的依赖项和 JSTL 作为编译依赖项,就像示例应用程序一样。 Spring Boot 文档说您可以使用mvn spring-boot:run运行。他们并没有说添加 JSP 意味着您必须使用java -jar。没有其他注释我的应用程序错误。 -
在您的“初始”尝试中,
InternalResourceViewResolver的配置也存在缺陷。由于 JSP 被放置在类路径中(因为source/production/rsources被标记为这样,而不是在单独的 Web 目录中。所以你应该在前缀前面加上classpath。你也不应该使用@EnableWebMvc因为这会禁用spring boot 的自动配置。您也不必配置InternalResourceViewResolver,而是可以添加spring.mvc.view.prefix=classpath:/WEB-APP/jsp/和spring.mvc.view.suffix=.jsp来实现相同的效果。
标签: java spring spring-boot jsp spring-boot-maven-plugin