Spring webflux 错误处理程序:如何在错误处理程序中获取请求的反应器上下文?
Spring Boot 2.1.5 Project Reactor 3.2.9
Spring boot 2.1.5 Project Reactor 3.2.9
在我的 webflux 项目中,我广泛使用反应器上下文来传递一些值.
In my webflux project, I extensively use the reactor contexts in order to pass around some values.
我在这里的目的是能够获取异常处理程序内部的上下文.
My purpose here is to be able to get the context inside of the Exception handler.
一个简单的例子:
@Component
@Order(-2)
public class GlobalErrorWebExceptionHandler extends
AbstractErrorWebExceptionHandler {
public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ApplicationContext applicationContext, ServerCodecConfigurer configurer) {
super(errorAttributes, resourceProperties, applicationContext);
this.setMessageWriters(configurer.getWriters());
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(
ErrorAttributes errorAttributes) {
return RouterFunctions
.route(RequestPredicates.all(), request -> {
Throwable error = errorAttributes.getError(request);
return ServerResponse.status(500).syncBody(error.getMessage()).doOnEach(serverResponseSignal -> {
//Here the context is empty because i guess i created a new flux
System.out.println("What is in my context ? " + serverResponseSignal.getContext());
System.out.println("What is my exception ? " + error);
});
});
}
}
我不确定如何使用 reactor 以干净的方式实现该目标.有人有想法吗?
I am not sure how to achieve that goal in a clean way with reactor. Anyone an idea ?
我找到了一个技巧来实现这一目标.听起来不太干净,但似乎有效.
I found a trick to be able to achieve that. It does not sound clean but it seems to work.
在过滤器中,我将订阅的上下文保存在请求属性中:
In a filter, I keep the subscribed context into a request attribute:
@Component
public class MdcWebFilter implements WebFilter {
@NotNull
@Override
public Mono<Void> filter(@NotNull ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
Mono<Void> filter = webFilterChain.filter(serverWebExchange);
return filter
.subscriberContext((context) -> {
//This code is executed before the query
Context contextTmp = context.put("whatever", "whichever");
//I save the context in an attribute attribute
serverWebExchange.getAttributes().put("context", contextTmp);
return contextTmp;
});
}
}
然后可以从反应式错误处理程序中获取它:
Then after that it is possible to get it from the reactive error handler:
@Component
@Order(-2)
public class GlobalErrorWebExceptionHandler extends
AbstractErrorWebExceptionHandler {
public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ApplicationContext applicationContext, ServerCodecConfigurer configurer) {
super(errorAttributes, resourceProperties, applicationContext);
this.setMessageWriters(configurer.getWriters());
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(
ErrorAttributes errorAttributes) {
return RouterFunctions
.route(RequestPredicates.all(), request -> {
Throwable error = errorAttributes.getError(request);
//The context will be visible in the whole error handling flow
return ServerResponse.status(500).syncBody(error.getMessage())
.subscriberContext((Context) request.attribute("context").orElse(Context.empty())));
});
}
}