过滤器
依赖于servlet容器。过滤的是servlet中的对象,在实现上基于函数回调,可以对几乎所有请求进行过滤。
使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest
的一些参数,包括:过滤低俗文字、危险字符等。
缺点:一个过滤器实例只能在容器初始化时调用一次。
解决方案:将HttpServletRequest的字节流的数据,保存到一个变量中,重写getInputStream()方法和getReader()方法,从变量中读取数据,返回给调用者。
RepeatableFilter重复读取HttpServletRequest数据
详见 《SpringMVC-快速入门(6.2)- 自定义过滤器》
拦截器
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。拦截的是框架中的对象,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。
由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个 controller 生命周期之内可以多次调用。
缺点:只能对 controller 请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
详见《SpringMVC-快速入门(6.3)- 自定义拦截器》
应用过滤器和拦截器场景:
SpringBoot+Redis实现后端接口防重复提交校验的示例
区别
过滤器
是 tomcat服务器创建的对象,作用于servlet中的对象,过滤servlet请求响应;拦截器
是 SpringMVC容器创建的对象,作用于框架中的对象,拦截普通类方法执行。过滤器
实现Filter
接口,用来设置 request,response参数、属性,侧重对数据的过滤;拦截器
实现HandleInterceptor
,用来验证请求的,侧重截断请求。过滤器
是一个执行时间点;拦截器
是三个执行时间点。过滤器
可以处理jsp、js、html等;拦截器
是侧重拦截 Controller 的对象,如果你的请求不能被DispatcherServlet
接收,这个请求不会执行拦截器的内容。
注:过滤器是在拦截器之前执行的。
验证器
《SpringMVC-快速入门(五)- 校验数据》说明了springMvc数据校验的用法,如果需要自定义数据验证器,需要实现 ConstraintValidator
接口。大致步骤如下:
- 创建验证器注解,指定注解的
@Constraint
为自定义验证器类。 - 创建验证器类,实现接口
ConstraintValidator
,isValid方法中编写验证器逻辑。 - bean类中属性使用验证器注解进行标注。
详见 :
《Spring MVC自定义验证》
《Spring MVC 参数验证3-自定义验证》
面试题
拦截器能多次调用,而过滤器只能在容器初始化时被调用一次。如何去理解?
主要原因还是因为拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
拦截器就是每次执行到某servlet都会响应所以可以多次,回调函数是调用的时候才会响应。所以,过滤器只有请求在第一次到达服务端进行初始化的时候被调用,所以在整个生命周期只有一次。