跳到主要内容
版本:7.0.3

过滤器

Hunyuan 7b 中英对照 Filters

你可以通过 WebClient.Builder 注册一个客户端过滤器(ExchangeFilterFunction),以便拦截和修改请求,如下例所示:

WebClient client = WebClient.builder()
.filter((request, next) -> {

ClientRequest filtered = ClientRequest.from(request)
.header("foo", "bar")
.build();

return next.exchange(filtered);
})
.build();

这可以用于解决一些跨领域的问题,例如身份验证。以下示例通过一个静态工厂方法使用了基本身份验证的过滤器:

import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;

WebClient client = WebClient.builder()
.filter(basicAuthentication("user", "password"))
.build();

可以通过修改现有的WebClient实例来添加或删除过滤器,从而得到一个新的WebClient实例,而这个新实例不会影响原来的WebClient实例。例如:

import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;

WebClient client = webClient.mutate()
.filters(filterList -> {
filterList.add(0, basicAuthentication("user", "password"));
})
.build();

WebClient 是一个轻量级的接口,它围绕一系列过滤器(filter chain)以及后续的 ExchangeFunction 构建。它提供了一套工作流程,用于发起请求、将数据编码成更高层次的对象格式,同时确保响应内容总能被正确处理。当过滤器以某种方式处理响应时,必须格外注意:要么确保响应内容被完全消费,要么将其传递给下游的 WebClient,由 WebClient 来完成同样的处理。下面是一个处理 UNAUTHORIZED 状态码的过滤器,但这个过滤器会确保无论是否预期,任何响应内容都会被释放:

public ExchangeFilterFunction renewTokenFilter() {
return (request, next) -> next.exchange(request).flatMap(response -> {
if (response.statusCode().value() == HttpStatus.UNAUTHORIZED.value()) {
return response.releaseBody()
.then(renewToken())
.flatMap(token -> {
ClientRequest newRequest = ClientRequest.from(request).build();
return next.exchange(newRequest);
});
} else {
return Mono.just(response);
}
});
}

下面的示例演示了如何使用ExchangeFilterFunction接口来创建一个自定义过滤类,该类通过缓冲机制帮助计算PUTPOST multipart/form-data请求的Content-Length头部信息。

public class MultipartExchangeFilterFunction implements ExchangeFilterFunction {

@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
if (MediaType.MULTIPART_FORM_DATA.includes(request.headers().getContentType())
&& (request.method() == HttpMethod.PUT || request.method() == HttpMethod.POST)) {
return next.exchange(ClientRequest.from(request).body((outputMessage, context) ->
request.body().insert(new BufferingDecorator(outputMessage), context)).build()
);
} else {
return next.exchange(request);
}
}

private static final class BufferingDecorator extends ClientHttpRequestDecorator {

private BufferingDecorator(ClientHttpRequest delegate) {
super(delegate);
}

@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
return DataBufferUtils.join(body).flatMap(buffer -> {
getHeaders().setContentLength(buffer.readableByteCount());
return super.writeWith(Mono.just(buffer));
});
}
}
}