1. 概述

在本文中,我们将比较 Java servlet Filter 和 Spring MVC HandlerInterceptor 以及何时其中一个可能优于另一个。

2. 过滤器

过滤器是 Web 服务器的一部分,而不是 Spring 框架的一部分。 对于传入请求, 我们可以使用过滤器来操纵甚至阻止请求到达任何servlet 。反之亦然,我们也可以阻止响应到达客户端。

Spring Security是使用过滤器进行身份验证和授权的一个很好的例子。要配置 Spring Security,我们只需添加一个过滤器 DelegatingFilterProxy 。 Spring Security 然后可以拦截所有传入和传出流量。这就是为什么 Spring Security 可以在Spring MVC之外使用。

2.1.创建 过滤器

要创建过滤器,首先,我们创建一个实现 javax.servlet.Filter接口的 类:

@Component
public class LogFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(LogFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
        logger.info("Hello from: " + request.getLocalAddr());
        chain.doFilter(request, response);
    }

}

接下来,我们重写 doFilter 方法,在该方法中我们可以访问或操作 ServletRequestServletResponseFilterChain 对象。我们可以使用 FilterChain 对象允许或阻止请求。

最后,我们通过使用 @Component 注解将 Filter 添加到 Spring 上下文中 春天将完成剩下的工作。

3.HandlerInterceptor

** HandlerInterceptor 是 Spring MVC 框架的一部分,位于 DispatcherServlet 和我们的 Controller 之间。** 我们可以在请求到达控制器之前以及视图渲染之前和之后拦截请求。

3.1.创建一个 HandlerInterceptor

为了创建 HandlerInterceptor ,我们创建一个实现 org.springframework.web.servlet.HandlerInterceptor 接口的类。这使我们可以选择重写三种方法:

  • preHandle() – 在调用目标处理程序之前执行
  • postHandle() – 在目标处理程序之后但在 DispatcherServlet 呈现视图之前执行
  • afterCompletion() – 请求处理和视图渲染完成后的回调

让我们向测试拦截器中的三个方法添加日志记录:

public class LogInterceptor implements HandlerInterceptor {

    private Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
      throws Exception {
        logger.info("preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 
      throws Exception {
        logger.info("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 
      throws Exception {
        logger.info("afterCompletion");
    }

}

4. 主要差异和用例

让我们看一个图表,显示 FilterHandlerInterceptor 在请求/响应流中的位置:

过滤器在请求到达 DispatcherServlet 之前拦截请求,这使得它们非常适合粗粒度任务, 例如:

  • 验证
  • 日志记录和审计
  • 图像和数据压缩
  • 我们希望与 Spring MVC 解耦的任何功能

另一方面, HandlerIntercepor 拦截 DispatcherServlet 和我们的 Controller 之间的请求。 这是在 Spring MVC 框架内完成的,提供对 HandlerModelAndView 对象的访问。这减少了重复并允许更细粒度的功能,例如:

  • 处理横切问题,例如应用程序日志记录
  • 详细的授权检查
  • 操作 Spring 上下文或模型

5. 结论

在本文中,我们介绍了 FilterHandlerInterceptor 之间的差异。

* 关键要点是,使用 Filter ,我们可以在请求到达我们的控制器之前以及 Spring MVC 之外对其进行操作。 * 否则, HandlerInterceptor 是处理特定于应用程序的横切关注点的好地方。通过提供对目标 HandlerModelAndView 对象的访问,我们可以进行更细粒度的控制。

所有这些示例和代码片段的实现都可以在 GitHub 上找到。