6. 내장 톰캣
스프링 부트는 서버가 아닌 어플리케이션이며, 프레임워크 내장으로 Tomcat, Netty, Undertow, Jetty 서버를 사용할 수 있다.
톰캣만 사용하려면 @SpringBootApplication 어노테이션를 빼고 Tomcat 객체를 생성하여 Context와 Servlet를 넣어주어서 사용할 수도 있다.
public static void main(String[] args) throws LifecycleException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
Context context = tomcat.addContext("/", "/");
HttpServlet servlet = new HttpServlet(){
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
PrintWriter writer = res.getWriter();
writer.println("<h1>HI</h1>");
}
};
String servletName = "helloServlet";
tomcat.addServlet("/", servletName, servlet);
context.addServletMappingDecoded("/", servletName);
tomcat.getConnector();
tomcat.start();
tomcat.getServer().await();
}
- Tomcat 객체를 생성
- 서버의 포트를 정의
- Tomcat에 Context 추가
- Servlet 객체를 생성하여 톰캣에 추가
- Context에 서블릿을 매핑
- Tomcat의 Conntector를 추가 (Tomcat 9 부터 사용)
- Tomcat실행 및 대기
스프링 부트 프레임워크는 이러한 서버를 정의 후 실행하기까지의 모든 절차를 자동으로 생성해주는데 그러한 작업은 @EnableAutoConfiguraion 에서 가져와준다.
org.springframework.boot:spring-boot-autoconfigure:2.2.6.RELEASE 의 라이브러리에 명시되어있는 spring.factories 에 보면
EnableAutoConfiguration 어노테이션이 사용되면 읽어들이는 bean의 리스트가 나열되어있는데 그중에 ServletWebServerFactoryAutoConfiguraion 클래스의 내부를 보면 @Import 항목에 EmbeddedTomcat.class 가 있다.
해당 정적클래스에 소스를 본다면 TomcatServletWebServerFactory 의 인스턴스를 생성하는데 그 객체에 getWebServer 메소드에 Tomcat 객체를 생성하고 위와 동일한 작업을 하고있는걸 볼수 있다.
Servlet MVC 라면 DispatcherServlet를 생성하여 ServletContainer에 등록해주어야하는데 이러한 작업 또한 DispatcherServletAutoConfiguration 클래스에서 정의하며 등록까지 해준다.
왜 Servlet과 Servlet Container와 서로 다른 클래스에서 연결해주는 작업을 해주는데 Servlet Container는 달라질수 있지만 Servlet은 달라지지 않기 때문이다.