Spring Boot:如何添加另一个WAR文件到嵌入式tomcat?

Spring Boot的嵌入式tomcat非常方便,用于开发和部署。

但是如果应该添加另一个(第三方)WAR文件(例如GeoServer)呢?

以下是正常的程序:

>安装正常的Tomcat服务器。
>将Spring Boot应用程序构建为WAR文件,并将其添加到Tomcat的webapps文件夹中。
>另外添加另一个(第三方)WAR文件到webapps文件夹。

但如果可以进行以下配置,那将是很好的。

>将Spring引导应用程序构建为独立的Jar,其中包括嵌入式Tomcat。
>部署Spring引导应用程序Jar。
>将另一个(第三方)WAR文件添加到嵌入式Tomcat识别的文件夹中。
>使用嵌入式Tomcat同时使用Spring引导应用程序内容和另一个WAR的内容。

怎么办?

UPDATE

当spring引导应用程序由fat jar(=可执行jar)组成时,答案中的代码是不够的。修改如下:

@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            try {
                Context context = tomcat.addWebapp("/foo", "/path/to/foo.war");
                WebappLoader loader =
                    new WebappLoader(Thread.currentThread().getContextClassLoader());
                context.setLoader(loader);
            } catch (ServletException ex) {
                throw new IllegalStateException("Failed to add webapp", ex);
            }
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

    };
}

由于fat jar中的jar文件无法由系统类加载器加载,因此必须指定一个显式的父类加载器。否则,额外的WAR无法将库jar加载到添加了WAR的弹簧启动应用程序的胖子中。

最佳答案
您可以使用Tomcat.addWebapp将一个war文件添加到嵌入式Tomcat中。正如其javadoc所说,这是“相当于将Web应用程序添加到Tomcat的Web应用程序目录”。要在Spring Boot中使用此API,您需要使用自定义的TomcatEmbeddedServletContainerFactory子类:

@Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            // Ensure that the webapps directory exists
            new File(tomcat.getServer().getCatalinaBase(), "webapps").mkdirs();

            try {
                Context context = tomcat.addWebapp("/foo", "/path/to/foo.war");
                // Allow the webapp to load classes from your fat jar
                context.setParentClassLoader(getClass().getClassLoader());
            } catch (ServletException ex) {
                throw new IllegalStateException("Failed to add webapp", ex);
            }
            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

    };
}

转载注明原文:Spring Boot:如何添加另一个WAR文件到嵌入式tomcat? - 代码日志