1. 概述
过滤器在 Web 应用中非常普遍,它提供了一种在不修改接口逻辑的情况下修改请求或响应的机制。本文将介绍在 WebFlux 框架中实现过滤器的几种方式。
⚠️ 本文假设读者已具备 WebFlux 基础知识,如需了解框架细节,可参考相关文档。
2. Maven 依赖
首先添加 WebFlux 的 Maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
3. 接口实现
我们需要创建两种类型的接口:基于注解和基于函数式编程的接口。
3.1 基于注解的控制器
@GetMapping(path = "/users/{name}")
public Mono<String> getName(@PathVariable String name) {
return Mono.just(name);
}
3.2 基于函数式编程的接口
先创建处理器:
@Component
public class PlayerHandler {
public Mono<ServerResponse> getName(ServerRequest request) {
Mono<String> name = Mono.just(request.pathVariable("name"));
return ok().body(name, String.class);
}
}
再配置路由映射:
@Bean
public RouterFunction<ServerResponse> route(PlayerHandler playerHandler) {
return RouterFunctions
.route(GET("/players/{name}"), playerHandler::getName)
.filter(new ExampleHandlerFilterFunction());
}
4. WebFlux 过滤器类型
WebFlux 提供两种过滤器:
- ✅ WebFilter:全局生效,作用于所有接口
- ✅ HandlerFilterFunction:仅作用于基于 Router 的接口
4.1 WebFilter 实现
实现一个为所有响应添加自定义头的过滤器:
@Component
public class ExampleWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
serverWebExchange.getResponse()
.getHeaders().add("web-filter", "web-filter-test");
return webFilterChain.filter(serverWebExchange);
}
}
4.2 HandlerFilterFunction 实现
当 name 参数为 "test" 时返回 403 状态码:
public class ExampleHandlerFilterFunction
implements HandlerFilterFunction<ServerResponse, ServerResponse> {
@Override
public Mono<ServerResponse> filter(ServerRequest serverRequest,
HandlerFunction<ServerResponse> handlerFunction) {
if (serverRequest.pathVariable("name").equalsIgnoreCase("test")) {
return ServerResponse.status(FORBIDDEN).build();
}
return handlerFunction.handle(serverRequest);
}
}
5. 测试方法
使用 WebTestClient 进行过滤器测试:
5.1 测试注解式接口
@Test
public void whenUserNameIsBaeldung_thenWebFilterIsApplied() {
EntityExchangeResult<String> result = webTestClient.get()
.uri("/users/baeldung")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
assertEquals(result.getResponseBody(), "baeldung");
assertEquals(
result.getResponseHeaders().getFirst("web-filter"),
"web-filter-test");
}
@Test
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
webTestClient.get().uri("/users/test")
.exchange()
.expectStatus().isOk();
}
5.2 测试函数式接口
@Test
public void whenPlayerNameIsBaeldung_thenWebFilterIsApplied() {
EntityExchangeResult<String> result = webTestClient.get()
.uri("/players/baeldung")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
assertEquals(result.getResponseBody(), "baeldung");
assertEquals(
result.getResponseHeaders().getFirst("web-filter"),
"web-filter-test");
}
@Test
public void whenPlayerNameIsTest_thenHandlerFilterFunctionIsApplied() {
webTestClient.get().uri("/players/test")
.exchange()
.expectStatus().isForbidden();
}
6. 总结
本文介绍了 WebFlux 中两种过滤器的实现方式:
- WebFilter:全局过滤器,简单粗暴地处理所有请求
- HandlerFilterFunction:针对特定路由的精细控制
实际开发中需要根据场景选择合适的过滤器类型。踩坑提醒:HandlerFilterFunction 仅对函数式路由生效,注解式接口不会触发!
完整示例代码可在 GitHub 获取。