Spring Boot 내장 톰캣의 서블릿, 리스너, 필터 등록

soomin·2021년 8월 18일
0

출처 : https://programmer.group/spring-boot-configuration-servlet-filter-listener.html

스프링 부트의 서블릿 컨테이너


스프링 부트 어플리케이션 내부에서 작동하는 내장 Servlet 3.0+ 컨테이너는 ServletContainerInitializerWebApplicationInitializer 를 직접적으로 사용하지 않는다.

즉, 위의 2개 인터페이스를 구현하여 설정한 FilterListener 는 올바르지 못하다.

이는 타사 코드의 설계가 응용 프로그램을 손상시키지 못하게 하기 위해 의도적으로 고려된 설계이다.

임베디드 서블릿 컨테이너는 Servlet 3.0+ javax.servlet.ServletContainerInitializer 인터페이스 또는 Spring의 org.springframework.web.WebApplicationInitializer 인터페이스를 직접 실행하지 않습니다.

이것은 war 파일 내에서 실행되도록 설계된 타사 라이브러리가 Spring Boot 애플리케이션을 중단시킬 위험을 줄이기 위한 의도적인 설계 결정입니다.



스프링 부트에서 사용하는 서블릿 컨테이너 설정 방법


spring boot 의 내장 서블릿 컨테이너는 위 문단의 인터페이스를 사용하지않기 때문에, 설정이 필요하다면

org.springframework.boot.context.embedded.ServletContextInitializer 인터페이스를 Bean 으로 등록해야한다.

해당 인터페이스는 함수형 인터페이스이며, #onStartUp() 함수를 구현하여 서블릿 컨텍스트에 접근 가능하다.



1. onStartUp() 함수 안에 서블릿 설정을 전부 작성하기


  • #onStartUp() 은 서블릿 컨텍스트 초기화 시 작동하는 로직을 기술하는 함수
  • 필터, 리스너, 세션 타임아웃등을 설정 가능
@Configuration
public class ServletConfig implements ServletContextInitializer {
@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.setSessionTimeout(30);// 분
        servletContext.setInitParameter("resource","classpath:resources/application.yaml");

        // 캐릭터 인코딩 필터

        FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);

        characterEncodingFilter.setInitParameter("encoding","UFT-8");
        characterEncodingFilter.setInitParameter("forceEncoding","true");
        characterEncodingFilter.addMappingForUrlPatterns(
                EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE,DispatcherType.ASYNC), // 디스패치타입
                false, // false = 전 작동 , true = 후 작동
                "/*"
        );
        characterEncodingFilter.setAsyncSupported(true);

        servletContext.addListener(new ServletContextListener() {
            @Override
            public void contextInitialized(ServletContextEvent sce) {
                System.out.println("내장 톰캣 기동");
            }

            @Override
            public void contextDestroyed(ServletContextEvent sce) {
                System.out.println("내장 톰캣 종료");
            }
        });
    }
}



2. 자동 등록 방법


ServletContextInitinalizerRegistrationBean 이 구현하고 있으며, 하위의 3개의 클래스가 다시 RegistrationBean 을 상속하고 있다.

RegistrationBean 을 상속하고 있는 3개의 하위클래스는 런타임에 Servlet & Filter & Listener 를 자동 등록하는 역할을하며, 해당 클래스는 전부 SpringBean 이여야만 합니다.

  1. ServletRegistrationBean : ServletContainer 가 초기화될 때, ServletContext 에 CustomServlet 을 등록시킨다.
  2. ServletListenerRegistrationBean : ServletContainer 가 초기화될 때, ServletContext 에 CustomServletContextListener 를 등록시킨다.
  3. AbstractFilterRegistartionBean : getFilter() 함수를 통해 Filter 생성과정을 하위클래스로 지연시키고 ServletContainer 가 초기화될 때, ServletContext 에 Filter 를 등록시킨다.

  • ServletRegistrationBean 설정
@Bean
public ServletRegistrationBean servletRegistrationBean(ServletContext servletContext) {
    ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
    // 설정정보 기입
    return  servletRegistrationBean;
}

  • ServletListenerRegistrationBean 설정
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean() {
    ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
    // 리스너추가
    return servletListenerRegistrationBean;
}

  • FilterRegistrationBean 설정
@Bean
public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CharacterEncodingFilter());
    filterRegistrationBean.addUrlPatterns("/*");
    filterRegistrationBean.setAsyncSupported(true);

    Map<String ,String > initParam = new HashMap<>();
    initParam.put("encoding","UTF-8");
    initParam.put("forceEncoding","true");
    filterRegistrationBean.setInitParameters(initParam);

    return filterRegistrationBean;
}
profile
블로그 유목민

0개의 댓글