无法在 tomcat 上部署 spring 启动应用程序

Cannot deploy a spring boot app on tomcat

我的 spring 启动应用程序在本地访问时运行正常 localhost:8080。

当我在 Apache Tomcat/7.0.76 上部署它时,出现以下错误:

FAIL - Application at context path /attributes could not be started
FAIL - Encountered exception org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/attributes]]

我按照说明 here 阅读了许多与我类似的 SO 问题,但找不到解决方案。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>ch.xxx.app</groupId>
    <artifactId>something-linkingservice</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>xxx-linkingservice</name>
    <description>xxx</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <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>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- tag::security[] -->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ldap</groupId>
            <artifactId>spring-ldap-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- tag::added for the missing the dependency for HttpSessionIdListener [] -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

xxxLinkingserviceApplication.app

@SpringBootApplication
public class xxxLinkingserviceApplication extends SpringBootServletInitializer {

  /**
   * Used when run as WAR
   */
  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
    return builder.sources(xxxLinkingserviceApplication.class);
  }

  /**
   * Used when run as JAR
   */
  public static void main(String[] args) {
    SpringApplication.run(xxxLinkingserviceApplication.class, args);
  }
}

我使用 mvn clean install 构建 war 并将 xxx-linkingservice-0.0.1-SNAPSHOT.war 重命名为 attributes.war 并将其部署到 Apache Tomcat/7.0.76. Tomcat 将其安装在 /attributes 下但无法启动。 不确定这是否重要,但我构建 .war 的机器上的 java 版本是:

openjdk version "1.8.0_275"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.275-b01, mixed mode)

而 tomcat 使用以下方式运行: Java 1.8.0_302-b08 红帽公司

更新: 我尝试在 this 文章之后使用“vanilla”spring 启动应用程序创建一个新的 war,但在 tomcat.[=25= 上启动该应用程序时收到相同的错误]

INFO: Deploying web application archive /vol/data/tomcat/webapps/web-services.war
    Sep 10, 2021 9:25:49 AM org.apache.catalina.startup.TldConfig execute
    INFO: 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 wer
    e scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    Sep 10, 2021 9:25:50 AM org.apache.catalina.core.ContainerBase addChildInternal
    SEVERE: ContainerBase.addChild: start:
    org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/web-ser
    vices]]
            at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
            at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:899)
            at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:875)
            at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
            at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1092)
            at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:560)
            at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1779)
            at sun.reflect.GeneratedMethodAccessor188.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
            at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
            at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
            at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1506)
            at org.apache.catalina.manager.HTMLManagerServlet.upload(HTMLManagerServlet.java:285)
            at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:205)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:136)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:607)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
            at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is java.lang.NoClassDefFoun
    dError: javax/servlet/http/HttpSessionIdListener
            at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java
    :163)
            at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577)
            at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:1
    45)
            at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
            at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
            at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:175)

我遵循@Joachim Rohde 的回答并将 servlet-api 依赖项添加到我的 pom.xml.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

据我了解Tomcat 7 附带tomcat-servlet-3.0-api.jarHttpSessionIdListener class 在3.1版本中是根据这个documentation来的。

这仍然没有解决我的问题,我仍然收到以下错误:

Sep 10, 2021 1:12:51 PM org.apache.catalina.startup.HostConfig deployWAR
SEVERE: Error deploying web application archive /vol/data/tomcat/webapps/web-services.war
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardE
ngine[Catalina].StandardHost[localhost].StandardContext[/web-services]]
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:903)

我的解决方案是 pom.xml 中的 spring-boot-starter-version。这个必须是 2.3.12.RELEASE (https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent).