SpringBoot 配置 Servlet、Filter、Listener

https://www.cnblogs.com/pomer-huang/p/9639322.html

https://blog.csdn.net/qq_38709999/article/details/99986797

SpringBoot 配置 Servlet、Filter、Listener

In SpringBoot application, embedded Servlet 3.0+ container and not directly ServletContainerInitializer WebApplicationInitializer, i.e. through two or more interfaces implemented Servlet, Filter, Listener configuration are invalid, which is designed to prevent damage to the application of the third-party code program, reads as follows

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.

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.

In summary, you can take the following configurations

A configuration policies: ServletContextInitializer

By the official text it shows that we can use alternatives: ServletContextInitializer, examples are as follows

@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/*"); } }

Pro-test, even if the Spring Boot packaged into WAR, and deployed to Tomcat 8.5, this configuration is effective


Configuration Strategy Two: Extension of ServletContextInitializer

See class inheritance system

Principle: lowermost three subclasses will be automatically registered at runtime Servlet, Listener, Filter (sure to be defined as Bean Spring container)

  1. ServletRegistrationBean: When initializing Servlet container, ServletContext to register a custom Servlet
  2. ServletListenerRegistrationBean: When initializing Servlet container, ServletContext to register a custom ServletContextListener
  3. AbstractFilterRegistrationBean :( Template Method) The method of the getFilter template (), the process delays to build Filter subclasses, and when initializing Servlet container, to register the ServletContext Filter. Developers can define a subclass to override the template method, Filter to configure a custom.

Servlet configuration example

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

Filter Configuration Example

@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 example

@Configuration
public class ListenerConfig { //配置 RequestContextListener @Bean public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() { return new ServletListenerRegistrationBean<>( new RequestContextListener()); } }
 
<<  Previous:  SpringBoot configure a static resource mapping  
>>  Next Article:  the Spring Security Oauth2 example
 
___________________________________________________________________________________________
Demand: automate some springboot start code, the initialization data and the data into servletContext. 

First, i.e., can not not be used ServletContextListener @WebListener, because the initialization servlet container, spring is not initialized, the object can not use the spring @Autowired injection. 

Recommended ApplicationListener: start the project, spring loaded only after the implementation of the ApplicationListener, and the Listener can use the content of spring. 

@Component 
public  class SettingDataInitListener the implements the ApplicationListener <ContextRefreshedEvent> { 
    @Override 
    public  void onApplicationEvent (ContextRefreshedEvent ContextRefreshedEvent) {
         // the ApplicationContext into the WebApplicationContext 
        the WebApplicationContext WebApplicationContext = 
            (WebApplicationContext)contextRefreshedEvent.getApplicationContext();
        // 从 webApplicationContext 中获取  servletContext 
        ServletContext servletContext = webApplicationContext.getServletContext();
        // servletContext设置值
        servletContext.setAttribute("key", "value");
    }

 

Demand: automate some springboot start code, the initialization data and the data into servletContext.

First, i.e., can not not be used ServletContextListener @WebListener, because the initialization servlet container, spring is not initialized, the object can not use the spring @Autowired injection.

Recommended ApplicationListener: start the project, spring loaded only after the implementation of the ApplicationListener, and the Listener can use the content of spring.

  1.  
    @Component
  2.  
    public class SettingDataInitListener implements ApplicationListener<ContextRefreshedEvent> {
  3.  
        @Override
  4.  
        public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
  5.  
            // The ApplicationContext into WebApplicationContext 
  6.  
            WebApplicationContext webApplicationContext = 
  7.  
                (WebApplicationContext)contextRefreshedEvent.getApplicationContext();
  8.  
            // Get the servletContext from webApplicationContext 
  9.  
            ServletContext servletContext = webApplicationContext.getServletContext();
  10.  
            // servletContext settings
  11.  
            servletContext.setAttribute( "key", "value");
  12.  
        }
  13.  

在SpringBoot应用中,嵌入式的 Servlet 3.0+ 容器不会直接使用 ServletContainerInitializer 和 WebApplicationInitializer,即通过以上两个接口实现的 Servlet、Filter、Listener 配置都是无效的,这是为了防止第三方代码的设计损坏应用程序,原文如下

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.

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.

综上,可以采取以下配置

配置策略一:ServletContextInitializer

由官方原文可知,我们可以使用替代方案:ServletContextInitializer,示例如下

@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,这份配置也是有效的


配置策略二:ServletContextInitializer 的延伸

请看类继承体系

原理:最下边的三个子类会自动在运行时注册 Servlet、Listener、Filter(一定要将其定义为 Spring 容器的 Bean)

  1. ServletRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 Servlet
  2. ServletListenerRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 ServletContextListener
  3. AbstractFilterRegistrationBean :( Template Method) The method of the getFilter template (), the process delays to build Filter subclasses, and when initializing Servlet container, to register the ServletContext Filter. Developers can define a subclass to override the template method, Filter to configure a custom.

Servlet configuration example

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

Filter Configuration Example

@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 example

@Configuration
public class ListenerConfig { //配置 RequestContextListener @Bean public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() { return new ServletListenerRegistrationBean<>( new RequestContextListener()); } }

Guess you like

Origin www.cnblogs.com/kelelipeng/p/11412138.html