스프링부트의 장점을 알아보기위해 저번시간에 부트의 내장 톰켓을 사용하지않고 톰켓을 직접깔고,서블릿,서블릿컨테이너, 스프링컨테이너, 디스패쳐서블릿 과 스프링컨테이너 연결 까지 해봤다.
이제 부트의 장점중 하나인 내장톰켓에 대해 알아보자
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();
}
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 = newAnnotationConfigWebApplicationContext();
appContext.register(HelloConfig.class);
//스프링 MVC 디스패처 서블릿 생성, 스프링 컨테이너 연결
DispatcherServlet dispatcher = new DispatcherServlet(appContext);
//디스패처 서블릿 등록
Context context = tomcat.addContext("", "/");
tomcat.addServlet("", "dispatcher", dispatcher);
context.addServletMappingDecoded("/", "dispatcher");
tomcat.start();**텍스트**
}
main 메서드를 실행하기 위해서는 jar로 빌드 해야함
jar 로 코드를 추출시 META-INF/MANIFEST.MF 에 실행할 main메서드의 클래스를 지정해줘야한다.
JAR는 JAR파일을 포함할수 없다
- WAR와 다르게 JAR는 라이브러리 역활을 하는 JAR를 포함할 수 없다.
public static void run(Class configClass, String[] args) {
//내장톰켓설정 코드
..
//스프링 컨테이너 설정 코드
AnnotationConfigWebApplicationContext appContext = new
AnnotationConfigWebApplicationContext();
appContext.register(configClass);
//디스패처 서블릿, 스프링 컨테이너 연결 코드
..
//디스패처 서블릿 -> 서블릿 컨테이너에 등록 코드
..
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ComponentScan
public @interface MySpringBootApplication {
}
@MySpringBootApplication
public class MySpringBootMain {
public static void main(String[] args) {
System.out.println("MySpringBootMain.main");
MySpringApplication.run(MySpringBootMain.class, args);
}
- 애노테이션으로 컴포넌트 스캔뒤, 그것들을 run(configClass) 인자로 넘겨서 스프링컨테이너에 넣어줌
jar 내부에 jar를 포함할 수 있는 특별한 구조의 jar를 만들고 동시에 만든 jar를 내부 jar를 포함해서 실행할 수 있게 했다. 이것을 실행 가능 Jar(Executable Jar)라 한다.
jar안에 jar를 넣는 구조라 무슨 라이브러리가 들어왔는지 파악 가능하며, 같은 경로에 파일이 있어도 파악 가능
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: hello.boot.BootApplication
Spring-Boot-Version: 3.0.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Build-Jdk-Spec: 17
하지만 실제로 MAINFEST.MF코드에 들어가보면 예상했던 main메서드가 있는 class 가 아닌 JarLauncher이 실행 됀다.
JarLauncher 은 스프링부트가 넣어준 것이며 스프링부투는 fatJar를 개선하기 위해 jar를 포함할수 있는 특별한 구조의 jar를 만들어 놓는다고 했다. 바로 JarLauncher가 이 특별한 구조를 읽는 장치다. 그 뒤로 우리가 예상했던 main 메서드 실행!
JarLauncher - >Main메서드