上一篇文章中我们学了了Servlet的概念,这篇我们学习一下过滤器Filter, 正如它的名字,过滤器是介于Servlet之前,可拦截过滤浏览器对于Servlet的请求,也可以改变Servlet对于浏览器的响应。
那要如何实现一个Filter呢,这里我又把Filter的各子类关系图给大家放出来了,从图中可以看出,要想实现一个过滤器,可以直接实现Filter接口,也可以继承他的子类,对于Http请求,则可以直接继承HttpFilter。


接下来我们就来看看如何实现一个过滤器:
方式一:使用@WebFilter注解 和 @ServletComponentScan注解


方式二:使用@Component注解

方式三:使用FilterRegistrationBean


接下来我们来写一个contoller, 来验证一下我的三种方式实现的filter都生效了。

我们调用上面的请求, 会看看再我们的console下出现下面的运行结果,正如我们的预期。

需求一----指定Filter的运行顺序
如果在程序中想定义多个filter,并且为不同的Filter指定顺序,则只能使用@Component注解和FilterRegistrationBean的方式。具体的使用请参见下图:


需求二-----在Filter中校验失败,抛出异常
在实际项目中,我们通常会定义一个统一的返回信息格式,如果抛出异常,会通过全局统一的异常处理器,使得前端接收到的返回结果都是同一种格式,具体示例如下:
我们会看到在Filter中的异常并没有被我们的全局异常处理器捕捉到,所以也没有被处理成我们想要的统一格式,这是因为Filter并不在我们的Spring上下文中, 要想处理成我们统一定义的格式, 只能我们自己重写,具体示例如下面的代码所示:


不同实现方式的对比
说了这么多那我该用那种方式来实现呢? 这里我总结了几点,供大家参考。
- 使用@Component方式最简单, 但是这种方式会过滤所有的请求。其余两种方式都可以针对指定的路由进行过滤
- 使用FilterRegistrationBean的方式实现,无法通过注入的方式获取Spring上下文的其他Bean。
- 使用@WebFilter的方式实现,无法指定顺序。
spring中提供的Filter
上面介绍了Filter是什么,以及如何实现一个Filter, 不知道大家发现没有,其实我们在实际项目中早就使用了Filter,比如我们常用的跨域处理filter, 具体示例如下所示,其实CorsFilter的本质就是一个Filter, 感兴趣的小伙伴可以去看看源码, 其本质就是实现了Filter接口。

这张图是Spring给我们提供的所有Filter, 我们在自己定义Filter时其实可以通过实现OncePerRequestFilter. 具体它都实现了什么,以及每个Filter都有怎样的用处,我们会在下一篇文章中详细阐述。

