springboot webflux webclient 使用說明


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();
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章