SpringBoot 配置 Servlet、Filter、Listener

SpringBoot 配置 Servlet、Filter、Listener

在SpringBoot應用中,嵌入式的 Servlet 3.0+ 容器不會直接使用 ServletContainerInitializer 和 WebApplicationInitializer,即經過以上兩個接口實現的 Servlet、Filter、Listener 配置都是無效的,這是爲了防止第三方代碼的設計損壞應用程序,原文以下java

Embedded servlet containers will not directly execute the Servlet 3.0+ javax.servlet.ServletContainerInitializer interface, or Spring’s org.springframework.web.WebApplicationInitializer interface. This is an intentional design decision intended to reduce the risk that 3rd party libraries designed to run inside a war will break Spring Boot applications.web

If you need to perform servlet context initialization in a Spring Boot application, you should register a bean that implements the org.springframework.boot.context.embedded.ServletContextInitializer interface. The single onStartup method provides access to the ServletContext, and can easily be used as an adapter to an existing WebApplicationInitializer if necessary.spring

綜上,能夠採起如下配置springboot

配置策略一:ServletContextInitializer

由官方原文可知,咱們能夠使用替代方案:ServletContextInitializer,示例以下app

@Configuration
public class GoServletContextInitializer implements ServletContextInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        //配置 Log4j Config Listener  
        servletContext.setInitParameter("log4jConfigLocation", "classpath:config/properties/log4j.properties");  
        servletContext.addListener(Log4jConfigListener.class);  
          
          
        //配置 CharacterEncodingFilter
        FilterRegistration.Dynamic characterEncodingFilter =
                servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class);
        characterEncodingFilter.setInitParameter("encoding", "UTF-8");
        characterEncodingFilter.setInitParameter("forceEncoding", "true");
        characterEncodingFilter.addMappingForUrlPatterns(
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE),
                false, "/*");
          
          
        //配置 statViewServlet  
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistration.Dynamic dynamic = servletContext.addServlet(
                "statViewServlet", statViewServlet);
        dynamic.setLoadOnStartup(2);
        dynamic.addMapping("/druid/*");
    }
}

親測,即便將 Spring Boot 打包成 war,並部署到 Tomcat 8.5,這份配置也是有效的ide


配置策略二:ServletContextInitializer 的延伸

請看類繼承體系ui

原理:最下邊的三個子類會自動在運行時註冊 Servlet、Listener、Filter(必定要將其定義爲 Spring 容器的 Bean)spa

  1. ServletRegistrationBean:在Servlet容器初始化時,向 ServletContext 註冊一個自定義的 Servlet
  2. ServletListenerRegistrationBean:在Servlet容器初始化時,向 ServletContext 註冊一個自定義的 ServletContextListener
  3. AbstractFilterRegistrationBean:(模板方法模式)經過模板方法 getFilter(),將 Filter 的構建過程延遲到子類,並在Servlet容器初始化時,向 ServletContext 註冊該 Filter。開發者能夠定義一個子類來重寫該模板方法,以配置一個自定義的 Filter。

Servlet 配置示例設計

@Configuration
public class ServletConfig {

    //配置 StatViewServlet
    @Bean
    public ServletRegistrationBean servletRegistration0() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet());
        registration.addUrlMappings("/druid/*");
        registration.setLoadOnStartup(0);
        return registration;
    }
}

Filter 配置示例code

@Configuration
public class FilterConfig {

    //配置 CharacterEncodingFilter
    @Bean
    public FilterRegistrationBean filterRegistration1() {
        FilterRegistrationBean registration = new FilterRegistrationBean(new CharacterEncodingFilter());
        registration.addUrlPatterns("/*");

        Map<String, String> initParameters = Maps.newHashMap();
        initParameters.put("encoding", "UTF-8");
        initParameters.put("forceEncoding", "true");
        registration.setInitParameters(initParameters);
        
        return registration;
    }
}

Listener 配置示例

@Configuration
public class ListenerConfig {

    //配置 RequestContextListener
    @Bean
    public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() {
        return new ServletListenerRegistrationBean<>(
            new RequestContextListener());
    }
}
相關文章
相關標籤/搜索