diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java index d697c4b3bc3..00335224619 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java @@ -40,20 +40,25 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.util.UriBuilder; import org.springframework.web.util.UriBuilderFactory; +import org.springframework.web.reactive.function.BodyInserters; /** - * The main entry point for initiating web requests on the client side. + * A non-blocking, reactive client for performing HTTP requests with Reactive + * Streams back pressure. Provides a higher level, common API over HTTP client + * libraries. Reactor Netty is used by default but other clients may be plugged + * in with a {@link ClientHttpConnector}. * - *
- * // Initialize the client
- * WebClient client = WebClient.create("http://abc.com");
+ * Use one of the static factory methods {@link #create()} or
+ * {@link #create(String)} or obtain a {@link WebClient#builder()} to create an
+ * instance.
*
- * // Perform requests...
- * Mono<String> result = client.get()
- * .uri("/foo")
- * .exchange()
- * .then(response -> response.bodyToMono(String.class));
- *
+ * For examples with a response body see + * {@link RequestHeadersSpec#retrieve() retrieve()} and + * {@link RequestHeadersSpec#exchange() exchange()}. + * For examples with a request body see + * {@link RequestBodySpec#body(Publisher, Class) body(Publisher,Class)}, + * {@link RequestBodySpec#syncBody(Object) syncBody(Object)}, and + * {@link RequestBodySpec#body(BodyInserter) body(BodyInserter)}. * * @author Rossen Stoyanchev * @author Arjen Poutsma @@ -119,54 +124,17 @@ public interface WebClient { // Static, factory methods /** - * Create a new {@code WebClient} with no default, shared preferences across - * requests such as base URI, default headers, and others. + * Create a new {@code WebClient} with a Reactor Netty connector. * @see #create(String) + * @see #builder() */ static WebClient create() { return new DefaultWebClientBuilder().build(); } /** - * Configure a base URI for requests performed through the client for - * example to avoid repeating the same host, port, base path, or even - * query parameters with every request. - *
For example given this initialization: - *
- * WebClient client = WebClient.create("http://abc.com/v1");
- *
- * The base URI is applied to exchanges with a URI template: - *
- * // GET http://abc.com/v1/accounts/43
- * Mono<Account> result = client.get()
- * .uri("/accounts/{id}", 43)
- * .exchange()
- * .then(response -> response.bodyToMono(Account.class));
- *
- * The base URI is also applied to exchanges with a {@code UriBuilder}: - *
- * // GET http://abc.com/v1/accounts?q=12
- * Flux<Account> result = client.get()
- * .uri(builder -> builder.path("/accounts").queryParam("q", "12").build())
- * .exchange()
- * .then(response -> response.bodyToFlux(Account.class));
- *
- * The base URI can be overridden with an absolute URI: - *
- * // GET http://xyz.com/path
- * Mono<Account> result = client.get()
- * .uri("http://xyz.com/path")
- * .exchange()
- * .then(response -> response.bodyToMono(Account.class));
- *
- * The base URI can be partially overridden with a {@code UriBuilder}: - *
- * // GET http://abc.com/v2/accounts?q=12
- * Flux<Account> result = client.get()
- * .uri(builder -> builder.replacePath("/v2/accounts").queryParam("q", "12").build())
- * .exchange()
- * .then(response -> response.bodyToFlux(Account.class));
- *
+ * A variant of {@link #create()} that accepts a default base URL. For more
+ * details see {@link Builder#baseUrl(String) Builder.baseUrl(String)}.
* @param baseUrl the base URI for all requests
*/
static WebClient create(String baseUrl) {
@@ -182,13 +150,50 @@ public interface WebClient {
/**
- * A mutable builder for a {@link WebClient}.
+ * A mutable builder for creating a {@link WebClient}.
*/
interface Builder {
/**
- * Configure a base URI as described in {@link WebClient#create(String)
- * WebClient.create(String)}.
+ * Configure a base URL for requests performed through the client.
+ *
+ * For example given base URL "http://abc.com/v1": + *
+ * Mono<Account> result = client.get()
+ * .uri("/accounts/{id}", 43)
+ * .exchange()
+ * .then(response -> response.bodyToMono(Account.class));
+ *
+ * // Result: http://abc.com/v1/accounts/43
+ *
+ * Flux<Account> result = client.get()
+ * .uri(builder -> builder.path("/accounts").queryParam("q", "12").build())
+ * .exchange()
+ * .then(response -> response.bodyToFlux(Account.class));
+ *
+ * // Result: http://abc.com/v1/accounts?q=12
+ *
+ *
+ * The base URL can be overridden with an absolute URI: + *
+ * Mono<Account> result = client.get()
+ * .uri("http://xyz.com/path")
+ * .exchange()
+ * .then(response -> response.bodyToMono(Account.class));
+ *
+ * // Result: http://xyz.com/path
+ *
+ *
+ * Or partially overridden with a {@code UriBuilder}: + *
+ * Flux<Account> result = client.get()
+ * .uri(builder -> builder.replacePath("/v2/accounts").queryParam("q", "12").build())
+ * .exchange()
+ * .then(response -> response.bodyToFlux(Account.class));
+ *
+ * // Result: http://abc.com/v2/accounts?q=12
+ *
+ *
* @see #defaultUriVariables(Map)
* @see #uriBuilderFactory(UriBuilderFactory)
*/
@@ -510,30 +515,29 @@ public interface WebClient {
RequestBodySpec contentType(MediaType contentType);
/**
- * Set the body of the request to the given {@code BodyInserter}.
- * @param inserter the {@code BodyInserter} that writes to the request
+ * Set the body of the request using the given body inserter.
+ * {@link BodyInserters} provides access to built-in implementations of
+ * {@link BodyInserter}.
+ * @param inserter the body inserter to use for the request body
* @return this builder
+ * @see org.springframework.web.reactive.function.BodyInserters
*/
RequestHeadersSpec> body(BodyInserter, ? super ClientHttpRequest> inserter);
/**
- * Set the body of the request to the given asynchronous {@code Publisher}.
- * This method is a convenient shortcut for {@link #body(BodyInserter)} with a
- * {@linkplain org.springframework.web.reactive.function.BodyInserters#fromPublisher}
- * Publisher body inserter}.
- * @param publisher the {@code Publisher} to write to the request
- * @param typeReference the type reference of elements contained in the publisher
- * @param the type of the {@code Publisher}
- * @return this builder
- */
- This method is a convenient shortcut for {@link #body(BodyInserter)} with a
- * {@linkplain org.springframework.web.reactive.function.BodyInserters#fromPublisher}
- * Publisher body inserter}.
+ * A shortcut for {@link #body(BodyInserter)} with a
+ * {@linkplain BodyInserters#fromPublisher Publisher inserter}.
+ * For example:
+ * This method is a convenient shortcut for:
- * the type of the {@code Publisher}
+ * @return this builder
+ */
+ The body can be a
- * {@link org.springframework.util.MultiValueMap MultiValueMap} to create
- * a multipart request. The values in the {@code MultiValueMap} can be
- * any Object representing the body of the part, or an
- * {@link org.springframework.http.HttpEntity HttpEntity} representing a
- * part with body and headers. The {@code MultiValueMap} can be built
- * conveniently using
+ * For multipart requests, provide a
+ * {@link org.springframework.util.MultiValueMap MultiValueMap}. The
+ * values in the {@code MultiValueMap} can be any Object representing
+ * the body of the part, or an
+ * {@link org.springframework.http.HttpEntity HttpEntity} representing
+ * a part with body and headers. The {@code MultiValueMap} can be built
+ * with {@link org.springframework.http.client.MultipartBodyBuilder
+ * MultipartBodyBuilder}.
* @param body the {@code Object} to write to the request
* @return this builder
*/
+ * Mono
* @param publisher the {@code Publisher} to write to the request
* @param elementClass the class of elements contained in the publisher
* @param
- * .body(BodyInserters.fromObject(object))
+ * A variant of {@link #body(Publisher, Class)} that allows providing
+ * element type information that includes generics via a
+ * {@link ParameterizedTypeReference}.
+ * @param publisher the {@code Publisher} to write to the request
+ * @param typeReference the type reference of elements contained in the publisher
+ * @param
+ * Person person = ... ;
+ *
+ * Mono
- *