过滤器 (Filter)
过滤器( Filter),是 JavaEE 的标准,依赖于 Servlet 容器,使用的时候是配置在web.xml 文件中的,自定义过滤器实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截
只要在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一配置请求编码以及过滤一些非法参数,垃圾信息,简化操作;同时还可进行逻辑判断,如用户是否已经登陆、有没有权限访问该页面等等工作。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。
- init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。「注意」:这个方法必须执行成功,否则过滤器会不起作用。
- doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。
- destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。
拦截器 Interceptor
拦截器(Interceptor) 不依赖 Servlet 容器,依赖 Spring 等 Web 框架,在 SpringMVC 框架中是配置在SpringMVC 的配置文件中,在 SpringBoot 项目中也可以采用注解的形式实现。
HandlerInterceptor接口:
-
preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。
-
postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行。
-
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。
拦截器是 AOP 的一种应用,底层采用 Java 的反射机制来实现的。与过滤器一个很大的区别是在拦截器中可以注入 Spring 的 Bean,能够获取到各种需要的 Service 来处理业务逻辑,而过滤器则不行。
拦截器的使用
interceptor 的执行顺序大致为:
- 请求到达 DispatcherServlet
- DispatcherServlet 发送至 Interceptor ,执行 preHandle
- 请求达到 Controller
- 请求结束后,postHandle 执行
Spring 中主要通过 HandlerInterceptor 接口来实现请求的拦截,实现 HandlerInterceptor 接口需要实现下面三个方法:
- preHandle() – 在handler执行之前,返回 boolean 值,true 表示继续执行,false 为停止执行并返回。
- postHandle() – 在handler执行之后, 可以在返回之前对返回的结果进行修改
- afterCompletion() – 在请求完全结束后调用,可以用来统计请求耗时等等
SpringBoot配置实现拦截器
1.自定义拦截器
实现HandlerInterceptor接口,然后根据需要实习preHandler(),postHandler(),afterCompletion()
2.自定义配置类
实现WebMvcConfigurer接口,将拦截器配置类注册进去
3.自定义注解
通过Import()导入配置类和拦截器
4.在你需要用到拦截器的启动项上加上该注解
过滤器和拦截器的执行流程
加上DispatcherServlet之后的流程如下:
两者的本质区别:
拦截器在SpringMVC中配置,依赖于框架
过滤器则依赖于Servlet,需要在web.xml中配置
拦截器(Interceptor)是基于Java的反射机制,而过滤器(Filter)是基于函数回调。从灵活性上说拦截器功能更强大些,过滤器能做的事情,拦截器都能做,而且可以在请求前,请求后执行,比较灵活。
拦截器用于对SpringMVC的请求和响应进行特定的业务处理,通常与控制器层的请求处理有关。过滤器用于对所有Servlet请求和响应进行通用性的处理,通常关注请求和响应内容,而不涉及具体的业务逻辑。主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类)
太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。