Spring Integration与Spring Boot:不依赖增减选择启动嵌入式Web服务器
实现同一Jar包运行时选择嵌入式Web服务器的方案
要在同一可执行Jar中动态切换Tomcat、Jetty、Undertow(Servlet栈)或Netty(WebFlux栈),核心思路是将所有服务器依赖打包进Jar,再通过Spring Boot的条件配置或启动阶段干预,激活目标服务器并排除其他服务器的自动配置。以下是具体实现步骤:
1. 配置Pom.xml引入所有服务器依赖
首先把所有需要的嵌入式服务器依赖都加入项目,同时排除Spring Boot Starter默认引入的服务器,避免依赖冲突:
<!-- Servlet 基础依赖(排除默认Tomcat) --> <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> <!-- WebFlux 基础依赖(排除默认Netty) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-reactor-netty</artifactId> </exclusion> </exclusions> </dependency> <!-- 引入所有嵌入式服务器依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-reactor-netty</artifactId> <scope>compile</scope> </dependency>
2. 用条件配置实现运行时服务器选择
创建配置类,通过@ConditionalOnProperty注解根据启动参数激活对应的服务器配置:
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration public class WebServerSelectionConfig { // Servlet 容器条件配置 @Configuration @ConditionalOnProperty(name = "server.type", havingValue = "tomcat", matchIfMissing = true) @Import(ServletWebServerFactoryAutoConfiguration.Tomcat.class) static class TomcatConfig {} @Configuration @ConditionalOnProperty(name = "server.type", havingValue = "jetty") @Import(ServletWebServerFactoryAutoConfiguration.Jetty.class) static class JettyConfig {} @Configuration @ConditionalOnProperty(name = "server.type", havingValue = "undertow") @Import(ServletWebServerFactoryAutoConfiguration.Undertow.class) static class UndertowConfig {} // WebFlux Netty 容器配置 @Configuration @ConditionalOnProperty(name = "server.type", havingValue = "netty") static class NettyConfig { @Bean public ReactiveWebServerFactory nettyReactiveWebServerFactory() { return new NettyReactiveWebServerFactory(); } } }
3. 启动时指定服务器类型
通过系统参数server.type和spring.main.web-application-type指定目标服务器:
- 启动Tomcat(Servlet栈):
java -jar your-app.jar -Dserver.type=tomcat -Dspring.main.web-application-type=servlet - 启动Jetty(Servlet栈):
java -jar your-app.jar -Dserver.type=jetty -Dspring.main.web-application-type=servlet - 启动Undertow(Servlet栈):
java -jar your-app.jar -Dserver.type=undertow -Dspring.main.web-application-type=servlet - 启动Netty(WebFlux栈):
java -jar your-app.jar -Dserver.type=netty -Dspring.main.web-application-type=reactive
4. 可选:通过启动类直接排除自动配置类
如果需要更直接的控制,可以在main方法中根据参数排除不需要的服务器自动配置类:
public static void main(String[] args) { String serverType = System.getProperty("server.type", "tomcat"); SpringApplication app = new SpringApplication(YourApplication.class); // 根据服务器类型排除其他自动配置类 switch (serverType) { case "jetty": app.setExcludeAutoConfigurations( ServletWebServerFactoryAutoConfiguration.Tomcat.class, ServletWebServerFactoryAutoConfiguration.Undertow.class ); break; case "undertow": app.setExcludeAutoConfigurations( ServletWebServerFactoryAutoConfiguration.Tomcat.class, ServletWebServerFactoryAutoConfiguration.Jetty.class ); break; case "netty": app.setExcludeAutoConfigurations( ServletWebServerFactoryAutoConfiguration.Tomcat.class, ServletWebServerFactoryAutoConfiguration.Jetty.class, ServletWebServerFactoryAutoConfiguration.Undertow.class ); break; default: app.setExcludeAutoConfigurations( ServletWebServerFactoryAutoConfiguration.Jetty.class, ServletWebServerFactoryAutoConfiguration.Undertow.class ); break; } app.run(args); }
注意事项
- 确保所有服务器依赖版本与Spring Boot版本兼容,优先使用Spring Boot Starter管理版本。
- 若不需要同时支持Servlet和WebFlux栈,可以移除对应基础依赖(如只需要Servlet则删除
spring-boot-starter-webflux)。 - 可通过
@ConfigurationProperties或直接在Bean中自定义服务器参数(如端口、线程池大小)。 - 测试阶段需分别验证每个服务器的启动逻辑,避免依赖冲突或配置遗漏。
内容的提问来源于stack exchange,提问作者al.truisme
相关产品推荐
相关产品推荐

