SpringBoot: Filter vs HandlerInterceptor ?

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


欢迎关注公众号:逻魔代码

前言

本文记录了 Servlet、Servlet Container、Filter、Interceptor、HandlerInterceptor 等概念相关的内容。


我们知道,在Java Web开发时,若想对请求或响应做出统一的逻辑处理,可以使用过滤器或者拦截器。那么具体什么时候使用过滤器,什么时候使用拦截器呢?

在探究这个问题之前,我们先搞清楚,什么是 Servlet ?

Servlet

现在我们通常做 Java Web 开发都会用 SpringBoot ,但要知道 SpringBoot 只是用来简化开发的,在此之前,Springframework 只是一个粘合剂框架,用来整合各种 Java Web 技术的,SpringMvc 都是出现的比较晚的技术,更早之前是 Struts2、Struts1。

那更早之前呢?就是基于原始的 Servlet/JSP 。

javax.servletjaavx.servlet.http 包提供了一些接口和类,实现了 Servlet 规范。 javax.servlet 包中的 Servlet 声明了一些重要方法,如 init(), service(), desctroy() 等,这些也都是 servlet 的生命周期方法.

我们还知道,Servlet 是运行于 Servlet 容器中的。容器可以处理网络连接,解析 HTTP 请求等。Tomcat 就是最负盛名的一个容器。

虽然现在大家都用 Spring 全家桶做开发,但必须要知道 SpringWvc 的核心还是一个 DispatcherServlet,其本质也就是一个 Servlet.

过滤器 Filter

过滤器是被容器执行的类。请求在进入容器时、响应在离开容器时,会经过一个个的过滤器。过滤器的实例,在容器中是以过滤器链的形式执行的。

如果在应用中,我们定义了多个过滤器,那么执行的先后顺序,可以通过 @Order 注解来指定。

Filter 接口的核心方法,也是其生命周期方法:

  • init(FilterConfig config) - 此方法只调用一次,用于初始化过滤器
  • doFilter(HttpServletRequest request, HttpServletResponse response, FilterChian chian) - 此方法在每一个请求打到映射的资源上时都会调用,比如定义一个 Filter 拦截 /path/* ,那么每一个匹配 /path/* 访问资源的请求进来时,都会执行此方法。这个方法中就是拦截器的具体逻辑
  • destroy() - 此方法也只执行一次,用于销毁过滤器

Servlet Invocation with and without Filters (docs.oracle.com)

拦截器 Interceptor

Spring 拦截器类似于 Servlet 过滤器。拦截器允许自定义预处理(Pre-Processing),在其中可以选择禁止对应 Handler 的执行;也允许自定义后处理(Post-Precessing);在拦截器中可以访问 Spring Context 上下文。

HandlerInterceptor 的核心方法:

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - 该方法在请求到达 Controller 之前执行操作,返回一个布尔值。当返回 false 时,不再执行对应的 handler
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) - 该方法在响应返回客户端之前执行
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) - 该方法在请求和响应流程完成之后执行

HandlerInterceptor: 它的实例在 DispatcherServlet(javax.servlet.Servlet 的实例) 中作为请求处理的一部分来执行。

注意,现在实现 Spring 拦截器,只需要实现 HandlerInterceptor 接口即可,更早之前,接口的方法不能有默认实现时,是需要继承 HandlerInteceptorAdapter 这个抽象类的,现在这个类已经可以废弃了。

通过下面一张图看看过滤器和拦截器的位置:

Filters and HandlerInterceptors

Filters vs HandlerInterceptors

  • Filter 是 Servlet 规范中的,而 HandlerInterceptor 是 Spring 中的一个概念
  • 拦截器位置相对于过滤器更靠后
  • 精细的预处理任务适用于拦截器,如授权检查等
  • 内容处理相关或通用的流程,非常适合用过滤器;如上传表单、zip 压缩、图像处理、日志记录请求、身份验证等
  • HandlerInterceptorpostHandle 方法允许我们向视图添加更多模型对象,但不能更改 HttpServletResponse,因为它已经被提交了
  • 过滤器的 doFilter 方法比拦截器的 postHandle 更通用。我们可以在过滤器中改变请求或响应,并将其传递给链,甚至阻止请求的处理
  • HandlerInterceptor 提供了比过滤器更精细的控制,因为我们可以访问实际的目标 handler,甚至可以检查 handler 方法是否有某个特定的注解

总结

本文回顾了 Servlet、Servlet Container、Filter、Interceptor、HandlerInterceptor 等一些概念,主要对比了 Servlet Filter 和 Spring HandlerInterceptor 在一个应用程序中的位置,探讨了何时该用 Filter 何时该用 Interceptor 的问题,希望对大家有帮助。

欢迎关注公众号:逻魔代码

posted @ 2022-05-30 17:48  北鱼扶摇  阅读(35)  评论(0编辑  收藏  举报  来源