Spring Boot多模块迁移场景下如何配置原有web.xml文件
多WAR包J2EE应用迁移Spring Boot的web.xml配置方案
最优平滑迁移方案(无WAR包依赖,优先推荐)
不需要保留原有模块的WAR打包形式,也不需要迁移webapp目录到启动模块,两个原有web模块完全独立,后续可逐步迭代迁移配置:
- 将原有两个web模块的打包类型从
war改为jar,将各自的web.xml和静态资源分别存放在模块的src/main/resources/WEB-INF/目录下,两个模块互不干扰 - 在Spring Boot启动模块中,用
LegacyWebApplicationContext直接加载各个模块的web.xml配置,代码示例:
import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.web.context.support.LegacyWebApplicationContext; @Configuration public class WebModuleConfig { // 注册第一个web模块的配置 @Bean public ServletContextInitializer firstWebModuleInitializer() { return servletContext -> { LegacyWebApplicationContext webContext = new LegacyWebApplicationContext(); webContext.setServletContext(servletContext); // 指向第一个模块的web.xml路径 webContext.setConfigLocation("classpath:WEB-INF/first-web.xml"); // 单独指定第一个模块的上下文路径 servletContext.setContextPath("/first-app"); webContext.refresh(); }; } // 注册第二个web模块的配置 @Bean public ServletContextInitializer secondWebModuleInitializer() { return servletContext -> { LegacyWebApplicationContext webContext = new LegacyWebApplicationContext(); webContext.setServletContext(servletContext); // 指向第二个模块的web.xml路径 webContext.setConfigLocation("classpath:WEB-INF/second-web.xml"); // 单独指定第二个模块的上下文路径 servletContext.setContextPath("/second-app"); webContext.refresh(); }; } }
注意:如果原有web.xml中存在JNDI、容器共享库等依赖,可以同步迁移到Spring Boot的
application.yml/properties配置文件中,无需额外调整web.xml本身的内容。
需保留原有WAR包格式的方案
如果必须保留原有两个模块的WAR打包形式,可通过类路径资源读取解决FAT JAR内WAR包路径识别问题:
- 在Spring Boot启动模块的pom.xml中引入两个WAR模块的依赖,指定type为war:
<dependencies> <dependency> <groupId>com.yourcompany</groupId> <artifactId>first-web-module</artifactId> <version>${project.version}</version> <type>war</type> <scope>runtime</scope> </dependency> <dependency> <groupId>com.yourcompany</groupId> <artifactId>second-web-module</artifactId> <version>${project.version}</version> <type>war</type> <scope>runtime</scope> </dependency> </dependencies>
- 自定义
TomcatServletWebServerFactory,自动读取类路径下的WAR资源完成部署:
import org.apache.catalina.Context; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; @Configuration public class TomcatWarConfig { private final ResourceLoader resourceLoader; public TomcatWarConfig(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> warDeployCustomizer() { return factory -> factory.addContextCustomizers(parentContext -> { // 部署第一个WAR deployWar(parentContext, "/first-app", "classpath:META-INF/resources/first-web-module.war"); // 部署第二个WAR deployWar(parentContext, "/second-app", "classpath:META-INF/resources/second-web-module.war"); }); } private void deployWar(Context parentContext, String contextPath, String warClassPath) { try { Resource warResource = resourceLoader.getResource(warClassPath); Context appContext = parentContext.getParent().addWebapp(contextPath, warResource.getFile().getAbsolutePath()); // 共享Spring Boot的类加载器,避免重复初始化Bean appContext.setParentClassLoader(parentContext.getClassLoader()); } catch (Exception e) { throw new RuntimeException("WAR包部署失败:" + warClassPath, e); } } }
内容的提问来源于stack exchange,提问作者myborobudur
相关产品推荐
相关产品推荐

