Spring-Boot using embedded containers, how to configure a custom Filter it

Listener, FilterAnd Servletis the Java Web development process commonly used three components, wherein the highest frequency component Filter, often used to make a simple processing authority, the request header and filtering to prevent XSSattacks. If we use the traditional Spring MVC development, only the following configuration is required to file in Tomcat's web.xml:

<!-- 配置Listener -->
<listener>
    <listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> 

<!--配置Filter,这边配置了一个Filter,但是匹配了多个url-pattern-->
<!-- 以url-partern方式配置的filter中,如果有多个与当前请求匹配,则按web.xml中filter-mapping出现的顺序来运行-->
<filter>  
    <filter-name>filter1</filter-name>  
    <filter-class>com.csx.MyFilter</filter-class>  
</filter>  
<filter-mapping>
    <filter-name>filter1</filter-name>  
    <url-pattern>/url/a/*</url-pattern>  
</filter-mapping>  
<filter-mapping>  
    <filter-name>filter1</filter-name>  
    <url-pattern>/url/b/*</url-pattern>  
</filter-mapping>

<!--配置Servlet-->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.spring.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!-- 这边不建议写成/* -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

PS: When the container is started, the startup sequence of the above three components is Listener -> Filter -> Servlet, a method of side Amway memory: the memory to the boot sequence "Li (The Listener) issued (the Filter) divisions ( Servlet) "can be.

These three components configured in web.xml is relatively simple, but with the use of the development of Spring-Boot is an embedded container, and did not allow us to configure web.xml file. So in the end how to configure the Spring-Boot in Listener, Filterand Servletand other components of it?

This blog to Filtera column, introduce how to configure the Spring-Boot in Listener, Filterand Servletand other components.

One way: the Filter declared bean

From here we first define a Filter, Filter this effect is time to call a statistical interface.

public class TimeConsumingCalculationFilter implements Filter {

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest httpRequest=(HttpServletRequest)request;
            long startTime = System.nanoTime();
            logger.info(">>>>>>> Begin ["+httpRequest.getRequestURI()+"]...");
            try{
                chain.doFilter(request, response);
            }finally {
                long endTime = System.nanoTime();
                logger.info(">>>>>>> End ["+httpRequest.getRequestURI()+"]["+(endTime-startTime)/1000/1000.0+"ms].");
            }
        }

    }

Filter configuration above the Spring-Boot, we only need @Configurationto do the following configuration to file:

@Configuration
public class WebConfig {

    private static Logger logger = LoggerFactory.getLogger(WebConfig.class);

    @Bean
    public Filter filter1(){
        return new TimeConsumingCalculationFilter();
    }
}

Filter default above will intercept all requests. If we want to configure multiple interceptors, then just add a Bean method on it.

@Configuration
public class WebConfig {

    private static Logger logger = LoggerFactory.getLogger(WebConfig.class);

    @Bean
    public Filter filter1(){
        return new TimeConsumingCalculationFilter();
    }
    
    @Bean
    public Filter filter2() {
        return new TimeConsumingCalculationFilter2();
    }
}

The above two configuration code configured Filter, Filter default are two intercepts all requests are intercepted sequence: filter1 -> filter2. Side of the first logic configured to intercept Filter After Filter configuration after the interception. Of course, if we want to explicitly specify the order, then you can intercept the aid of @Ordernotes. However, note that this comment must be added to the class defined above.

@Order(Ordered.LOWEST_PRECEDENCE - 2)
public class TimeConsumingCalculationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       //your logic
    }

}
@Order(Ordered.LOWEST_PRECEDENCE - 1)
public class TimeConsumingCalculationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       //your logic
    }

}

PS: the larger the value of @Order value, the smaller the execution priority. The smaller the value, the higher the priority. Since the time when we define the order of execution, it is recommended to use @Order(Ordered.LOWEST_PRECEDENCE - 1)this form of configuration, the greater the Ordered.LOWEST_PRECEDENCE subtracted value, the higher the priority, so it looks more intuitive.

In addition, Spring also provides an OrderedFilterinterface that is Filterand Orderedthe combination of interfaces, and the principle is the same as above. You can look at situations.

The above advantages of this arrangement is very simple to configure, but the disadvantages are also obvious, is not flexible enough to configure default intercepts all requests.

Second way: @WebFilter way

@WebFilterAnnotations are notes provided in Servlet, Spring also supports this comment. @WebFilterFine-grained configuration can be more flexible than the above manner.

@Configuration
public class WebConfig {
    //可以自定义url-pattern
    @WebFilter(urlPatterns="/*")
    @Order(Ordered.LOWEST_PRECEDENCE - 2)
    //这边如果不加`@Configuration`,需要通过`@ServletComponentScan`扫描`Listener`、`Filter`和`Servlet`这三个组件
    @Configuration
    public class TimeConsumingCalculationFilter implements Filter {

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //your logic
        }
    }   
    
    @WebFilter(urlPatterns="/*")
    @Order(Ordered.LOWEST_PRECEDENCE - 2)
    //这边如果不加`@Configuration`,需要通过`@ServletComponentScan`扫描`Listener`、`Filter`和`Servlet`这三个组件
    @Configuration
    public class TimeConsumingCalculationFilter2 implements Filter {

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //your logic
        }
    }   
    
}

By @WebFilterannotations arranged Filter simple, and the ability to customize and intercept url-pattern sequence.

Three ways: using FilterRegistrationBean Configuration

@Configuration
public class WebConfig {

    private static Logger logger = LoggerFactory.getLogger(WebConfig.class);

    @Bean
        public FilterRegistrationBean<Filter> filter1() {
            FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setName("filter1");
            registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 2);
            registrationBean.setFilter(new TimeConsumingCalculationFilter());
            registrationBean.addUrlPatterns("/foo/*");
            return registrationBean;
        }
    
    
        @Bean
        public FilterRegistrationBean<Filter> filter2() {
            FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setName("filter2");
            registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 3);
            registrationBean.setFilter(new TimeConsumingCalculationFilter1());
            registrationBean.addUrlPatterns("/*");
            registrationBean.addInitParameter("key1","value1");
            registrationBean.addInitParameter("key2","value2");
            //通过Servlet name匹配Filter,不建议使用
            registrationBean.addServletNames("name1");
            return registrationBean;
        }

}

important point:

  • It is one to one relationship between FilterRegistrationBean and Filter.
  • If there are multiple FilterRegistrationBean need to call its setName (String name) declare its unique name, otherwise only the first successful registration is valid.
  • If necessary to ensure the call sequence can be set by calling its setOrder (int order) method.

Four ways: using DelegatingFilterProxyRegistrationBean way

@Configuration
public class WebConfig {
    
    @Bean("myFilter")
    //配置了DelegatingFilterProxyRegistrationBean后,这种方式配置的Filter不会生效了,只会拦截/foo/*的请求
    public Filter myFilter(){
        return new TimeConsumingCalculationFilter();
    }

    @Bean
    public DelegatingFilterProxyRegistrationBean delegatingFilterProxyRegistrationBean(){
        DelegatingFilterProxyRegistrationBean filterProxy = new DelegatingFilterProxyRegistrationBean("myFilter");
        filterProxy.addUrlPatterns("/foo/*");
        filterProxy.addInitParameter("targetFilterLifecycle","true");
        filterProxy.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico");
        filterProxy.setDispatcherTypes(DispatcherType.REQUEST);
        return filterProxy;
    }

}

FilterRegistrationBean and DelegatingFilterProxyRegistrationBean difference:

  • FilterRegistrationBean register directly filter through onStartup method.
  • DelegatingFilterProxyRegistrationBean is registered Servlet3.0 + DelegatingFilterProxy vessel, while achieving ApplicationContextAware interface ApplicationContext instance name of the custom lookup by passing through a filter corresponding bean, and generates a proxy object corresponding bean.

comprehend by analogy

  • Add custom Servlet @WebServlet or a method may be employed ServletRegistrationBean
  • Add a custom Listener methods can also be used a @WebListener or ServletListenerRegistrationBean, note that the event is a generic monitor

Other related categories

  • ServletComponentRegisteringPostProcessor
  • ServletComponentHandler
  • WebListenerHandler
  • WebFilterHandler
  • WebServletHandler

reference

  • https://blog.csdn.net/loveForever_xiang/article/details/101270633
  • https://www.liangzl.com/get-article-detail-121998.html
  • https://mp.weixin.qq.com/s/t8WdKEkYJuRApeEEOvXR_A
  • https://blog.csdn.net/andy_zhang2007/article/details/90399870

Guess you like

Origin www.cnblogs.com/54chensongxia/p/12177784.html