starter run deploy spring tomcat spring-boot

run - spring boot war gradle



Spring Boot: ¿Cómo agregar otros archivos WAR al tomcat incrustado? (2)

Me tomó un tiempo resolver esto para Spring Boot 2 ya que ninguna de las respuestas funcionó completamente para mí. Finalmente se me ocurrió esto (para mi tengo SSL activado): WarRun.java con las dependencias de Gradle a continuación para que funcione.

Lo que da:

Tomcat incrustado con ruta de contexto / en https: // localhost: 8070

sample.war en https://localhost:8070/sample

SampleWebApp.war en https://localhost:8070/yo

import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.Properties; import org.apache.catalina.Context; import org.apache.catalina.startup.Tomcat; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Profile; import org.springframework.core.io.ClassPathResource; @ComponentScan({ "com.towianski.controllers" }) @SpringBootApplication @Profile("server") public class WarRun extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(WarRun.class).web( WebApplicationType.SERVLET ); } public static void main(String[] args) { SpringApplication app = new SpringApplication(WarRun.class); System.out.println( "Entered WarRun.main"); String loggingFile = ""; String dir = ""; for ( int i = 0; i < args.length; i++ ) { // logger.info( "** args [" + i + "] =" + args[i] + "=" ); System.out.println( "** args [" + i + "] =" + args[i] + "=" ); if ( args[i].toLowerCase().startsWith( "-dir" ) ) { dir = args[i].substring( "-dir=".length() ); } else if ( args[i].toLowerCase().startsWith( "--logging.file" ) ) { loggingFile = args[i].substring( "--logging.file=".length() ); stdOutFilePropertyChange( loggingFile ); stdErrFilePropertyChange( loggingFile ); } } Properties properties = new Properties(); // properties.setProperty( "spring.resources.static-locations", // "classpath:/home/stan/Downloads" ); properties.setProperty( "server.port", "8070" ); // System.setProperty("server.servlet.context-path", "/prop"); <--- Will set embedded Spring Boot Tomcat context path properties.setProperty( "spring.security.user.name", "stan" ); properties.setProperty( "spring.security.user.password", "stan" ); System.out.println( "Entered WarRun.main after set properties"); app.setDefaultProperties(properties); System.out.println( "Entered WarRun.main after call set props. before app.run"); app.run(args); System.out.println( "Entered WarRun.main after app.run()"); } @Bean public ServletWebServerFactory servletContainer() { return new TomcatServletWebServerFactory() { protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { System.out.println( "tomcat.getServer().getCatalinaBase() =" + tomcat.getServer().getCatalinaBase() + "=" ); new File(tomcat.getServer().getCatalinaBase(), "/webapps").mkdirs(); // try { // Files.copy( (new File( "/home/stan/Downloads/sample.war" ) ).toPath(), (new File( tomcat.getServer().getCatalinaBase() +"/webapp/sample.war") ).toPath()); // } catch (IOException ex) { // Logger.getLogger(WarRun.class.getName()).log(Level.SEVERE, null, ex); // } try { System.out.println( "Entered ServletWebServerFactory servletContainer()"); Context context2 = tomcat.addWebapp("/sample", new ClassPathResource("file:/home/stan/Downloads/sample.war").getFile().toString()); Context context3 = tomcat.addWebapp("/yo", new ClassPathResource("file:/home/stan/Downloads/SampleWebApp.war").getFile().toString()); // Context context = tomcat.addWebapp("/what", new ClassPathResource( "file:" + tomcat.getServer().getCatalinaBase() +"/webapps/sample.war" ).getFile().toString() ); context2.setParentClassLoader(getClass().getClassLoader()); context3.setParentClassLoader(getClass().getClassLoader()); // also works but above seems better // WebappLoader loader2 = new WebappLoader(Thread.currentThread().getContextClassLoader()); // WebappLoader loader3 = new WebappLoader(Thread.currentThread().getContextClassLoader()); // context2.setLoader(loader2); // context3.setLoader(loader3); } catch (IOException ex) { ex.printStackTrace(); } return super.getTomcatWebServer(tomcat); } }; } }

Gradle:

apply plugin: ''war'' war { enabled = true } . . . . dependencies { compile("org.springframework.boot:spring-boot-starter:2.1.6.RELEASE") compile("org.springframework.boot:spring-boot-starter-web:2.1.6.RELEASE") compile group: ''org.apache.tomcat.embed'', name: ''tomcat-embed-jasper'', version: ''9.0.21'' compile("org.springframework.boot:spring-boot-starter-security:2.1.6.RELEASE") compile ''org.apache.httpcomponents:httpclient:4.5.7'' compile group: ''org.codehaus.groovy'', name: ''groovy-all'', version: ''2.5.6'' compile fileTree(dir: ''libs'', include: [''*.jar'']) compile ''com.jcraft:jsch:0.1.55'' testCompile group: ''junit'', name: ''junit'', version: ''4.12'' }

El gato incrustado de Spring Boot es muy útil, tanto para el desarrollo como para la implementación.

Pero, ¿qué sucede si se debe agregar otro archivo WAR (de terceros) (por ejemplo, GeoServer)?

Quizás el siguiente es el procedimiento normal:

  1. Instale un servidor Tomcat normal.
  2. Cree la aplicación Spring Boot como un archivo WAR y agréguelo a la carpeta webapps de Tomcat.
  3. Agregue también otro archivo WAR (de terceros) a la carpeta webapps.

Pero sería bueno si la siguiente configuración fuera posible.

  1. Cree la aplicación de arranque Spring como un Jar independiente, que incluye el Tomcat incorporado.
  2. Implemente la aplicación de arranque Spring Jar.
  3. Agregue otro archivo WAR (de terceros) a una carpeta que reconoce Tomcat incrustado.
  4. Sirva tanto el contenido de la aplicación de arranque Spring como el contenido de otro WAR utilizando el Tomcat incorporado.

¿Cómo puede hacerse esto?

ACTUALIZAR

Cuando la aplicación de arranque de primavera está hecha de jar jar (= jar ejecutable), el código en la respuesta no es suficiente. El revisado es el siguiente:

@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); } }; }

Dado que los archivos jar en un jar gordo no pueden ser cargados por el cargador de clases del sistema, se debe especificar un cargador de clases padre explícito. De lo contrario, el WAR adicional no puede cargar los tarros de la biblioteca en el tarro gordo de la aplicación de arranque de primavera que agregó el WAR.


Puede agregar un archivo war a Tomcat incrustado usando Tomcat.addWebapp . Como dice su javadoc, es el "equivalente a agregar una aplicación web al directorio de aplicaciones web de Tomcat". Para usar esta API en Spring Boot, debe usar una subclase personalizada 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); } }; }