springboot创建过滤器filter的方式

springboot创建过滤器filter两种方式和区别

浏览器发出的请求先递交给第一个filter进行过滤,符合规则则放行,递交给filter链中的下一个过滤器进行过滤。在doFilter()方法中,chain.doFilter()前的一般是对request执行的过滤操作,chain.doFilter后面的代码一般是对response执行的操作。过滤链代码的执行顺序如下

 过滤器用途:

1)过滤敏感词汇(防止sql注入)
2)设置字符编码
3)URL级别的权限访问控制
4)压缩响应信息

1、使用@WebFilter和@ServletComponentScan注解方式创建filter

 首先创建过滤器类,实现  javax.servlet.Filter接口,并添加注解@WebFilter(javax.servlet.annotation.WebFilter),urlPatterns 过滤器要过滤的URL规则配置,filterName 过滤器的名称。有的博客上说使用@Order(int) 注解,可以自定义过滤器的顺序,但经过验证后此种方式并不生效。

package com.test.demo.filter;


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "aFilter", urlPatterns = {"/*"})
public class AFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("A Filter before");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("A Filter after");
    }
}

然后再项目的启动类上加上@ServletComponentScan注解即可

package com.test.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import springfox.documentation.oas.annotations.EnableOpenApi;

@EnableOpenApi
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

当使用这种方式启动多个过滤器时,过滤器的顺序是按照类名升序排序的,

经过测试,发现 @Order 注解指定 int 值没有起作用,是无效的。因为看源码发现 @WebFilter 修饰的过滤器在加载时,没有使用 @Order 注解,而是使用的类名来实现自定义Filter顺序,

所以这种方式定义Filter的顺序,就必须限定 Filter 的类名,比如刚才那个 Filter 叫 AFilter ,加入我们现在新写了一个 Filter 叫 BFilter ,那么顺序就是 AFilter BFilter 

所以这种方式虽然实现起来简单,只需要注解,但自定义顺序就必须要限定类名,使用类名达到排序效果了。

测试验证如图:

 AFilter过滤器设置的order是100,BFilter设置的order是1,但是执行顺序还是AFilter在BFilter之前,证明order注解并没有起作用。

2、FilterRegistrationBean方式创建过滤器

FilterRegistrationBeanspringboot提供的,此类提供setOrder方法,可以为filter设置排序值,让spring在注册web filter之前排序后再依次注册。

package com.test.demo.config;

import com.test.demo.filter.AFilter;
import com.test.demo.filter.BFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean filter1() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        AFilter aFilter = new AFilter();
        //设置过滤器
        filterRegistrationBean.setFilter(aFilter);
        filterRegistrationBean.setName("A filter");  //设置名称
        List list = new ArrayList();
        list.add("/*");   //拦截路径
        filterRegistrationBean.setUrlPatterns(list);
        filterRegistrationBean.setOrder(2);  //设置访问优先级 值越小越高
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean filter2() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        BFilter bFilter = new BFilter();
        filterRegistrationBean.setFilter(bFilter);
        filterRegistrationBean.setName("B filter");
        List list = new ArrayList();
        list.add("/*");   //拦截路径
        filterRegistrationBean.setUrlPatterns(list);
        filterRegistrationBean.setOrder(1);  //设置访问优先级 值越小越高
        return filterRegistrationBean;
    }

}

执行结果如图:

 设置过滤器顺序成功,BFilter在AFilter过滤器之前执行。

当不设置 setOrder 次序时,过滤器的执行顺序默认是 Bean 的加载顺序。在当前 FilterConfig 类中,先加载的是 filter1方法 即 AFilter 过滤器,后加载的是 filter2 方法 即 BFilter 过滤器。

package com.test.demo.config;

import com.test.demo.filter.AFilter;
import com.test.demo.filter.BFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean filter2() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        BFilter bFilter = new BFilter();
        filterRegistrationBean.setFilter(bFilter);
        filterRegistrationBean.setName("B filter");
        List list = new ArrayList();
        list.add("/*");   //拦截路径
        filterRegistrationBean.setUrlPatterns(list);
//        filterRegistrationBean.setOrder(1);  //设置访问优先级 值越小越高
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean filter1() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        AFilter aFilter = new AFilter();
        //设置过滤器
        filterRegistrationBean.setFilter(aFilter);
        filterRegistrationBean.setName("A filter");  //设置名称
        List list = new ArrayList();
        list.add("/*");   //拦截路径
        filterRegistrationBean.setUrlPatterns(list);
//        filterRegistrationBean.setOrder(2);  //设置访问优先级 值越小越高
        return filterRegistrationBean;
    }



}

注释掉setOrder后,将filter2方法放在filter1方法前,再次执行,结果如图:

 证明使用此种方式创建过滤器,过滤器的默认顺序就是过滤器的加载顺序,与过滤器类名无关。

3、SpringBoot注册第三方过滤器

假如在项目里引入了第三方的jar,要使用jar里面带的 Filter ,且这个过滤器在实现时没有使用 @Component标识为Spring Bean,则这个过滤器将不会生效。此时需要通过java代码去注册这个过滤器。也是使用FilterRegistrationBean配置类的方式进行注册。

4、使用@Component注解创建过滤器

package com.test.demo.filter;


import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;

@Component
public class AFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("A Filter before");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("A Filter after");
    }
}
package com.test.demo.filter;


import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;

@Component
public class BFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("B Filter before");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("B Filter after");
    }
}

然后启动项目后者执行,结果如图所示:

 先执行的AFilter过滤器,后执行的BFilter过滤器。通过此种方式无法自定义设置过滤器的顺序。

 

posted @ 2021-11-09 10:42  wang_longan  阅读(719)  评论(0编辑  收藏  举报