gpt4 book ai didi

java - Spring 响应式(Reactive)应用程序上请求/响应主体的副本?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:04:42 24 4
gpt4 key购买 nike

我正在研究访问 HTTP 请求和响应主体的最佳方式,以便在 Spring 响应式(Reactive)应用程序中进行跟踪。

对于以前的版本,我们利用 Servlet 过滤器和 Servlet 请求包装器来使用传入请求的输入流并保留它的副本以异步处理跟踪(我们将它们发送到 Elasticsearch)。

但对于 Spring 响应式(Reactive)应用程序(使用 webflux),我想知道在解码之前访问请求的最合适方式是什么。有什么想法吗?

最佳答案

事实证明,这可以使用提供的装饰器来实现:分别是ServerWebExchangeDecoratorServerHttpRequestDecoratorServerHttpResponseDecorator

这是一个示例请求装饰器,它在请求的默认订阅者读取时累积 DataBuffer 内容:

@Slf4j
public class CachingServerHttpRequestDecorator extends ServerHttpRequestDecorator {

@Getter
private final OffsetDateTime timestamp = OffsetDateTime.now();
private final StringBuilder cachedBody = new StringBuilder();

CachingServerHttpRequestDecorator(ServerHttpRequest delegate) {
super(delegate);
}

@Override
public Flux<DataBuffer> getBody() {
return super.getBody().doOnNext(this::cache);
}

@SneakyThrows
private void cache(DataBuffer buffer) {
cachedBody.append(UTF_8.decode(buffer.asByteBuffer())
.toString());
}

public String getCachedBody() {
return cachedBody.toString();
}

只需确保,当您装饰由 WebFilter 传递的 ServerWebExchange 时,您还覆盖了 getRequest() 以返回请求装饰器还有:

public final class PartnerServerWebExchangeDecorator extends ServerWebExchangeDecorator {

private final ServerHttpRequestDecorator requestDecorator;
private final ServerHttpResponseDecorator responseDecorator;

public PartnerServerWebExchangeDecorator(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new PartnerServerHttpRequestDecorator(delegate.getRequest());
this.responseDecorator = new PartnerServerHttpResponseDecorator(delegate.getResponse());
}

@Override
public ServerHttpRequest getRequest() {
return requestDecorator;
}

@Override
public ServerHttpResponse getResponse() {
return responseDecorator;
}

}

在过滤器上:

@Component
public class TracingFilter implements WebFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(new PartnerServerWebExchangeDecorator(exchange));
}
}

可以这样使用(注意静态导入的函数):

@Bean
public HttpHandler myRoute(MyHandler handler) {
final RouterFunction<ServerResponse> routerFunction =
route(POST("/myResource"), handler::persistNotification);
return webHandler(toWebHandler(routerFunction))
.filter(new TracingFilter())
.build();
}

关于java - Spring 响应式(Reactive)应用程序上请求/响应主体的副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47182961/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com