Spring Boot项目部署至Tomcat 8出现404 Not Found问题排查
问题描述
我有一个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-api和javax.servlet:servlet-api,且后者是2.5版本(和Tomcat8支持的Servlet3.1不兼容),这会导致类冲突。建议:
- 删除
javax.servlet:servlet-api依赖 - 保留
tomcat-servlet-api的provided作用域,或者直接移除它(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应用已成功初始化。如果有异常,根据日志信息进一步排查。
总结修复步骤
- 修改
spring-boot-starter-tomcat的scope为provided - 删除冲突的
javax.servlet:servlet-api依赖 - 主启动类继承
SpringBootServletInitializer并重写configure方法 - 在pom.xml中添加
<packaging>war</packaging> - 重新执行
mvn clean install生成war包,部署到Tomcat并重启
这样应该就能解决404的问题了。
内容的提问来源于stack exchange,提问作者artemk




