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

在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:(模板方法模式)通过模板方法 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 配置示例

@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()); } }
 
« 上一篇:  SpringBoot 配置静态资源映射 
» 下一篇:  Spring Security Oauth2 示例
 
___________________________________________________________________________________________
需求:springboot 启动后自动执行某些代码,初始化数据,并将数据放到 servletContext 中。

首先,不可使用 ServletContextListener 即不能用 @WebListener ,因为 servlet 容器初始化后,spring 并未初始化完毕,不能使用 @Autowired 注入 spring 的对象。

推荐使用 ApplicationListener:启动项目, spring 加载完毕后,才执行该 ApplicationListener,并且该 Listener 中可以使用 spring 的内容。

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

需求:springboot 启动后自动执行某些代码,初始化数据,并将数据放到 servletContext 中。

首先,不可使用 ServletContextListener 即不能用 @WebListener ,因为 servlet 容器初始化后,spring 并未初始化完毕,不能使用 @Autowired 注入 spring 的对象。

推荐使用 ApplicationListener:启动项目, spring 加载完毕后,才执行该 ApplicationListener,并且该 Listener 中可以使用 spring 的内容。

  1.  
    @Component
  2.  
    public class SettingDataInitListener implements ApplicationListener<ContextRefreshedEvent> {
  3.  
        @Override
  4.  
        public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
  5.  
            // 将 ApplicationContext 转化为 WebApplicationContext 
  6.  
            WebApplicationContext webApplicationContext = 
  7.  
                (WebApplicationContext)contextRefreshedEvent.getApplicationContext();
  8.  
            // 从 webApplicationContext 中获取  servletContext 
  9.  
            ServletContext servletContext = webApplicationContext.getServletContext();
  10.  
            // servletContext设置值
  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:(模板方法模式)通过模板方法 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 配置示例

@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()); } }

猜你喜欢

转载自www.cnblogs.com/kelelipeng/p/11412138.html