스프링 내장톰캣

justindevcode·2024년 4월 28일
0

스프링부트

목록 보기
16/39
post-thumbnail

스프링 내장톰캣

내장톰캣 기능 제공

기존의 war파일은 무조건 서버위에서만 실행되던 파일이였다 그런데 톰캣도 자바인데 라이브러리로 내장으로 가질수는없을까? 해서 나온것이 내장톰캣

dependencies {
 //스프링 MVC 추가
 implementation 'org.springframework:spring-webmvc:6.0.4'
 //내장 톰캣 추가
 implementation 'org.apache.tomcat.embed:tomcat-embed-core:10.1.5'
}
.
.
.
//일반 Jar 생성
task buildJar(type: Jar) {
 manifest {
 attributes 'Main-Class': 'hello.embed.EmbedTomcatSpringMain'
 }
 with jar
}

이정도 디펜던시를 사용하면 쓸 수 있다. jar생성 task도 추가

이전의

  • hello.servlet.HelloServlet
  • hello.spring.HelloController
  • hello.spring.HelloConfig
    코드가 있다고할때
    main함수에 이정도만 써주면 일단 톰캣을 사용할 수 있다.
public class EmbedTomcatServletMain {
 public static void main(String[] args) throws LifecycleException {
 System.out.println("EmbedTomcatServletMain.main");
 //톰캣 설정
 Tomcat tomcat = new Tomcat();
 Connector connector = new Connector();
 connector.setPort(8080);
 tomcat.setConnector(connector);
 //서블릿 등록
 Context context = tomcat.addContext("", "/");
 tomcat.addServlet("", "helloServlet", new HelloServlet());
 context.addServletMappingDecoded("/hello-servlet", "helloServlet");
 tomcat.start();
 }
}

톰캣생성 -> 포트연결 -> 톰캣서블릿등록 -> 경로등록 -> 스타트
이러고 http://localhost:8080/hello-servlet로 요청보내면 지정된 컨트롤러가 실행된다.

이걸기반으로 스프링을 등록하는거도 똑같다.

public class EmbedTomcatSpringMain {
 public static void main(String[] args) throws LifecycleException {
 System.out.println("EmbedTomcatSpringMain.main");
 //톰캣 설정
 Tomcat tomcat = new Tomcat();
 Connector connector = new Connector();
 connector.setPort(8080);
 tomcat.setConnector(connector);
 //스프링 컨테이너 생성
 AnnotationConfigWebApplicationContext appContext = new
AnnotationConfigWebApplicationContext();
 appContext.register(HelloConfig.class);
 //스프링 MVC 디스패처 서블릿 생성, 스프링 컨테이너 연결
 DispatcherServlet dispatcher = new DispatcherServlet(appContext);
 //디스패처 서블릿 등록
 Context context = tomcat.addContext("", "/");
 tomcat.addServlet("", "dispatcher", dispatcher);
 context.addServletMappingDecoded("/", "dispatcher");
 tomcat.start();
 }
}

위랑 비슷하게 스프링 컨테이너를 실행하고 내장톰캣에 디스패처 서블릿을 등록해줬다. 그러고 실행
http://localhost:8080/hello-spring 똑같이 요청해주면 응답이 나온다.

사실 진짜 톰캣을 딥하게 직접 사용하려면 여러 예외처리와 이것저것 해줘야할게 많은데 배워야할게 많으니 이정도만 이해하고 넘어가도된다.

빌드와 배포

우리는 이제 순수 자바의 main 메소드만 실행하면 되기때문에 jar로 빌드해주면된다.
그리고 jar는 META-INF/MANIFEST.MF파일안에 main() 메서드의 클래스를 지정해줘야하는데

task buildJar(type: Jar) {
 manifest {
 attributes 'Main-Class': 'hello.embed.EmbedTomcatSpringMain'
 }
 with jar
}

task에 그부분을 같이 넣어줬다.

./gradlew clean buildJar하고 build/libs/embed-0.0.1-SNAPSHOT.jar위치에 java -jar embed-0.0.1-SNAPSHOT.jar이거 실행해주면???

안된다;;;;

왜냐하면 embed-0.0.1-SNAPSHOT.jar를 까보면 우리가 라이브러리 등록한 MVC, 톰캣 라이브러리가 아에없다.
기본적인 jar는 war와 다르게 lib폴더에 라이브러리 jar를 포함할 수 없고, jar안에 다른 jar를 포함하지 못하도록 규정되어있다.

그래서 나온방법

task buildFatJar(type: Jar) {
 manifest {
 attributes 'Main-Class': 'hello.embed.EmbedTomcatSpringMain'
 }
 duplicatesStrategy = DuplicatesStrategy.WARN
 from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : 
zipTree(it) } }
 with jar
}

task에 FatJar추가 -> 내가 등록한 라이브러리의 jar도 모두 압축해제해서 class파일로 전부까서 기존의 내 코드와 합쳐 jar만들기

이렇게하면 java -jar embed-0.0.1-SNAPSHOT.jar실행했을때 INFO: Starting ProtocolHandler ["http-nio-8080"]서버가 띄워진다.

다만 이방법도 단점이 있는데 META-INF/services/jakarta.servlet.ServletContainerInitializer이런 기초적인 서블릿등록파일이 여러 라이브러리에 동시에있을 수 있다.
이경우 한쪽이 버려지거나 하는데 이러면 버려진쪽은 아에 실행이 안된다.

그렇지만 이런문제들까지 스프링부트가 해결해준다. 다음에 알아보기

profile
("Hello World!");

0개의 댓글