You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot项目部署至Tomcat 8出现404 Not Found问题排查

解决Spring Boot部署到外部Tomcat 8出现404的问题

问题描述

我有一个Spring Boot应用,使用内置服务器运行正常,可通过Postman测试API。现在我想将其部署到Tomcat 8,通过maven install生成root.war文件并放入Tomcat/webapps/目录,启动Tomcat无报错,但使用与内置服务器相同的URL(如localhost:8080/auth/registration)访问时出现404 Not Found。我曾尝试在application.properties中设置server.context-path,但无效果,认为问题出在项目配置上。

提供的pom.xml片段

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.4.3.RELEASE</version> 
</parent> 
<dependencies> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-tomcat</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-data-jpa</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-security</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-configuration-processor</artifactId> 
        <optional>true</optional> 
    </dependency> 
    <dependency> 
        <groupId>io.jsonwebtoken</groupId> 
        <artifactId>jjwt</artifactId> 
        <version>0.7.0</version> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.tika</groupId> 
        <artifactId>tika-core</artifactId> 
        <version>1.14</version> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.httpcomponents</groupId> 
        <artifactId>httpclient</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>io.springfox</groupId> 
        <artifactId>springfox-swagger-ui</artifactId> 
        <version>2.8.0</version> 
    </dependency> 
    <dependency> 
        <groupId>commons-fileupload</groupId> 
        <artifactId>commons-fileupload</artifactId> 
        <version>1.3.2</version> 
    </dependency> 
    <dependency> 
        <groupId>io.springfox</groupId> 
        <artifactId>springfox-swagger2</artifactId> 
        <version>2.8.0</version> 
    </dependency> 
    <!--Dependency for singleton--> 
    <dependency> 
        <groupId>javax.ejb</groupId> 
        <artifactId>javax.ejb-api</artifactId> 
        <version>3.2</version> 
    </dependency> 
    <!--PostgreSQL driver--> 
    <dependency> 
        <groupId>org.postgresql</groupId> 
        <artifactId>postgresql</artifactId> 
        <scope>runtime</scope> 
    </dependency> 
    <dependency> 
        <groupId>javax.xml.bind</groupId> 
        <artifactId>jaxb-api</artifactId> 
        <version>2.3.0</version> 
    </dependency> 
    <!--SEND MAIL--> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-mail</artifactId> 
    </dependency> 
    <dependency> 
        <groupId>org.apache.tomcat</groupId> 
        <artifactId>tomcat-servlet-api</artifactId> 
        <version>7.0.21</version> 
        <scope>provided</scope> 
    </dependency> 
    <!--Amazon--> 
    <dependency> 
        <groupId>com.amazonaws</groupId> 
        <artifactId>aws-java-sdk</artifactId> 
        <version>1.11.331</version> 
    </dependency> 
    <dependency> 
        <groupId>log4j</groupId> 
        <artifactId>log4j</artifactId> 
        <version>1.2.17</version> 
    </dependency> 
    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-test</artifactId> 
        <scope>test</scope> 
    </dependency> 
    <dependency> 
        <groupId>javax.servlet</groupId> 
        <artifactId>servlet-api</artifactId> 
        <version>2.5</version> 
    </dependency> 
    <dependency> 
        <groupId>commons-io</groupId> 
        <artifactId>commons-io</artifactId> 
        <version>2.5</version> 
    </dependency> 
</dependencies> 
<build> 
    <plugins> 
        <plugin> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-maven-plugin</artifactId> 
            <configuration> 
                <executable>true</executable> 
            </configuration> 
        </plugin> 
        <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <configuration> 
                <!-- 内容截断 --> 
            </configuration> 
        </plugin> 
    </plugins> 
</build>

问题分析与解决方案

结合你的配置和场景,我整理了几个核心问题点及修复步骤:

1. 调整内置Tomcat依赖的作用域

部署到外部Tomcat时,不需要打包内置的Tomcat容器,否则会和外部Tomcat产生类加载冲突。修改spring-boot-starter-tomcat的依赖配置:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope> <!-- 添加该作用域,避免打包内置容器 -->
</dependency>

2. 移除冲突的Servlet API依赖

你的pom.xml中同时引入了tomcat-servlet-apijavax.servlet:servlet-api,且后者是2.5版本(和Tomcat8支持的Servlet3.1不兼容),这会导致类冲突。建议:

  • 删除javax.servlet:servlet-api依赖
  • 保留tomcat-servlet-apiprovided作用域,或者直接移除它(Spring Boot的spring-boot-starter-web已包含适配的Servlet API)

3. 让主启动类适配外部Tomcat

Spring Boot应用部署到外部容器时,主启动类需要继承SpringBootServletInitializer并重写configure方法,这样Tomcat才能正确初始化Spring上下文:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class YourApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(YourApplication.class);
    }

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

注:Spring Boot 1.4.x版本使用org.springframework.boot.web.support.SpringBootServletInitializer,对应你的版本是正确的。

4. 配置正确的打包类型

确保pom.xml中指定打包为war格式,放在<parent>节点之后:

<packaging>war</packaging>

5. 上下文路径的正确处理

外部Tomcat中,server.context-path配置不生效,上下文路径由部署方式决定:

  • 你生成的root.war会被部署到根路径/,所以访问URLlocalhost:8080/auth/registration是正确的,前提是应用正常启动
  • 如果需要自定义路径,可以修改war文件名(比如myapp.war,对应路径localhost:8080/myapp/...),或者在Tomcat的server.xml中配置<Context>节点指定路径

6. 验证应用启动状态

启动Tomcat后,查看logs/catalina.out日志,确认是否有Started YourApplication in X seconds的提示,这表明Spring Boot应用已成功初始化。如果有异常,根据日志信息进一步排查。

总结修复步骤

  1. 修改spring-boot-starter-tomcat的scope为provided
  2. 删除冲突的javax.servlet:servlet-api依赖
  3. 主启动类继承SpringBootServletInitializer并重写configure方法
  4. 在pom.xml中添加<packaging>war</packaging>
  5. 重新执行mvn clean install生成war包,部署到Tomcat并重启

这样应该就能解决404的问题了。

内容的提问来源于stack exchange,提问作者artemk

火山引擎 最新活动