Spring Boot WAR包部署Tomcat访问报404 应用未启动问题求解
Spring Boot WAR包部署Tomcat返回404问题排查方案
问题现象
将Spring Boot项目打包为WAR包部署到Tomcat后,访问返回HTTP Status 404错误,无对应业务日志输出,Spring应用未正常启动。已修改server.xml中Context path配置,错误截图如下:
现有配置与日志信息
build.gradle配置
plugins { id 'org.springframework.boot' version '2.7.0' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'war' } group = '-' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'mysql:mysql-connector-java' annotationProcessor 'org.projectlombok:lombok' // 错误依赖:spring-boot-starter-parent为Maven父POM,不应作为普通依赖引入 implementation 'org.springframework.boot:spring-boot-starter-parent:2.7.0' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0' } bootWar{ archiveName("ROOT.war") } tasks.named('test') { useJUnitPlatform() }
启动类配置
MyApplication.java
@SpringBootApplication public class MyApplication extends SpringBootServletInitializer{ public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
ServletInitializer.java
public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(MyApplication.class); } }
Tomcat启动日志
20-Jun-2022 12:17:03.944 INFO [Thread-3] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-80"] 20-Jun-2022 12:17:03.968 INFO [Thread-3] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina] 20-Jun-2022 12:17:04.045 INFO [Thread-3] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-80"] 20-Jun-2022 12:17:04.052 INFO [Thread-3] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-80"] 20-Jun-2022 12:17:05.268 WARNING [main] org.apache.catalina.core.StandardContext.setPath A context path must either be an empty string or start with a '/' and do not end with a '/'. The path [/] does not meet these criteria and has been changed to [] 20-Jun-2022 12:17:05.343 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/9.0.31 (Ubuntu) 20-Jun-2022 12:17:05.344 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Mar 16 2022 18:51:24 UTC 20-Jun-2022 12:17:05.345 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.31.0 20-Jun-2022 12:17:05.346 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux 20-Jun-2022 12:17:05.347 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 5.4.0-1018-aws 20-Jun-2022 12:17:05.348 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64 20-Jun-2022 12:17:05.348 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/java-11-openjdk-amd64 20-Jun-2022 12:17:05.351 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 11.0.15+10-Ubuntu-0ubuntu0.20.04.1 20-Jun-2022 12:17:05.352 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Private Build 20-Jun-2022 12:17:05.352 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /var/lib/tomcat9 20-Jun-2022 12:17:05.353 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/share/tomcat9 20-Jun-2022 12:17:05.355 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED 20-Jun-2022 12:17:05.356 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED 20-Jun-2022 12:17:05.357 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED 20-Jun-2022 12:17:05.358 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/var/lib/tomcat9/conf/logging.properties 20-Jun-2022 12:17:05.359 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 20-Jun-2022 12:17:05.362 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.awt.headless=true 20-Jun-2022 12:17:05.363 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048 20-Jun-2022 12:17:05.363 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 20-Jun-2022 12:17:05.363 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 20-Jun-2022 12:17:05.364 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs= 20-Jun-2022 12:17:05.364 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/var/lib/tomcat9 20-Jun-2022 12:17:05.365 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/share/tomcat9 20-Jun-2022 12:17:05.365 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/tmp 20-Jun-2022 12:17:05.367 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library [1.2.23] using APR version [1.6.5]. 20-Jun-2022 12:17:05.367 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 20-Jun-2022 12:17:05.368 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 20-Jun-2022 12:17:05.375 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1f 31 Mar 2020] 20-Jun-2022 12:17:06.084 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-80"] 20-Jun-2022 12:17:06.156 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [1,471] milliseconds 20-Jun-2022 12:17:06.314 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina] 20-Jun-2022 12:17:06.315 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.31 (Ubuntu)] 20-Jun-2022 12:17:12.419 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 20-Jun-2022 12:17:12.640 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deploying deployment descriptor [/etc/tomcat9/Catalina/localhost/host-manager.xml] 20-Jun-2022 12:17:12.648 WARNING [main] org.apache.catalina.startup.HostConfig.deployDescriptor The path attribute with value [/host-manager] in deployment descriptor [/etc/tomcat9/Catalina/localhost/host-manager.xml] has been ignored 20-Jun-2022 12:17:13.716 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 20-Jun-2022 12:17:13.721 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of deployment descriptor [/etc/tomcat9/Catalina/localhost/host-manager.xml] has finished in [1,081] ms 20-Jun-2022 12:17:13.723 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deploying deployment descriptor [/etc/tomcat9/Catalina/localhost/manager.xml] 20-Jun-2022 12:17:13.724 WARNING [main] org.apache.catalina.startup.HostConfig.deployDescriptor The path attribute with value [/manager] in deployment descriptor [/etc/tomcat9/Catalina/localhost/manager.xml] has been ignored 20-Jun-2022 12:17:14.651 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 20-Jun-2022 12:17:14.694 INFO [main] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of deployment descriptor [/etc/tomcat9/Catalina/localhost/manager.xml] has finished in [971] ms 20-Jun-2022 12:17:14.700 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-80"] 20-Jun-2022 12:17:14.732 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [8,574] milliseconds
server.xml配置
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Context docBase="ROOT" path="/" reloadable="false" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host>
排查修复方向
按优先级从高到低排查以下问题:
- JDK版本不匹配
项目build.gradle中配置sourceCompatibility = '17',即编译使用JDK17,但Tomcat运行环境为JDK11(日志中明确显示JVM Version为11.0.15),高版本编译的class文件无法在低版本JVM上运行,会直接导致应用初始化失败,无Spring启动日志输出。
修复方案:要么将Tomcat运行JDK升级到17,要么将项目编译版本下调到11,保证编译和运行的JDK大版本一致。 - 错误引入starter-parent依赖
spring-boot-starter-parent是Maven专用的父POM依赖,不能作为普通implementation依赖引入到Gradle项目中,会导致依赖树混乱,引发类冲突、配置加载失败等问题。
修复方案:直接删除implementation 'org.springframework.boot:spring-boot-starter-parent:2.7.0'这行依赖,Gradle项目通过io.spring.dependency-management插件已经实现了和starter-parent一致的依赖版本管理能力,不需要额外引入。 - Spring Boot Servlet初始化配置冗余
目前同时在MyApplication启动类继承了SpringBootServletInitializer,又单独写了ServletInitializer类继承同一个类,部分Tomcat版本扫描时会出现初始化类重复加载、找不到启动源的问题。
修复方案:二选一即可,推荐直接删除独立的ServletInitializer.java,把configure方法直接写在MyApplication类中,代码如下:@SpringBootApplication public class MyApplication extends SpringBootServletInitializer{ public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(MyApplication.class); } } - **Context配置
相关产品推荐
相关产品推荐

