You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot部署Payara Server后多次启动问题排查求助

Spring Boot应用部署Payara Server后重复启动问题排查

问题背景

作为Spring框架新手,用spring-boot-starter-web搭建的应用本地启动正常,但部署到**Payara Server 5.2021.1(Java 11)**后出现多次启动现象,导致调度器等功能重复初始化。尝试过调整依赖版本、移除部分依赖,问题仍未解决,需排查原因并找到解决方案。

服务器部分日志

Initializing Soteria 1.1-b01.payara-p5 for context '/springweb'

Registering WebSocket filter for url pattern /*]]

ServletContext.log():2 Spring WebApplicationInitializers detected on classpath

    .   ____          _            __ _ _
   /\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\
  ( ( )\___ | '_ | '_| | '_ \/ _` | \\ \\ \\ \\
   \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
    '  |____| .__|_| |_|_| |_\\__, | / / / /
   =========|_|==============|___/=/_/_/_/

:: Spring Boot ::                (v2.7.4)

INFO 2470 --- [in-listener(56)] springweb.Application  : Starting Application using Java 11.0.11 on 192.168.0.1 with PID 2470 (/usr/share/payara/payara5/glassfish/domains/domain1/applications/springweb/WEB-INF/classes/springweb/Application.class started by root in /usr/share/payara/payara5/glassfish/domains/domain1/config)

INFO 2470 --- [in-listener(56)] springweb.Application  : No active profile set, falling back to 1 default profile: "default"

WebModule[/springerb] ServletContext.log():Initializing Spring embedded WebApplicationContext

INFO 2470 --- [in-listener(56)] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1975 ms

INFO 2470 --- [in-listener(56)] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: ServletContext resource [/index.html]

WARN 2470 --- [in-listener(56)] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates, check your Thymeleaf configuration, or set spring.thymeleaf.check-template-location=false)

WARN 2470 --- [in-listener(56)] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: b200e25a-ee5a-49f1-b7f4-047aa11fa4fb

This generated password is for development use only. Your security configuration must be updated before running your application in production.

INFO 2470 --- [in-listener(56)] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@78d61d6d, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2de8cf84, org.springframework.security.web.context.SecurityContextPersistenceFilter@6e79b72e, org.springframework.security.web.header.HeaderWriterFilter@1aca9626, org.springframework.security.web.csrf.CsrfFilter@387eb143, org.springframework.security.web.authentication.logout.LogoutFilter@39199309, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@29d0bc34, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@34c4cf9e, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@5603f50, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1d190e55, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@30f8298b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7b7f364, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5e208791, org.springframework.security.web.session.SessionManagementFilter@1ab27ca7, org.springframework.security.web.access.ExceptionTranslationFilter@330305b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@196974a2

INFO 2470 --- [in-listener(56)] springweb.Application  : Started Application in 5.942 seconds (JVM running for 274786.407)

Initializing Mojarra |version.string| for context '/springweb'

Initializing Soteria 1.1-b01.payara-p5 for context '/springweb'

Registering WebSocket filter for url pattern /*

ServletContext.log():2 Spring WebApplicationInitializers detected on classpath

    .   ____          _            __ _ _]]
   /\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\]]
  ( ( )\___ | '_ | '_| | '_ \/ _` | \\ \\ \\ \\]]
   \\/  ___)| |_)| | | | | || (_| |  ) ) ) )]]
    '  |____| .__|_| |_|_| |_\\__, | / / / /]]
   =========|_|==============|___/=/_/_/_/]]

:: Spring Boot ::                (v2.7.4)]]

...

项目依赖配置

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>tomcat-embed-logging-juli</artifactId>
                <groupId>org.apache.tomcat.embed</groupId>
            </exclusion>
            <exclusion>
                <artifactId>tomcat-embed-websocket</artifactId>
                <groupId>org.apache.tomcat.embed</groupId>
            </exclusion>
            <exclusion>
                <artifactId>tomcat-embed-el</artifactId>
                <groupId>org.apache.tomcat.embed</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-loader</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-websocket</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-messaging</artifactId>
    </dependency>        
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-resource-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-jose</artifactId>
    </dependency>
    <dependency>
        <groupId>com.unboundid</groupId>
        <artifactId>unboundid-ldapsdk</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId> 
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.3</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>                 
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>
</dependencies>

启动类代码

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

问题原因分析

  1. Spring Boot Servlet初始化冲突:Payara作为Java EE容器,会自动扫描并初始化SpringBootServletInitializer实现类,同时Spring Boot的内嵌容器逻辑可能被触发,导致应用被多次初始化。日志中重复出现2 Spring WebApplicationInitializers detected,说明存在多个初始化入口。
  2. 依赖配置冗余/不兼容:
    • 引入了spring-boot-loader依赖,该依赖用于可执行JAR包的启动逻辑,部署到Java EE容器时无需引入,可能引发冲突。
    • 显式引入spring-security-web,但spring-boot-starter-security已包含该依赖,重复引入可能导致类加载异常。
    • servlet-api版本为2.3,Payara 5支持Servlet 4.0,版本过低易引发兼容性问题。
  3. Payara容器特性触发:Payara的Soteria、Mojarra等组件初始化时,可能触发Servlet上下文重新加载,间接导致Spring应用重复启动。

解决方案

1. 调整启动类逻辑

移除main方法(部署到容器时,SpringBootServletInitializer的configure方法会被容器调用,无需main触发启动),修改后代码:

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

若需保留main方法用于本地调试,可添加环境判断:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    public static void main(String[] args) {
        // 仅在非容器环境下启动内嵌容器
        if (!System.getProperties().containsKey("javaee.container")) {
            SpringApplication.run(Application.class, args);
        }
    }

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

2. 优化依赖配置

  • 移除spring-boot-loader依赖,该依赖仅适用于可执行JAR包。
  • 移除显式的spring-security-web依赖,由spring-boot-starter-security自动引入。
  • 更新servlet-api为兼容Payara的版本,或直接移除(容器会提供Servlet API):
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
  • 完善spring-boot-starter-web的Tomcat排除规则,避免与Payara容器冲突:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
            <!-- 保留原有其他排除项 -->
        </exclusions>
    </dependency>
    

3. 配置Payara容器

  • 登录Payara管理控制台,进入Deployment Settings,禁用不必要的自动部署和上下文重载功能。
  • 在项目WEB-INF下添加glassfish-web.xml,禁止上下文自动重新加载:
    <glassfish-web-app>
        <context-root>/springweb</context-root>
        <class-loader delegate="true"/>
        <reload-enabled>false</reload-enabled>
    </glassfish-web-app>
    

4. 规范Spring配置

  • 确保调度器等组件使用单例模式,或添加@ConditionalOnMissingBean注解,避免重复初始化。
  • 在application.properties中明确指定Web应用类型:
    spring.main.web-application-type=servlet
    

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:31:03