WEB/Spring Boot

웹 서버와 서블릿 컨테이너

Tony Lim 2023. 5. 8. 14:44

서블릿 컨테이너 초기화2 (Servelt App 의 유연한 초기화)

@HandlesTypes(AppInit.class)
public class MyContainerInitV2 implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        System.out.println("MyyContainerInitV2.onStartup");
        System.out.println("c = " + c);
        System.out.println("ctx = " + ctx);

        for (Class<?> appInitClass: c) {
            try {
                AppInit appInit = (AppInit) appInitClass.getDeclaredConstructor().newInstance();
                appInit.onStartup(ctx);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

ServletContainer 초기화에서 말고 나만의 servlet application을 초기화를 진행할 수 있다. AppInit은 내가만든 interface이고 딱히 ServletContext같은것을 넘겨줄 필요 없이 

위와 같이 세팅을 해놓으면 ServerletContainer가 초기화 되는 시점에 @HandleTypes에서 지정한 클래스들의 구현체(interface이니까) 를 루프를 돌면서 초기화 작업을 진행시킬 수 있다.


스프링 컨테이너 등록

public class AppInitV2Spring implements AppInit{
    @Override
    public void onStartup(ServletContext servletContext) {
        System.out.println("AppInitV2Spring.onStartup");

        // create spring container
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(HelloConfig.class);

        // create spring mvc dispatcher servlet and connect with spring container
        DispatcherServlet dispatcher = new DispatcherServlet(appContext);

        // enroll dispatcher servlet to tomcat servlet container (look out for naming)
        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcherV2", dispatcher);

        // configure dispatcher servlet to handle http request that has url "/spring/*"
        servlet.addMapping("/spring/*");
    }
}

appContext = 스프링 컨테이너를 생성하고 HellConfig 를 통해 필요한 bean들을 등록한다.

Dispatcher servlet으로 하여금 스프링 컨테이너를 알게 하고 어떤 url을 처리해야하는지 알려준다.


스프링 MVC 서블릿 컨테이너 초기화 지원

public class AppInitV3SpringMvc implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.out.println("AppInitV3SpringMvc.onStartup");

        // create spring container
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(HelloConfig.class);

        // create spring mvc dispatcher servlet and connect with spring container
        DispatcherServlet dispatcher = new DispatcherServlet(appContext);

        // enroll dispatcher servlet to tomcat servlet container (look out for naming "dispatcherV3")
        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcherV3", dispatcher);

        // configure dispatcher servlet to handle every http request"
        servlet.addMapping("/");
    }
}

WebApplicationInitializer 는 스프링에서 만들어둔 애플리케이션 초기화 인터페이스이다. V2와 동일한 코드내용이고 실행하게 되면

그림과 같이 2개의 spring container 와 2개의 dispatcher servlet이 생기게된다. HelloController에서 this를 찍어보면 @{number} 가달라 다른 객체임을 알 수 있다.

위에서 했던 AppInit처럼 SpringServletContainerInitializer 에도 @HandleTypes(WebApplicationInitializer.class) 가 존재해서 구현체들을 불러와서 onStartup을 호출하게 된다.