springboot webflux webclient 使用說明
應用:webflux可使用webclient獲取網絡資源
************************
相關類與接口
WebClient
public interface WebClient {
WebClient.RequestHeadersUriSpec<?> get();
WebClient.RequestHeadersUriSpec<?> head();
WebClient.RequestBodyUriSpec post();
WebClient.RequestBodyUriSpec put();
WebClient.RequestBodyUriSpec patch();
WebClient.RequestHeadersUriSpec<?> delete();
WebClient.RequestHeadersUriSpec<?> options();
WebClient.RequestBodyUriSpec method(HttpMethod var1);
WebClient.Builder mutate();
static WebClient create() { //創建WebClient對象
return (new DefaultWebClientBuilder()).build();
}
static WebClient create(String baseUrl) {
return (new DefaultWebClientBuilder()).baseUrl(baseUrl).build();
}
static WebClient.Builder builder() {
return new DefaultWebClientBuilder();
}
public interface RequestBodyUriSpec extends WebClient.RequestBodySpec, WebClient.RequestHeadersUriSpec<WebClient.RequestBodySpec> {
}
public interface RequestHeadersUriSpec<S extends WebClient.RequestHeadersSpec<S>> extends WebClient.UriSpec<S>, WebClient.RequestHeadersSpec<S> {
}
public interface ResponseSpec {
WebClient.ResponseSpec onStatus(Predicate<HttpStatus> var1, Function<ClientResponse, Mono<? extends Throwable>> var2);
WebClient.ResponseSpec onRawStatus(IntPredicate var1, Function<ClientResponse, Mono<? extends Throwable>> var2);
<T> Mono<T> bodyToMono(Class<T> var1);
<T> Mono<T> bodyToMono(ParameterizedTypeReference<T> var1);
//使用方法可將返回結果轉換爲制定的類型,
//如:new ParameterizedTypeReference<Map<String,String>> 轉換爲 Map<String,String>
// new ParameterizedTypeReference<Person> 轉換爲 Person類
<T> Flux<T> bodyToFlux(Class<T> var1);
<T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> var1);
<T> Mono<ResponseEntity<T>> toEntity(Class<T> var1);
<T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> var1);
<T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> var1);
<T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> var1);
Mono<ResponseEntity<Void>> toBodilessEntity();
}
public interface RequestBodySpec extends WebClient.RequestHeadersSpec<WebClient.RequestBodySpec> {
WebClient.RequestBodySpec contentLength(long var1);
WebClient.RequestBodySpec contentType(MediaType var1);
WebClient.RequestHeadersSpec<?> bodyValue(Object var1);
<T, P extends Publisher<T>> WebClient.RequestHeadersSpec<?> body(P var1, Class<T> var2);
<T, P extends Publisher<T>> WebClient.RequestHeadersSpec<?> body(P var1, ParameterizedTypeReference<T> var2);
WebClient.RequestHeadersSpec<?> body(Object var1, Class<?> var2);
WebClient.RequestHeadersSpec<?> body(Object var1, ParameterizedTypeReference<?> var2);
WebClient.RequestHeadersSpec<?> body(BodyInserter<?, ? super ClientHttpRequest> var1);
/** @deprecated */
@Deprecated
WebClient.RequestHeadersSpec<?> syncBody(Object var1);
}
public interface RequestHeadersSpec<S extends WebClient.RequestHeadersSpec<S>> {
S accept(MediaType... var1);
S acceptCharset(Charset... var1);
S cookie(String var1, String var2);
S cookies(Consumer<MultiValueMap<String, String>> var1);
S ifModifiedSince(ZonedDateTime var1);
S ifNoneMatch(String... var1);
S header(String var1, String... var2);
S headers(Consumer<HttpHeaders> var1);
S attribute(String var1, Object var2);
S attributes(Consumer<Map<String, Object>> var1);
WebClient.ResponseSpec retrieve();
Mono<ClientResponse> exchange();
}
public interface UriSpec<S extends WebClient.RequestHeadersSpec<?>> {
S uri(URI var1); //設置請求的uri
S uri(String var1, Object... var2);
S uri(String var1, Map<String, ?> var2);
S uri(String var1, Function<UriBuilder, URI> var2);
S uri(Function<UriBuilder, URI> var1);
}
public interface Builder {
WebClient.Builder baseUrl(String var1);
WebClient.Builder defaultUriVariables(Map<String, ?> var1);
WebClient.Builder uriBuilderFactory(UriBuilderFactory var1);
WebClient.Builder defaultHeader(String var1, String... var2);
WebClient.Builder defaultHeaders(Consumer<HttpHeaders> var1);
WebClient.Builder defaultCookie(String var1, String... var2);
WebClient.Builder defaultCookies(Consumer<MultiValueMap<String, String>> var1);
WebClient.Builder defaultRequest(Consumer<WebClient.RequestHeadersSpec<?>> var1);
WebClient.Builder filter(ExchangeFilterFunction var1);
WebClient.Builder filters(Consumer<List<ExchangeFilterFunction>> var1);
WebClient.Builder clientConnector(ClientHttpConnector var1);
WebClient.Builder codecs(Consumer<ClientCodecConfigurer> var1);
WebClient.Builder exchangeStrategies(ExchangeStrategies var1);
/** @deprecated */
@Deprecated
WebClient.Builder exchangeStrategies(Consumer<org.springframework.web.reactive.function.client.ExchangeStrategies.Builder> var1);
WebClient.Builder exchangeFunction(ExchangeFunction var1);
WebClient.Builder apply(Consumer<WebClient.Builder> var1);
WebClient.Builder clone();
WebClient build();
}
}
DefaultWebClient:默認實現類
class DefaultWebClient implements WebClient {
private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate";
private static final Mono<ClientResponse> NO_HTTP_CLIENT_RESPONSE_ERROR = Mono.error(new IllegalStateException("The underlying HTTP client completed without emitting a response."));
private final ExchangeFunction exchangeFunction;
private final UriBuilderFactory uriBuilderFactory;
@Nullable
private final HttpHeaders defaultHeaders;
@Nullable
private final MultiValueMap<String, String> defaultCookies;
@Nullable
private final Consumer<RequestHeadersSpec<?>> defaultRequest;
private final DefaultWebClientBuilder builder;
***********
構造方法
DefaultWebClient(ExchangeFunction exchangeFunction, @Nullable UriBuilderFactory factory, @Nullable HttpHeaders defaultHeaders, @Nullable MultiValueMap<String, String> defaultCookies, @Nullable Consumer<RequestHeadersSpec<?>> defaultRequest, DefaultWebClientBuilder builder) {
this.exchangeFunction = exchangeFunction;
this.uriBuilderFactory = (UriBuilderFactory)(factory != null ? factory : new DefaultUriBuilderFactory());
this.defaultHeaders = defaultHeaders;
this.defaultCookies = defaultCookies;
this.defaultRequest = defaultRequest;
this.builder = builder;
}
***********
普通方法
public RequestHeadersUriSpec<?> get() {
return this.methodInternal(HttpMethod.GET);
}
public RequestHeadersUriSpec<?> head() {
return this.methodInternal(HttpMethod.HEAD);
}
public RequestBodyUriSpec post() {
return this.methodInternal(HttpMethod.POST);
}
public RequestBodyUriSpec put() {
return this.methodInternal(HttpMethod.PUT);
}
public RequestBodyUriSpec patch() {
return this.methodInternal(HttpMethod.PATCH);
}
public RequestHeadersUriSpec<?> delete() {
return this.methodInternal(HttpMethod.DELETE);
}
public RequestHeadersUriSpec<?> options() {
return this.methodInternal(HttpMethod.OPTIONS);
}
public RequestBodyUriSpec method(HttpMethod httpMethod) {
return this.methodInternal(httpMethod);
}
private RequestBodyUriSpec methodInternal(HttpMethod httpMethod) {
return new DefaultWebClient.DefaultRequestBodyUriSpec(httpMethod);
}
public Builder mutate() {
return new DefaultWebClientBuilder(this.builder);
}
***********
內部類:DefaultWebClient.DefaultResponseSpec
private static class DefaultResponseSpec implements ResponseSpec {
private static final IntPredicate STATUS_CODE_ERROR = (value) -> {
return value >= 400;
};
private static final DefaultWebClient.DefaultResponseSpec.StatusHandler DEFAULT_STATUS_HANDLER;
private final Mono<ClientResponse> responseMono;
private final Supplier<HttpRequest> requestSupplier;
private final List<DefaultWebClient.DefaultResponseSpec.StatusHandler> statusHandlers = new ArrayList(1);
DefaultResponseSpec(Mono<ClientResponse> responseMono, Supplier<HttpRequest> requestSupplier) {
this.responseMono = responseMono;
this.requestSupplier = requestSupplier;
this.statusHandlers.add(DEFAULT_STATUS_HANDLER);
}
public ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
return this.onRawStatus(toIntPredicate(statusPredicate), exceptionFunction);
}
private static IntPredicate toIntPredicate(Predicate<HttpStatus> predicate) {
return (value) -> {
HttpStatus status = HttpStatus.resolve(value);
return status != null && predicate.test(status);
};
}
public ResponseSpec onRawStatus(IntPredicate statusCodePredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
Assert.notNull(statusCodePredicate, "IntPredicate must not be null");
Assert.notNull(exceptionFunction, "Function must not be null");
int index = this.statusHandlers.size() - 1;
this.statusHandlers.add(index, new DefaultWebClient.DefaultResponseSpec.StatusHandler(statusCodePredicate, exceptionFunction));
return this;
}
public <T> Mono<T> bodyToMono(Class<T> elementClass) {
Assert.notNull(elementClass, "Class must not be null");
return this.responseMono.flatMap((response) -> {
return this.handleBodyMono(response, response.bodyToMono(elementClass));
});
}
public <T> Mono<T> bodyToMono(ParameterizedTypeReference<T> elementTypeRef) {
Assert.notNull(elementTypeRef, "ParameterizedTypeReference must not be null");
return this.responseMono.flatMap((response) -> {
return this.handleBodyMono(response, response.bodyToMono(elementTypeRef));
});
}
private <T> Mono<T> handleBodyMono(ClientResponse response, Mono<T> bodyPublisher) {
Mono<T> result = this.statusHandlers(response);
return result != null ? result.switchIfEmpty(bodyPublisher) : bodyPublisher;
}
public <T> Flux<T> bodyToFlux(Class<T> elementClass) {
Assert.notNull(elementClass, "Class must not be null");
return this.responseMono.flatMapMany((response) -> {
return this.handleBodyFlux(response, response.bodyToFlux(elementClass));
});
}
public <T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> elementTypeRef) {
Assert.notNull(elementTypeRef, "ParameterizedTypeReference must not be null");
return this.responseMono.flatMapMany((response) -> {
return this.handleBodyFlux(response, response.bodyToFlux(elementTypeRef));
});
}
private <T> Publisher<T> handleBodyFlux(ClientResponse response, Flux<T> bodyPublisher) {
Mono<T> result = this.statusHandlers(response);
return result != null ? result.flux().switchIfEmpty(bodyPublisher) : bodyPublisher;
}
@Nullable
private <T> Mono<T> statusHandlers(ClientResponse response) {
int statusCode = response.rawStatusCode();
Iterator var3 = this.statusHandlers.iterator();
DefaultWebClient.DefaultResponseSpec.StatusHandler handler;
do {
if (!var3.hasNext()) {
return null;
}
handler = (DefaultWebClient.DefaultResponseSpec.StatusHandler)var3.next();
} while(!handler.test(statusCode));
Mono exMono;
try {
exMono = handler.apply(response);
exMono = exMono.flatMap((ex) -> {
return this.drainBody(response, ex);
});
exMono = exMono.onErrorResume((ex) -> {
return this.drainBody(response, ex);
});
} catch (Throwable var8) {
exMono = this.drainBody(response, var8);
}
Mono<T> result = exMono.flatMap(Mono::error);
HttpRequest request = (HttpRequest)this.requestSupplier.get();
return this.insertCheckpoint(result, statusCode, request);
}
private <T> Mono<T> drainBody(ClientResponse response, Throwable ex) {
return response.releaseBody().onErrorResume((ex2) -> {
return Mono.empty();
}).thenReturn(ex);
}
private <T> Mono<T> insertCheckpoint(Mono<T> result, int statusCode, HttpRequest request) {
String httpMethod = request.getMethodValue();
URI uri = request.getURI();
String description = statusCode + " from " + httpMethod + " " + uri + " [DefaultWebClient]";
return result.checkpoint(description);
}
public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyClass) {
return this.responseMono.flatMap((response) -> {
return WebClientUtils.mapToEntity(response, this.handleBodyMono(response, response.bodyToMono(bodyClass)));
});
}
public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeRef) {
return this.responseMono.flatMap((response) -> {
return WebClientUtils.mapToEntity(response, this.handleBodyMono(response, response.bodyToMono(bodyTypeRef)));
});
}
public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass) {
return this.responseMono.flatMap((response) -> {
return WebClientUtils.mapToEntityList(response, this.handleBodyFlux(response, response.bodyToFlux(elementClass)));
});
}
public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef) {
return this.responseMono.flatMap((response) -> {
return WebClientUtils.mapToEntityList(response, this.handleBodyFlux(response, response.bodyToFlux(elementTypeRef)));
});
}
public Mono<ResponseEntity<Void>> toBodilessEntity() {
return this.responseMono.flatMap((response) -> {
return WebClientUtils.mapToEntity(response, this.handleBodyMono(response, Mono.empty())).flatMap((entity) -> {
return response.releaseBody().thenReturn(entity);
});
});
}
static {
DEFAULT_STATUS_HANDLER = new DefaultWebClient.DefaultResponseSpec.StatusHandler(STATUS_CODE_ERROR, ClientResponse::createException);
}
private static class StatusHandler {
private final IntPredicate predicate;
private final Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction;
public StatusHandler(IntPredicate predicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction) {
this.predicate = predicate;
this.exceptionFunction = exceptionFunction;
}
public boolean test(int status) {
return this.predicate.test(status);
}
public Mono<? extends Throwable> apply(ClientResponse response) {
return (Mono)this.exceptionFunction.apply(response);
}
}
}
***********
內部類:DefaultWebClient.DefaultRequestBodyUriSpec
private class DefaultRequestBodyUriSpec implements RequestBodyUriSpec {
private final HttpMethod httpMethod;
@Nullable
private URI uri;
@Nullable
private HttpHeaders headers;
@Nullable
private MultiValueMap<String, String> cookies;
@Nullable
private BodyInserter<?, ? super ClientHttpRequest> inserter;
private final Map<String, Object> attributes = new LinkedHashMap(4);
DefaultRequestBodyUriSpec(HttpMethod httpMethod) {
this.httpMethod = httpMethod;
}
public RequestBodySpec uri(String uriTemplate, Object... uriVariables) {
this.attribute(DefaultWebClient.URI_TEMPLATE_ATTRIBUTE, uriTemplate);
return this.uri(DefaultWebClient.this.uriBuilderFactory.expand(uriTemplate, uriVariables));
}
public RequestBodySpec uri(String uriTemplate, Map<String, ?> uriVariables) {
this.attribute(DefaultWebClient.URI_TEMPLATE_ATTRIBUTE, uriTemplate);
return this.uri(DefaultWebClient.this.uriBuilderFactory.expand(uriTemplate, uriVariables));
}
public RequestBodySpec uri(String uriTemplate, Function<UriBuilder, URI> uriFunction) {
this.attribute(DefaultWebClient.URI_TEMPLATE_ATTRIBUTE, uriTemplate);
return this.uri((URI)uriFunction.apply(DefaultWebClient.this.uriBuilderFactory.uriString(uriTemplate)));
}
public RequestBodySpec uri(Function<UriBuilder, URI> uriFunction) {
return this.uri((URI)uriFunction.apply(DefaultWebClient.this.uriBuilderFactory.builder()));
}
public RequestBodySpec uri(URI uri) {
this.uri = uri;
return this;
}
private HttpHeaders getHeaders() {
if (this.headers == null) {
this.headers = new HttpHeaders();
}
return this.headers;
}
private MultiValueMap<String, String> getCookies() {
if (this.cookies == null) {
this.cookies = new LinkedMultiValueMap(4);
}
return this.cookies;
}
public DefaultWebClient.DefaultRequestBodyUriSpec header(String headerName, String... headerValues) {
String[] var3 = headerValues;
int var4 = headerValues.length;
for(int var5 = 0; var5 < var4; ++var5) {
String headerValue = var3[var5];
this.getHeaders().add(headerName, headerValue);
}
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec headers(Consumer<HttpHeaders> headersConsumer) {
headersConsumer.accept(this.getHeaders());
return this;
}
public RequestBodySpec attribute(String name, Object value) {
this.attributes.put(name, value);
return this;
}
public RequestBodySpec attributes(Consumer<Map<String, Object>> attributesConsumer) {
attributesConsumer.accept(this.attributes);
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec accept(MediaType... acceptableMediaTypes) {
this.getHeaders().setAccept(Arrays.asList(acceptableMediaTypes));
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec acceptCharset(Charset... acceptableCharsets) {
this.getHeaders().setAcceptCharset(Arrays.asList(acceptableCharsets));
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec contentType(MediaType contentType) {
this.getHeaders().setContentType(contentType);
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec contentLength(long contentLength) {
this.getHeaders().setContentLength(contentLength);
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec cookie(String name, String value) {
this.getCookies().add(name, value);
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec cookies(Consumer<MultiValueMap<String, String>> cookiesConsumer) {
cookiesConsumer.accept(this.getCookies());
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec ifModifiedSince(ZonedDateTime ifModifiedSince) {
this.getHeaders().setIfModifiedSince(ifModifiedSince);
return this;
}
public DefaultWebClient.DefaultRequestBodyUriSpec ifNoneMatch(String... ifNoneMatches) {
this.getHeaders().setIfNoneMatch(Arrays.asList(ifNoneMatches));
return this;
}
public RequestHeadersSpec<?> bodyValue(Object body) {
this.inserter = BodyInserters.fromValue(body);
return this;
}
public <T, P extends Publisher<T>> RequestHeadersSpec<?> body(P publisher, ParameterizedTypeReference<T> elementTypeRef) {
this.inserter = BodyInserters.fromPublisher(publisher, elementTypeRef);
return this;
}
public <T, P extends Publisher<T>> RequestHeadersSpec<?> body(P publisher, Class<T> elementClass) {
this.inserter = BodyInserters.fromPublisher(publisher, elementClass);
return this;
}
public RequestHeadersSpec<?> body(Object producer, Class<?> elementClass) {
this.inserter = BodyInserters.fromProducer(producer, elementClass);
return this;
}
public RequestHeadersSpec<?> body(Object producer, ParameterizedTypeReference<?> elementTypeRef) {
this.inserter = BodyInserters.fromProducer(producer, elementTypeRef);
return this;
}
public RequestHeadersSpec<?> body(BodyInserter<?, ? super ClientHttpRequest> inserter) {
this.inserter = inserter;
return this;
}
/** @deprecated */
@Deprecated
public RequestHeadersSpec<?> syncBody(Object body) {
return this.bodyValue(body);
}
public Mono<ClientResponse> exchange() {
ClientRequest request = this.inserter != null ? this.initRequestBuilder().body(this.inserter).build() : this.initRequestBuilder().build();
return Mono.defer(() -> {
return DefaultWebClient.this.exchangeFunction.exchange(request).checkpoint("Request to " + this.httpMethod.name() + " " + this.uri + " [DefaultWebClient]").switchIfEmpty(DefaultWebClient.NO_HTTP_CLIENT_RESPONSE_ERROR);
});
}
private org.springframework.web.reactive.function.client.ClientRequest.Builder initRequestBuilder() {
if (DefaultWebClient.this.defaultRequest != null) {
DefaultWebClient.this.defaultRequest.accept(this);
}
return ClientRequest.create(this.httpMethod, this.initUri()).headers((headers) -> {
headers.addAll(this.initHeaders());
}).cookies((cookies) -> {
cookies.addAll(this.initCookies());
}).attributes((attributes) -> {
attributes.putAll(this.attributes);
});
}
private URI initUri() {
return this.uri != null ? this.uri : DefaultWebClient.this.uriBuilderFactory.expand("", new Object[0]);
}
private HttpHeaders initHeaders() {
if (CollectionUtils.isEmpty(this.headers)) {
return DefaultWebClient.this.defaultHeaders != null ? DefaultWebClient.this.defaultHeaders : new HttpHeaders();
} else if (CollectionUtils.isEmpty(DefaultWebClient.this.defaultHeaders)) {
return this.headers;
} else {
HttpHeaders result = new HttpHeaders();
result.putAll(DefaultWebClient.this.defaultHeaders);
result.putAll(this.headers);
return result;
}
}
private MultiValueMap<String, String> initCookies() {
if (CollectionUtils.isEmpty(this.cookies)) {
return (MultiValueMap)(DefaultWebClient.this.defaultCookies != null ? DefaultWebClient.this.defaultCookies : new LinkedMultiValueMap());
} else if (CollectionUtils.isEmpty(DefaultWebClient.this.defaultCookies)) {
return this.cookies;
} else {
MultiValueMap<String, String> result = new LinkedMultiValueMap();
result.putAll(DefaultWebClient.this.defaultCookies);
result.putAll(this.cookies);
return result;
}
}
public ResponseSpec retrieve() {
return new DefaultWebClient.DefaultResponseSpec(this.exchange(), this::createRequest);
}
private HttpRequest createRequest() {
return new HttpRequest() {
private final URI uri = DefaultRequestBodyUriSpec.this.initUri();
private final HttpHeaders headers = DefaultRequestBodyUriSpec.this.initHeaders();
public HttpMethod getMethod() {
return DefaultRequestBodyUriSpec.this.httpMethod;
}
public String getMethodValue() {
return DefaultRequestBodyUriSpec.this.httpMethod.name();
}
public URI getURI() {
return this.uri;
}
public HttpHeaders getHeaders() {
return this.headers;
}
};
}
}
}
DefaultWebClientBuilder
final class DefaultWebClientBuilder implements Builder {
private static final boolean reactorClientPresent;
private static final boolean jettyClientPresent;
@Nullable
private String baseUrl;
@Nullable
private Map<String, ?> defaultUriVariables;
@Nullable
private UriBuilderFactory uriBuilderFactory;
@Nullable
private HttpHeaders defaultHeaders;
@Nullable
private MultiValueMap<String, String> defaultCookies;
@Nullable
private Consumer<RequestHeadersSpec<?>> defaultRequest;
@Nullable
private List<ExchangeFilterFunction> filters;
@Nullable
private ClientHttpConnector connector;
@Nullable
private ExchangeStrategies strategies;
@Nullable
private List<Consumer<org.springframework.web.reactive.function.client.ExchangeStrategies.Builder>> strategiesConfigurers;
@Nullable
private ExchangeFunction exchangeFunction;
**************
構造方法
public DefaultWebClientBuilder() {
}
public DefaultWebClientBuilder(DefaultWebClientBuilder other) {
Assert.notNull(other, "DefaultWebClientBuilder must not be null");
this.baseUrl = other.baseUrl;
this.defaultUriVariables = other.defaultUriVariables != null ? new LinkedHashMap(other.defaultUriVariables) : null;
this.uriBuilderFactory = other.uriBuilderFactory;
if (other.defaultHeaders != null) {
this.defaultHeaders = new HttpHeaders();
this.defaultHeaders.putAll(other.defaultHeaders);
} else {
this.defaultHeaders = null;
}
this.defaultCookies = other.defaultCookies != null ? new LinkedMultiValueMap(other.defaultCookies) : null;
this.defaultRequest = other.defaultRequest;
this.filters = other.filters != null ? new ArrayList(other.filters) : null;
this.connector = other.connector;
this.strategies = other.strategies;
this.strategiesConfigurers = other.strategiesConfigurers != null ? new ArrayList(other.strategiesConfigurers) : null;
this.exchangeFunction = other.exchangeFunction;
}
**************
普通方法
public Builder baseUrl(String baseUrl) {
public Builder defaultUriVariables(Map<String, ?> defaultUriVariables) {
public Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
public Builder defaultHeader(String header, String... values) {
public Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer) {
private HttpHeaders initHeaders() {
if (this.defaultHeaders == null) {
this.defaultHeaders = new HttpHeaders();
}
return this.defaultHeaders;
}
public Builder defaultCookie(String cookie, String... values) {
public Builder defaultCookies(Consumer<MultiValueMap<String, String>> cookiesConsumer) {
private MultiValueMap<String, String> initCookies() {
if (this.defaultCookies == null) {
this.defaultCookies = new LinkedMultiValueMap(4);
}
return this.defaultCookies;
}
public Builder defaultRequest(Consumer<RequestHeadersSpec<?>> defaultRequest) {
this.defaultRequest = this.defaultRequest != null ? this.defaultRequest.andThen(defaultRequest) : defaultRequest;
return this;
}
public Builder filter(ExchangeFilterFunction filter) {
Assert.notNull(filter, "ExchangeFilterFunction must not be null");
this.initFilters().add(filter);
return this;
}
public Builder filters(Consumer<List<ExchangeFilterFunction>> filtersConsumer) {
filtersConsumer.accept(this.initFilters());
return this;
}
private List<ExchangeFilterFunction> initFilters() {
if (this.filters == null) {
this.filters = new ArrayList();
}
return this.filters;
}
public Builder clientConnector(ClientHttpConnector connector) {
this.connector = connector;
return this;
}
public Builder codecs(Consumer<ClientCodecConfigurer> configurer) {
if (this.strategiesConfigurers == null) {
this.strategiesConfigurers = new ArrayList(4);
}
this.strategiesConfigurers.add((builder) -> {
builder.codecs(configurer);
});
return this;
}
public Builder exchangeStrategies(ExchangeStrategies strategies) {
this.strategies = strategies;
return this;
}
public Builder exchangeFunction(ExchangeFunction exchangeFunction) {
this.exchangeFunction = exchangeFunction;
return this;
}
public Builder apply(Consumer<Builder> builderConsumer) {
builderConsumer.accept(this);
return this;
}
public Builder clone() {
return new DefaultWebClientBuilder(this);
}
public WebClient build() { //返回WebClient對象
ExchangeFunction exchange = this.exchangeFunction == null ? ExchangeFunctions.create(this.getOrInitConnector(), this.initExchangeStrategies()) : this.exchangeFunction;
ExchangeFunction filteredExchange = this.filters != null ? (ExchangeFunction)this.filters.stream().reduce(ExchangeFilterFunction::andThen).map((filter) -> {
return filter.apply(exchange);
}).orElse(exchange) : exchange;
return new DefaultWebClient(filteredExchange, this.initUriBuilderFactory(), this.defaultHeaders != null ? HttpHeaders.readOnlyHttpHeaders(this.defaultHeaders) : null, this.defaultCookies != null ? CollectionUtils.unmodifiableMultiValueMap(this.defaultCookies) : null, this.defaultRequest, new DefaultWebClientBuilder(this));
}
private ClientHttpConnector getOrInitConnector() {
if (this.connector != null) {
return this.connector;
} else if (reactorClientPresent) {
return new ReactorClientHttpConnector();
} else if (jettyClientPresent) {
return new JettyClientHttpConnector();
} else {
throw new IllegalStateException("No suitable default ClientHttpConnector found");
}
}
private ExchangeStrategies initExchangeStrategies() {
if (CollectionUtils.isEmpty(this.strategiesConfigurers)) {
return this.strategies != null ? this.strategies : ExchangeStrategies.withDefaults();
} else {
org.springframework.web.reactive.function.client.ExchangeStrategies.Builder builder = this.strategies != null ? this.strategies.mutate() : ExchangeStrategies.builder();
this.strategiesConfigurers.forEach((configurer) -> {
configurer.accept(builder);
});
return builder.build();
}
}
private UriBuilderFactory initUriBuilderFactory() {
if (this.uriBuilderFactory != null) {
return this.uriBuilderFactory;
} else {
DefaultUriBuilderFactory factory = this.baseUrl != null ? new DefaultUriBuilderFactory(this.baseUrl) : new DefaultUriBuilderFactory();
factory.setDefaultUriVariables(this.defaultUriVariables);
return factory;
}
}
static {
ClassLoader loader = DefaultWebClientBuilder.class.getClassLoader();
reactorClientPresent = ClassUtils.isPresent("reactor.netty.http.client.HttpClient", loader);
jettyClientPresent = ClassUtils.isPresent("org.eclipse.jetty.client.HttpClient", loader);
}
}
WebClientAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({WebClient.class})
@AutoConfigureAfter({CodecsAutoConfiguration.class, ClientHttpConnectorAutoConfiguration.class})
public class WebClientAutoConfiguration {
public WebClientAutoConfiguration() {
}
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
public Builder webClientBuilder(ObjectProvider<WebClientCustomizer> customizerProvider) {
//返回WebClient.Builder對象,可使用該對象直接創建WebClient
Builder builder = WebClient.builder();
customizerProvider.orderedStream().forEach((customizer) -> {
customizer.customize(builder);
});
return builder;
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnBean({CodecCustomizer.class})
protected static class WebClientCodecsConfiguration {
protected WebClientCodecsConfiguration() {
}
@Bean
@ConditionalOnMissingBean
@Order(0)
public WebClientCodecCustomizer exchangeStrategiesCustomizer(ObjectProvider<CodecCustomizer> codecCustomizers) {
return new WebClientCodecCustomizer((List)codecCustomizers.orderedStream().collect(Collectors.toList()));
}
}
}
ClientResponse
public interface ClientResponse {
HttpStatus statusCode();
int rawStatusCode();
ClientResponse.Headers headers();
MultiValueMap<String, ResponseCookie> cookies();
ExchangeStrategies strategies();
<T> T body(BodyExtractor<T, ? super ClientHttpResponse> var1);
//將ClientHttpResponse內容提取出來,轉換爲制定的類型T
<T> Mono<T> bodyToMono(Class<? extends T> var1);
<T> Mono<T> bodyToMono(ParameterizedTypeReference<T> var1);
<T> Flux<T> bodyToFlux(Class<? extends T> var1);
<T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> var1);
Mono<Void> releaseBody();
<T> Mono<ResponseEntity<T>> toEntity(Class<T> var1);
<T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> var1);
<T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> var1);
<T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> var1);
Mono<ResponseEntity<Void>> toBodilessEntity();
Mono<WebClientResponseException> createException();
String logPrefix();
static ClientResponse.Builder from(ClientResponse other) {
return new DefaultClientResponseBuilder(other);
}
static ClientResponse.Builder create(HttpStatus statusCode) {
return create(statusCode, ExchangeStrategies.withDefaults());
}
static ClientResponse.Builder create(HttpStatus statusCode, ExchangeStrategies strategies) {
return (new DefaultClientResponseBuilder(strategies)).statusCode(statusCode);
}
static ClientResponse.Builder create(int statusCode, ExchangeStrategies strategies) {
return (new DefaultClientResponseBuilder(strategies)).rawStatusCode(statusCode);
}
static ClientResponse.Builder create(HttpStatus statusCode, final List<HttpMessageReader<?>> messageReaders) {
return create(statusCode, new ExchangeStrategies() {
public List<HttpMessageReader<?>> messageReaders() {
return messageReaders;
}
public List<HttpMessageWriter<?>> messageWriters() {
return Collections.emptyList();
}
});
}
public interface Builder {
ClientResponse.Builder statusCode(HttpStatus var1);
ClientResponse.Builder rawStatusCode(int var1);
ClientResponse.Builder header(String var1, String... var2);
ClientResponse.Builder headers(Consumer<HttpHeaders> var1);
ClientResponse.Builder cookie(String var1, String... var2);
ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> var1);
ClientResponse.Builder body(Flux<DataBuffer> var1);
ClientResponse.Builder body(String var1);
ClientResponse.Builder request(HttpRequest var1);
ClientResponse build();
}
public interface Headers {
OptionalLong contentLength();
Optional<MediaType> contentType();
List<String> header(String var1);
HttpHeaders asHttpHeaders();
}
}
BodyExtractor
@FunctionalInterface
public interface BodyExtractor<T, M extends ReactiveHttpInputMessage> {
T extract(M var1, BodyExtractor.Context var2);
public interface Context {
List<HttpMessageReader<?>> messageReaders();
Optional<ServerHttpResponse> serverResponse();
Map<String, Object> hints();
}
}