Spring Boot 2.0.0中如何通过配置文件设置嵌入式Tomcat的jvmRoute
解决Spring Boot中通过配置文件设置Tomcat jvmRoute实现粘性会话的问题
我懂你想通过application.properties的可配置项来设置嵌入式Tomcat的jvmRoute,而不是硬写System.setProperty("jvmRoute", "node1"),而且之前试了@PostConstruct没生效对吧?确实在Spring Boot 2.0.0.RELEASE这类2.x版本里,@PostConstruct的执行时机太晚了,Tomcat已经初始化完成,这时候再设置jvmRoute根本不会生效。
下面给你两种可行的方案,都是能通过配置文件动态设置的:
方案一:通过WebServerFactoryCustomizer定制Tomcat(推荐)
这种方式最贴合Spring Boot的扩展风格,直接定制Tomcat的工厂类,在Tomcat初始化阶段就设置好jvmRoute:
1. 先在application.properties添加配置
# 自定义你的节点标识,比如node1、node2 tomcat.jvm-route=node1
2. 编写定制器组件
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; @Component public class TomcatJvmRouteCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Value("${tomcat.jvm-route}") private String jvmRoute; @Override public void customize(TomcatServletWebServerFactory factory) { // 给Tomcat的Engine设置jvmRoute factory.addEngineValves(engine -> engine.setJvmRoute(jvmRoute)); } }
方案二:通过监听ServletWebServerInitializedEvent事件
如果更倾向于用事件监听的方式,也可以通过监听Web服务器初始化事件来修改配置:
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; import org.apache.catalina.core.StandardEngine; import org.apache.catalina.connector.Connector; @Component public class TomcatJvmRouteInitializer implements ApplicationListener<ServletWebServerInitializedEvent> { @Value("${tomcat.jvm-route}") private String jvmRoute; @Override public void onApplicationEvent(ServletWebServerInitializedEvent event) { Connector connector = (Connector) event.getWebServer().getServletContext() .getAttribute("org.apache.catalina.CONNECTOR"); if (connector != null) { StandardEngine engine = (StandardEngine) connector.getService().getContainer(); engine.setJvmRoute(jvmRoute); } } }
为什么@PostConstruct不生效?
在Spring Boot 2.x中,@PostConstruct标注的方法是在Bean初始化完成后执行的,但这时候Tomcat的核心组件(比如Engine)已经初始化完毕并准备好处理请求了,再修改jvmRoute已经无法被Tomcat识别,所以不会生效。而上面两种方案都是在Tomcat初始化的关键阶段介入,刚好能让配置生效。
内容的提问来源于stack exchange,提问作者davey
相关产品推荐
相关产品推荐

