1. 总览

在本快速教程中,我们将探索如何在Spring Boot的帮助下定义自定义过滤器并指定其调用顺序。

2. 定义过滤器和调用顺序

让我们从创建两个过滤器开始

  1. TransactionFilter – to start and commit transactions
  2. RequestResponseLoggingFilter – to log requests and responses

创建过滤器,我们只需实现filter接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
@Order(1)
public class TransactionFilter implements Filter {

    @Override
    public void doFilter(
            ServletRequest request,
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        LOG.info(
                "Starting a transaction for req : {}",
                req.getRequestURI());

        chain.doFilter(request, response);
        LOG.info(
                "Committing a transaction for req : {}",
                req.getRequestURI());
    }
 
    // other methods 
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

@Component
@Order(2)
public class RequestResponseLoggingFilter implements Filter {

    @Override
    public void doFilter(
            ServletRequest request,
            ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        LOG.info(
                "Logging Request  {} : {}", req.getMethod(),
                req.getRequestURI());
        chain.doFilter(request, response);
        LOG.info(
                "Logging Response :{}",
                res.getContentType());
    }

    // other methods
}

为了使Spring能够识别过滤器,我们需要使用@Component注释将其定义为bean。

同时,要使过滤器以正确的顺序触发–我们需要使用@Order批注。

2.1 使用网址格式过滤

在上面的示例中,默认情况下,我们为应用程序中的所有URL注册了我们的过滤器。

但是,有时我们可能希望过滤器仅应用于某些URL模式。

在这种情况下,我们必须从过滤器类定义中删除@Component批注,并使用FilterRegistrationBean注册过滤器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@Bean
public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter() {
    FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean
            = new FilterRegistrationBean<>();

    registrationBean.setFilter(new RequestResponseLoggingFilter());
    registrationBean.addUrlPatterns("/users/*");

    return registrationBean;
}

现在,过滤器将仅适用于与/ users / *模式匹配的路径。

要设置过滤器的网址格式,我们可以使用addUrlPatterns() 或setUrlPatterns() 方法。

一个简单的例子

现在,让我们创建一个简单的接口并向其发送HTTP请求:

1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping()
    public List<User> getAllUsers() {
        // ...
    }
}

当访问这个api的时候,会产生以下日志:

1
2
3
4
5
23:54:38 INFO  com.spring.demo.TransactionFilter - Starting Transaction for req :/users
23:54:38 INFO  c.s.d.RequestResponseLoggingFilter - Logging Request  GET : /users
...
23:54:38 INFO  c.s.d.RequestResponseLoggingFilter - Logging Response :application/json;charset=UTF-8
23:54:38 INFO  com.spring.demo.TransactionFilter - Committing Transaction for req :/users

这说明过滤器按顺序执行了。

结论

在本文中,我们总结了如何在Spring Boot Webapp中定义自定义过滤器。