【发布时间】:2019-03-11 02:31:03
【问题描述】:
目前正在使用 Spring Boot 2.0.4 开发一个 WebFilter,用于在 Spring WebFlux 应用程序中记录 HTTP 请求和响应信息(URL、响应状态代码、持续时间等)。
工作正常,只是 exchange.getResponse().getStatusCode() 保持为空。
尝试了两种不同的filter(ServerWebExchange exchange, WebFilterChain chain),第一个:
return chain.filter(exchange).doAfterTerminate(
() -> System.out.println("Status=" + exchange.getResponse().getStatusCode()));
第二个:
Mono<Void> filtered = chain.filter(exchange);
exchange.getResponse().beforeCommit(() -> {
System.out.println("Status=" + exchange.getResponse().getStatusCode());
return Mono.empty();
});
return filtered;
还尝试了过滤器上的各种顺序:无、@Order(100000)、@Order(-100000)。
状态码保持为空。
什么是正确的实现方式?
更新 1
基于 KevH 解决方案编写了一个简约的工作示例,请参阅 https://github.com/fbeaufume/webflux-filter-sample 但它还没有工作,状态仍然为空。 MWE 公开了两个 REST 端点:/hello 和 /pause/1000(暂停 1 秒)。
注意,当调用暂停端点日志时:
11:06:20.644 INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.LogFilter : Request [/pause/1000] started, traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:20.673 INFO 9536 --- [ctor-http-nio-2] com.adeliosys.sample.HelloController : Pausing for 1000 msec
11:06:21.683 INFO 9536 --- [ parallel-2] com.adeliosys.sample.LogFilter : Request [/pause/1000] completed, statusCode [null], time [1039], traceId [bb3fe67d-170b-4070-837d-816fe1420a1f]
11:06:21.684 INFO 9536 --- [ parallel-2] com.adeliosys.sample.HelloController : Paused for 1000 msec
我很惊讶过滤器的第二条消息显示在在端点的第二条消息之前。
更新 2
使用 doAfterTerminate(或类似方法)的过滤器实现似乎是正确的,但这只有使用使用 ResponseEntity 的 REST 控制器方法才能正确检索 HTTP 响应状态在返回类型中。
不支持(即状态为空):void、Mono<Void>、String、Mono<String>、MyBean、Mono<MyBean> 等。
支持(即状态为 200):ReponseEntity<Void>、Mono<ResponseEntity<Void>>、ReponseEntity<String>、Mono<ResponseEntity<String>>、ReponseEntity<MyBean>、Mono<ResponseEntity<MyBean>> 等。
错误?
Spring Boot 2.0.5 具有相同的行为。
更新 3
打开一个关于该主题的问题,请参阅https://jira.spring.io/browse/SPR-17368
【问题讨论】:
标签: java spring-boot spring-webflux