스프링 부트:내장된 Tomcat에 다른 WAR 파일을 추가하려면 어떻게 해야 합니까?
Spring Boot에 내장된 Tomcat은 개발 및 도입에 매우 편리합니다.
그러나 다른 (서드파티제의) WAR 파일(예: GeoServer)을 추가해야 하는 경우에는 어떻게 해야 합니까?
통상적인 순서는 다음과 같습니다.
- 일반 Tomcat 서버를 설치합니다.
- Spring Boot 애플리케이션을 WAR 파일로 빌드하여 Tomcat의 webapps 폴더에 추가합니다.
- 다른 (서드파티제의) WAR 파일도 webapps 폴더에 추가합니다.
하지만 다음과 같은 구성이 가능하다면 좋을 것 같습니다.
- Spring 부팅 응용 프로그램을 내장된 Tomcat을 포함하는 독립 실행형 Jar로 빌드합니다.
- 스프링 부트 애플리케이션 Jar를 전개합니다.
- 내장된 Tomcat이 인식하는 폴더에 다른 (서드파티제의) WAR 파일을 추가합니다.
- 내장된 Tomcat을 사용하여 Spring 부팅 응용 프로그램 콘텐츠와 다른 WAR 콘텐츠를 모두 처리합니다.
어떻게 할 수 있을까요?
갱신하다
스프링 부트 어플리케이션이 fat jar(=sublicable 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을 추가한 스프링 부트애플리케이션의 fat jar에 라이브러리 jar를 로드할 수 없습니다.
다음을 사용하여 내장 Tomcat에 전쟁 파일을 추가할 수 있습니다.Tomcat.addWebapp
javadoc이 말하는 것처럼 "Tomcat의 웹 앱 디렉토리에 웹 애플리케이션을 추가하는 것과 동등합니다."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 1.x 입니다.이 클래스는 Spring Boot 2.x에는 존재하지 않게 되었습니다.버전 2를 사용할 때는 다른 버전을 사용해야 합니다.
@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();
Context context = tomcat.addWebapp(contextPath, path);
context.setParentClassLoader(getClass().getClassLoader());
return super.getTomcatWebServer(tomcat);
}
};
}
또한 Spring boot enbedded Tomcat에는 기본적으로 JSP에 대한 의존관계가 포함되어 있지 않습니다.외부 전쟁에서 JSP를 사용하는 경우 JSP를 포함해야 합니다.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
업데이트: Spring Boot 1과 Spring Boot 2의 셋업 방법에 대한 자세한 블로그 투고를 작성했습니다.
Spring Boot 2의 경우 답변이 모두 제대로 작동하지 않았기 때문에 이 문제를 해결하는 데 시간이 걸렸습니다.드디어 다음과 같은 것이 생각났습니다(SSL이 유효하게 되어 있는 경우).WarRun.java와 Gradle 의존관계를 아래에 나타냅니다.
장점:
컨텍스트 경로 포함 Tomcat / at https://localhost:8070
sample.war at https://localhost:8070/sample
샘플 Web Apphttps://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);
}
};
}
}
그라들:
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'
}
언급URL : https://stackoverflow.com/questions/31374726/spring-boot-how-to-add-another-war-files-to-the-embedded-tomcat
'programing' 카테고리의 다른 글
babel을 사용한 후 IE에서 '심볼'이 정의되지 않음 (0) | 2023.03.05 |
---|---|
mongodb ID에서 타임스탬프를 가져오는 중 (0) | 2023.03.05 |
permalinks 워드프레스 변경 후 404 오류 발생 (0) | 2023.03.05 |
jQuery AJAX를 사용하여 여러 데이터 매개 변수 전송 (0) | 2023.03.05 |
Oracle "파티션 기준" 키워드 (0) | 2023.03.05 |