怎么实现 Spring Boot 过滤器(Filter)?

转自:https://www.baeldung.com/spring-boot-add-filter

1. 概述

在这教程里将解释怎么定义自定义过滤器并且通过 Spring Boot 制定过滤器的执行顺序。

2. 定义过滤器及其执行顺序

先定义两个过滤器:

  1. TransactionFilter - 用来开启和提交事务
  2. RequestResponseLoggingFilter - 用来把请求和响应写到日志里

为了创建过滤器,只需实一下 Filter 接口就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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(
"为请求开启一个事务 : {}",
req.getRequestURI());

chain.doFilter(request, response);
LOG.info(
"提交请求事务 : {}",
req.getRequestURI());
}

// 其他方法
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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(
"请求日志 {} : {}", req.getMethod(),
req.getRequestURI());
chain.doFilter(request, response);
LOG.info(
"响应日志 :{}",
res.getContentType());
}

// 其他方法
}

为了让 Spring 识别为过滤器,需要给类添加 @Component 注解。

并且为了让多个过滤器以准确的顺序执行,需要用 @Order 注解。

2.1. 特定URL格式的过滤器

上述实例中实现的过滤器会被默认注册到应用所有的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;
}

现在 RequestResponseLoggingFilter 过滤器只对匹配 /users/* 格式的路径生效。

为了给其他URL格式的路径添加过滤器,可以用 addUrlPatterns()addUrlPatterns() 方法。

3. 简单例子

先实现一个简单的访问点并且发送一个HTTP请求:

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

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

应用输出的日志如下:

1
2
3
4
5
23:54:38 INFO  com.spring.demo.TransactionFilter - 为请求开启一个事务  :/users
23:54:38 INFO c.s.d.RequestResponseLoggingFilter - 请求日志 GET : /users
...
23:54:38 INFO c.s.d.RequestResponseLoggingFilter - 响应日志 :application/json;charset=UTF-8
23:54:38 INFO com.spring.demo.TransactionFilter - 提交请求事务 :/users

4. 总结

本文中,简述了一下怎么在Spring Boot web 应用里实现自定义过滤器。

完整代码在GitHub上可以找到: 地址