当前位置: 首页 > 知识库问答 >
问题:

无论我做什么,Spring Boot应用程序中的JSP都会产生404错误

梁存
2023-03-14

我将首先说,我已经查看并尝试了我能找到的每个问题的解决方案。最大的问题是,这些解决方案中的大多数都非常古老,Spring Boot在过去几年中发生了很大变化。明确地说,我已经尝试了这个、这个、这个、这个等等。我还阅读了许多教程。没有任何效果。

我有一个全新的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>

我的申请课程如下:

@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\u应用程序时,出现以下错误:

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,而不是我的控制器。我的控制器正在工作。

我尝试过的其他事情:

  • 最初,我的应用程序上没有启用WebMVC。没有它,除了我的日志语句外,日志是空的。当我添加EnableWebMvc时,它现在被404记录:GET/WEB-APP/jsp/initialization/begin没有映射。jsp(或除“WEB-APP”之外我尝试过的任何其他目录)
  • 我已经试着直接在纯命令行上用mvn-spring-boot:run运行它
  • 我试着在IntelliJ IDEA中用Maven run配置和命令运行这个程序,spring boot:run(同样的结果)
  • 我两个都试过了

我还确认,我的jsp存在于[code>target/classes/WEB-APP/jsp]中(或者我尝试过的除“WEB-APP”之外的任何其他目录),因此它们确实存在。

我不知该怎么办。我开始认为我需要抛弃Spring Boot,坚持使用传统的样板Spring Web MVC应用程序,使用Servlet配置和Tomcat安装,但我对Spring Boot的“只运行”方面感到非常兴奋。任何帮助都将不胜感激。

更新1

在阅读了这个关于JSP限制的Spring文档后,我现在知道我必须使用

此外,在找到这个旧的、官方的Spring Boot示例应用程序后,我稍微改变了我的项目结构:

- 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包,我的WAR会正确创建(类和JSP都应该在它们应该在的地方),但mvn spring-boot: runmvn包spring-boot: run都不起作用-我仍然会在解析我的JSP时遇到404错误。

上面链接的旧Spring Boot示例应用程序将JSP放在WEB-INF/jsp中,但我不能这样做,因为这会导致带有“WEB-INF”或“META-INF”的警告路径:[WEB-INF/jsp/初始化/begin.jsp](仍然是404)。令人沮丧的是,这个示例应用程序不再存在,它的任何新变体也不存在。我找不到任何适用于最新版本Spring Boot的更新版本。示例应用程序在2.2. x中被删除。


共有2个答案

景阳曜
2023-03-14

假设您的web内容位于以下位置(应该在类路径AFAIK之外)source/production/webapp。Spring Boot将忽略这一点,因为在从命令行或IDE运行时,DocumentRoot中有一个硬编码路径用于检测目录(在构建war并运行war时,它会起作用)。

作为一种解决方法,您可以添加一个TomcatContextCustomizer作为bean来检测路径并将其设置为正确的基。

package com.my.project;

@SpringBootApplication
public class Application extends SpringBootServletInitializer 
{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
    {
        return application.sources(DemoApplication.class);
    }

    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public TomcatContextCustomizer docBaseCustomizer() 
    {
        return new TomcatContextCustomizer() 
        {
            public void customize(Context context) 
            {
                File root = new File("source/production/webapp");
                if (root.exists() && root.isDirectory()) 
                {
                    context.setDocBase(root.getAbsolutePath());
                }        
            }
        }
    } 
}

现在将以下内容添加到应用程序中。属性

spring.mvc.view.prefix=/jsp/
spring.mvc.view.suffix=.jsp

注意:只有当您的@SpringBootApplication注释类位于com.my.project包中时,才能删除其他注释。然后它会自动检测其他类(如实体和存储库)。

赏逸春
2023-03-14

您可以尝试将tomcat嵌入jasper的范围更改为提供的范围,因为编译JSP需要这种依赖关系。

    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <version>[9.0.38,)</version>
        <scope>provided</scope>
    </dependency>

编辑:

我在互联网上寻找了各种spring-boot jsp项目。我注意到他们还有spring-boot-starter-tomcat提供了范围。你能试试这个吗。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <version>[2.3.4.RELEASE,3)</version>
        <scope>provided</scope>
    </dependency>

参考文献:

https://mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/

https://dzone.com/articles/spring-boot-2-with-jsp-view

编辑-2:

所以这次我创建了一个新的springboot项目。进行了最低限度的设置以呈现jsp。所以基本上我遵循了这个教程,我的项目运行良好。

然后我更换了pom。xml与您的和我得到的问题中提到的相同错误。

然后,在进行试错时,我删除了<代码>

        <!--I have removed version here and it started working for me-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
<!--            <version>[9.0.38,)</version>-->
            <scope>provided</scope>
        </dependency>

虽然我有不同的目录结构。但正如你提到的,这不是问题的原因。

我已将该项目上传到github。可以随意拉它,在本地运行它。

github

 类似资料:
  • 在我的应用程序(,出现了一个向上箭头,表示,但我无法处理它来执行任何操作,甚至无法显示toast。我尝试了这个方法,并在选项ItemSelected()中处理了开关(item.getItemId()),但这两种解决方案都不适合我。我错过了一些东西,但不知道是什么。 这是我的代码: ... 我的整个选项项已选定: 我不知道其他代码是否重要: 在我的清单中,我没有父母活动。 我找到了这个答案,它似乎是

  • 我刚刚安装了一台新的计算机--全新的Java1.8安装,全新的3.5.2 Maven配置,现在我正在创建一个全新的quickstart Maven项目。 当我添加父Spring Boot启动程序和单个依赖项时,无论我做什么,它都无法解析它。

  • 我在网上学习了REST API | Web服务教程,中途被卡住了。当我运行它成功安装的服务器时,显示它在http://localhost:8080/同样如此,但只要我尝试访问不同的servlet,页面就会重新加载并返回404 Error Not found。我试着下载早期版本的wildfly,但没有用。我尝试的路径是/demorest、/webapi、/myresources,它们也被结合使用。有

  • 我正在尝试向我用SceneBuilder创建的FXML文件中存在的ChoiceBox添加值,但当我尝试这样做时(在main类中),无论我尝试什么,我都会得到一个NullPointerException。请注意,当我注释掉方法中的ChoiceBox代码(参见下面)时,项目成功运行,因此NPE没有其他原因。 null 堆栈跟踪

  • 我尝试样式复选框背景颜色,但它不会改变任何我做。我正在使用最新的火狐29。 是否在css中或浏览器中有一些规则更改? CSS: 下面是一个演示http://jsfidle.net/6kxrg/

  • 问题内容: 首先了解应用程序的一些背景知识。我有一个应用程序通过线程池并行处理许多独立的任务。现在线程池正在挂起。 以下是我的线程转储的摘录,我的pool-2中的所有线程都被“ pool-2-thread-78”阻止了。尝试写入控制台似乎已锁定,我觉得这很奇怪。谁能为我说明情况? 编辑 :平台详细信息Java版本“ 1.6.0_07” Java(TM)SE运行时环境(内部版本1.6.0_07-b0