Spring Boot 2.1.5 Project Reactor 3.2.9
在我的webflux项目中,我广泛使用反应堆上下文以传递一些值。
我设置了一个过滤器,并试图记录上下文中的内容,并在发生错误/成功的情况下记录不同的内容。
我已经查看了以下文档:https://projectreactor.io/docs/core/release/reference/#context
我仍然在努力(尤其是在错误方面)来获取它。
基本上,我有这个过滤器:
@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
.doAfterSuccessOrError(new BiConsumer<Void, Throwable>() {
@Override
public void accept(Void aVoid, Throwable throwable) {
//Here i would like to be able to access to the request's context
System.out.println("doAfterSuccessOrError:" + (throwable==null ? "OK" : throwable.getMessage())+"log the context");
}
})
.doOnEach(new Consumer<Signal<Void>>() {
@Override
public void accept(Signal<Void> voidSignal) {
//Here i have the context but i don't really know if i am in success or error
System.out.println("doOnEach:"+"Log OK/KO and the exception" + voidSignal.getContext());
}
})
.subscriberContext(context -> context.put("somevar", "whatever"));
}
}
我还尝试了flatMap()和Mono.subscriberContext(),但是我不确定如何正确插入过滤器(尤其是错误的消息)。
实现此目标的最佳方法是什么?
答案 0 :(得分:1)
我知道这可能不是最干净的解决方案,但是您可以创建一个容器类,以在两个回调之间保留上下文。
您可以将上下文存储在doOnEach
,然后可以将其加载回doAfterSuccessOrError
:
public Mono<Void> filter(@NotNull ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
@lombok.Data
class MyContextContainer {
private Context context;
}
MyContextContainer container = new MyContextContainer();
Mono<Void> filter = webFilterChain.filter(serverWebExchange);
return filter
.doAfterSuccessOrError(new BiConsumer<Void, Throwable>() {
@Override
public void accept(Void aVoid, Throwable throwable) {
// load the context here
Context context = container.getContext();
// then do your stuff here
}
})
.doOnEach(new Consumer<Signal<Void>>() {
@Override
public void accept(Signal<Void> voidSignal) {
// store the context here
container.setContext(voidSignal.getContext());
}
})
.subscriberContext(context -> context.put("somevar", "whatever"));
}
确实不需要上课。可能是AtomicReference
,但您明白了。
同样,这可能只是解决方法。我相信必须有更好的方法来访问上下文。
答案 1 :(得分:1)
我不确定是否可以从WebFilter中访问请求反应器上下文。 WebFilter上下文存在于另一个Mono链中。 但是可以将属性与请求相关联,并能够在请求生存期内RequestContextHolder for Reactive Web提取这些属性 与Servlet API非常相似。
控制器:
Token.update(
{
updatedAt: new Date
},
{
where: {
token_id: token
}
}
).then(value1 => {
console.log('Token UpdatedAt has been updated');
}
)
WebFilter:
@GetMapping(path = "/v1/customers/{customerId}")
public Mono<Customer> getCustomerById(
@PathVariable("customerId") String customerId,
ServerWebExchange serverWebExchange)
{
serverWebExchange.getAttributes().put("traceId", "your_trace_id");
return customerService.findById(customerId);
}