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); } }
问题原因分析
- Spring Boot Servlet初始化冲突:Payara作为Java EE容器,会自动扫描并初始化
SpringBootServletInitializer实现类,同时Spring Boot的内嵌容器逻辑可能被触发,导致应用被多次初始化。日志中重复出现2 Spring WebApplicationInitializers detected,说明存在多个初始化入口。 - 依赖配置冗余/不兼容:
- 引入了
spring-boot-loader依赖,该依赖用于可执行JAR包的启动逻辑,部署到Java EE容器时无需引入,可能引发冲突。 - 显式引入
spring-security-web,但spring-boot-starter-security已包含该依赖,重复引入可能导致类加载异常。 servlet-api版本为2.3,Payara 5支持Servlet 4.0,版本过低易引发兼容性问题。
- 引入了
- 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
相关产品推荐
相关产品推荐

