默认情况下,Spring Boot在嵌入式Tomcat中以jar形式运行(尽管您可以将其部署为常规WAR)。与嵌入式应用程序服务器一起运行非常好,但是有时您可能需要将另一场战争与嵌入式应用程序捆绑在一起。也许您有一个旧版应用程序需要包括在内,但不想为此设置常规的Tomcat。
幸运的是,使用Spring Boot,这很容易。具体实现方式取决于您的Spring Boot版本。
Spring Boot 2.x
您需要做的就是在您的一个@Configurationtype类中声明一个bean TomcatServletWebServerFactory。然后,您需要重写getTomcatWebServer()方法。这样增加war如同运行tomcat.addWebApp()一样简单。
请注意,在下面的示例中,webapps由于默认情况下该目录不存在,因此需要创建该目录。它是通常将war部署到Tomcat的目录。
@Bean public TomcatServletWebServerFactory servletContainerFactory() { return new TomcatServletWebServerFactory() { @Override protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { // webapps directory does not exist by default, needs to be created new File(tomcat.getServer().getCatalinaBase(), "webapps").mkdirs(); // Add a war with given context path // Can add multiple wars this way with different context paths tomcat.addWebapp("context-path", "path-to-your-war.war"); return super.getTomcatWebServer(tomcat); } }; }
|
您可以将它们外部化为属性,而不必硬编码WAR的路径及其上下文路径,并且仅在存在这些属性时使用加载WAR(使用@ConditionalOnProperty)。
您可以将它们放入您application.properties的应用程序中,也可以在运行应用程序时将它们作为命令行参数传递。这样,您可以例如在进行本地开发时跳过加载您的WAR,或者在不同的环境中提供不同的工件。
@Bean @ConditionalOnProperty(name = "external.war.file") public TomcatServletWebServerFactory servletContainerFactory(@Value("${external.war.file}") String path, @Value("${external.war.context}") String contextPath) { return new TomcatServletWebServerFactory() {
@Override protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { new File(tomcat.getServer().getCatalinaBase(), "webapps").mkdirs();
tomcat.addWebapp(contextPath, path);
return super.getTomcatWebServer(tomcat); }
}; }
|
如果要将WAR部署到/,则需要使用一个空字符串作为上下文根。为了避免与Spring Boot应用程序发生冲突,可以application.properties通过设置来更改其上下文根server.servlet.context-path。使用胖JAR中的依赖项
如果要避免两个工件都使用重复的依赖关系,则可以指定外部WAR应使用胖JAR的类加载器。
Context context = tomcat.addWebapp("context-path", "path-to-your-war.war"); context.setParentClassLoader(getClass().getClassLoader());
|
Spring Boot 1.x
Spring Boot 2.x进行了大量的重构,在运行Spring Boot 1.x时,您需要使用其他类来部署WAR。还请注意该try-catch块,这对于捕获方法抛出的已检查异常是必需的。
@Bean public EmbeddedServletContainerFactory servletContainerFactory() { return new TomcatEmbeddedServletContainerFactory() {
@Override protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer( Tomcat tomcat) {
new File(tomcat.getServer().getCatalinaBase(), "webapps").mkdirs(); try { tomcat.addWebapp("context-path", "path-to-your-war.war"); } catch (ServletException e) { log.error("Unable to deploy war to embedded Tomcat"); }
return super.getTomcatEmbeddedServletContainer(tomcat); }
}; }
|
如果您想更改Spring Boot应用程序的上下文路径,则该过程与2.x相同,除了其中的属性名称application.properties不同,这也适用于1.x版本server.context-path。
添加对JSP的支持
如果您的外部非Spring Boot WAR包含JSP,则需要确保为其提供适当的依赖项,因为嵌入式Tomcat默认情况下不包含它们。对于Maven,您可以使用:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency>
|
对于Gradle,请改用以下代码:
compile "org.apache.tomcat.embed:tomcat-embed-jasper" compile "javax.servlet:jstl"
|