Web 三大组件之Filter

222 阅读3分钟

Web 三大组件之Filter

今天我们来讨论一下什么是Filter(过滤器),以及它可以用来干嘛,最后我们如何通过代码来进行实现

1. 什么是Filter

我们知道,浏览器和服务器进行交互的时候,肯定避免不了发送Http请求,那么请求到达后端controller接口的过程中,其实我们可以设定一层拦截,这层拦截其实就是过滤器啦。形象一点说,它就像是一条河的大坝,我们可以进行拦截。

2. Filter有哪些实际作用呢

  • 日志记录: 这是最常见的,我们去记录方法的执行时间,请求参数,相应参数等等
  • 权限控制: 由于Filter可以对于过来的请求进行放行或者遣返,因此我们可以对于过来的请求进行相关校验,决定请求放行与否
  • 跨域处理: 我们知道前后端分离的项目很容易发生跨域问题,在Filter中也可以去解决

3. Filter如何来实现呢

话不多说,我们直接看代码会更加形象,这里我们列举两种在springboot项目中如何简单去实现 filter

1. 通过@WebFilter注解简单实现

  1. 首先第一步,我们要撰写一个自定义的Filter类,实现Filter接口,实现后会发现我们要重写3个方法

    init该方法是filter初始化时候执行,一般不太需要去实现它
    destroy该方法是filter被销毁时候执行,一般来说只有我们的应用程序关闭时候,这个方法才会触发
    doFilter这是最重要的方法,这个方法可以获取请求途中的request, response,以及一个filterChain, 前两个参数我们可以做一些记录,然后,只要我们调用了filterChain.doFilter(servletRequest, servletResponse) 方法,这个请求才会被放行到Controller层

    @WebFilter注解中需要的参数如下

    属性名类型描述
    filterNameString指定过滤器的 name 属性
    valueString[]该属性等价于 urlPatterns 属性。但是两者不应该同时使用。
    urlPatternsString[]指定一组过滤器的 URL 匹配模式。等价于 标签。
    servletNamesString[]指定过滤器将 应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 的取值。
    dispatcherTypesDispatcherType指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
    initParamsWebInitParam[]指定一组过滤器初始化参数,等价于 标签。
    asyncSupportedboolean声明过滤器是否支持异步操作模式,等价于 标签。
    descriptionString该过滤器的描述信息,等价于 标签。
    displayNameString该过滤器的显示名,通常配合工具使用,等价于 标签。
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "myFilter", asyncSupported = true)
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
      log.info("MyFilter 初始化成功啦。。。");
    }

    @Override
    public void destroy() {
        log.info("MyFilter 销毁成功了。。。");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

重点来了,这种方式在使用的时候一定要在启动类上加上@ServletComponentScan, 否则不会生效,切记

image.png 以上就是Filter的第一种使用姿势了,但是它会有一个弊端,就是我们无法去指定各个Filter之间的优先级,那这种情况怎么办呢,可以使用第二种方式

2. 通过FilterRegistrationBean 把我们定义的Filter注入到spring容器中

其中这个order属性的值约小,代表优先级就越高

@SpringBootApplication
@ServletComponentScan
public class SpringTestProject implements WebMvcConfigurer {

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

    @Bean
    public FilterRegistrationBean<Filter> registrationBean() {
        FilterRegistrationBean<Filter> filter = new FilterRegistrationBean<>();
        filter.setName("myFilter2");
        filter.setFilter(new MyFilter2());
        filter.setOrder(-1);
        return filter;
    }

}