HandlerInterceptors vs. Filters in Spring MVC – 处理程序拦截器与Spring MVC中的过滤器

最后修改: 2021年 5月 17日

中文/混合/英文(键盘快捷键:t)

 1. Overview

1.概述

In this article, we’ll compare the Java servlet Filter and the Spring MVC HandlerInterceptor, and when one might be preferable over the other.

在这篇文章中,我们将比较Java servlet Filter和Spring MVC HandlerInterceptor,以及什么时候一个可能比另一个更好。

2. Filters

2、过滤器s

Filters are part of the webserver and not the Spring framework. For incoming requests, we can use filters to manipulate and even block requests from reaching any servlet. Vice versa, we can also block responses from reaching the client.

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

Spring Security is a great example of using filters for authentication and authorization. To configure Spring Security, we simply need to add a single filter, the DelegatingFilterProxy. Spring Security can then intercept all incoming and outgoing traffic. This is why Spring Security can be used outside of Spring MVC.

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

2.1. Creating a Filter

2.1.创建一个过滤器

To create a filter, first, we create a class that implements the javax.servlet.Filter interface:

要创建一个过滤器,首先,我们创建一个实现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);
    }

}

Next, we override the doFilter method, where we can access or manipulate the ServletRequest, ServletResponse, or FilterChain objects. We can allow or block requests with the FilterChain object.

接下来,我们覆盖doFilter方法,我们可以访问或操作ServletRequestServletResponseFilterChain对象。我们可以通过FilterChain对象允许或阻止请求。

Finally, we add the Filter to the Spring context by annotating it with @Component. Spring will do the rest.

最后,我们将Filter添加到Spring上下文中,用@Component注释它。Spring将完成剩下的工作。

3. HandlerInterceptors

3.HandlerInterceptors

HandlerInterceptors are part of the Spring MVC framework and sit between the DispatcherServlet and our Controllers. We can intercept requests before they reach our controllers, and before and after the view is rendered.

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

3.1. Creating a HandlerInterceptor

3.1.创建一个HandlerInterceptor

To create a HandlerInterceptor, we create a class that implements the org.springframework.web.servlet.HandlerInterceptor interface. This gives us the option to override three methods:

为了创建一个HandlerInterceptor,我们创建一个实现org.springframework.web.servlet.HandlerInterceptor接口的类。这让我们可以选择覆盖三个方法。

  • preHandle() – Executed before the target handler is called
  • postHandle() – Executed after the target handler but before the DispatcherServlet renders the view
  • afterCompletion() – Callback after completion of request processing and view rendering

Let’s add logging to the three methods in our test interceptor:

让我们为测试拦截器中的三个方法添加日志。

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. Key Differences and Use Cases

4.关键差异和使用案例

Let’s look at a diagram showing where Filters and HandlerInterceptors fit in the request/response flow:

让我们看一张图,显示Filters和HandlerInterceptors在请求/响应流程中的位置。

Filters intercept requests before they reach the DispatcherServlet, making them ideal for coarse-grained tasks such as:

过滤器在请求到达DispatcherServlet之前进行拦截,使其成为粗粒度任务的理想选择,例如。

  • Authentication
  • Logging and auditing
  • Image and data compression
  • Any functionality we want to be decoupled from Spring MVC

HandlerIntercepors, on the other hand, intercepts requests between the DispatcherServlet and our Controllers. This is done within the Spring MVC framework, providing access to the Handler and ModelAndView objects. This reduces duplication and allows for more fine-grained functionality such as:

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

  • Handling cross-cutting concerns such as application logging
  • Detailed authorization checks
  • Manipulating the Spring context or model

5. Conclusion

5.总结

In this article, we covered the differences between a Filter and HandlerInterceptor.

在这篇文章中,我们介绍了FilterHandlerInterceptor的区别。

The key takeaway is that with Filters, we can manipulate requests before they reach our controllers and outside of Spring MVC. Otherwise, HandlerInterceptors are a great place for application-specific cross-cutting concerns. By providing access to the target Handler and ModelAndView objects, we have more fine-grained control.

关键的启示是,通过Filters,我们可以在请求到达我们的控制器之前,在Spring MVC之外对其进行操作。否则,HandlerInterceptors是特定应用的交叉关注点的绝佳场所。通过提供对目标HandlerModelAndView对象的访问,我们可以进行更精细的控制。

The implementation of all these examples and code snippets can be found over on GitHub.

所有这些例子和代码片断的实现都可以在GitHub上找到over