40
40
import org .springframework .web .reactive .function .BodyInserter ;
41
41
import org .springframework .web .util .UriBuilder ;
42
42
import org .springframework .web .util .UriBuilderFactory ;
43
+ import org .springframework .web .reactive .function .BodyInserters ;
43
44
44
45
/**
45
- * The main entry point for initiating web requests on the client side.
46
+ * A non-blocking, reactive client for performing HTTP requests with Reactive
47
+ * Streams back pressure. Provides a higher level, common API over HTTP client
48
+ * libraries. Reactor Netty is used by default but other clients may be plugged
49
+ * in with a {@link ClientHttpConnector}.
46
50
*
47
- * <pre class="code">
48
- * // Initialize the client
49
- * WebClient client = WebClient.create("http://abc.com");
51
+ * <p>Use one of the static factory methods {@link #create()} or
52
+ * {@link #create(String)} or obtain a {@link WebClient#builder()} to create an
53
+ * instance.
50
54
*
51
- * // Perform requests...
52
- * Mono<String> result = client.get()
53
- * .uri("/foo")
54
- * .exchange()
55
- * .then(response -> response.bodyToMono(String.class));
56
- * </pre>
55
+ * <p>For examples with a response body see
56
+ * {@link RequestHeadersSpec#retrieve() retrieve()} and
57
+ * {@link RequestHeadersSpec#exchange() exchange()}.
58
+ * For examples with a request body see
59
+ * {@link RequestBodySpec#body(Publisher, Class) body(Publisher,Class)},
60
+ * {@link RequestBodySpec#syncBody(Object) syncBody(Object)}, and
61
+ * {@link RequestBodySpec#body(BodyInserter) body(BodyInserter)}.
57
62
*
58
63
* @author Rossen Stoyanchev
59
64
* @author Arjen Poutsma
@@ -119,54 +124,17 @@ public interface WebClient {
119
124
// Static, factory methods
120
125
121
126
/**
122
- * Create a new {@code WebClient} with no default, shared preferences across
123
- * requests such as base URI, default headers, and others.
127
+ * Create a new {@code WebClient} with a Reactor Netty connector.
124
128
* @see #create(String)
129
+ * @see #builder()
125
130
*/
126
131
static WebClient create () {
127
132
return new DefaultWebClientBuilder ().build ();
128
133
}
129
134
130
135
/**
131
- * Configure a base URI for requests performed through the client for
132
- * example to avoid repeating the same host, port, base path, or even
133
- * query parameters with every request.
134
- * <p>For example given this initialization:
135
- * <pre class="code">
136
- * WebClient client = WebClient.create("http://abc.com/v1");
137
- * </pre>
138
- * <p>The base URI is applied to exchanges with a URI template:
139
- * <pre class="code">
140
- * // GET http://abc.com/v1/accounts/43
141
- * Mono<Account> result = client.get()
142
- * .uri("/accounts/{id}", 43)
143
- * .exchange()
144
- * .then(response -> response.bodyToMono(Account.class));
145
- * </pre>
146
- * <p>The base URI is also applied to exchanges with a {@code UriBuilder}:
147
- * <pre class="code">
148
- * // GET http://abc.com/v1/accounts?q=12
149
- * Flux<Account> result = client.get()
150
- * .uri(builder -> builder.path("/accounts").queryParam("q", "12").build())
151
- * .exchange()
152
- * .then(response -> response.bodyToFlux(Account.class));
153
- * </pre>
154
- * <p>The base URI can be overridden with an absolute URI:
155
- * <pre class="code">
156
- * // GET http://xyz.com/path
157
- * Mono<Account> result = client.get()
158
- * .uri("http://xyz.com/path")
159
- * .exchange()
160
- * .then(response -> response.bodyToMono(Account.class));
161
- * </pre>
162
- * <p>The base URI can be partially overridden with a {@code UriBuilder}:
163
- * <pre class="code">
164
- * // GET http://abc.com/v2/accounts?q=12
165
- * Flux<Account> result = client.get()
166
- * .uri(builder -> builder.replacePath("/v2/accounts").queryParam("q", "12").build())
167
- * .exchange()
168
- * .then(response -> response.bodyToFlux(Account.class));
169
- * </pre>
136
+ * A variant of {@link #create()} that accepts a default base URL. For more
137
+ * details see {@link Builder#baseUrl(String) Builder.baseUrl(String)}.
170
138
* @param baseUrl the base URI for all requests
171
139
*/
172
140
static WebClient create (String baseUrl ) {
@@ -182,13 +150,50 @@ static WebClient.Builder builder() {
182
150
183
151
184
152
/**
185
- * A mutable builder for a {@link WebClient}.
153
+ * A mutable builder for creating a {@link WebClient}.
186
154
*/
187
155
interface Builder {
188
156
189
157
/**
190
- * Configure a base URI as described in {@link WebClient#create(String)
191
- * WebClient.create(String)}.
158
+ * Configure a base URL for requests performed through the client.
159
+ *
160
+ * <p>For example given base URL "http://abc.com/v1":
161
+ * <p><pre class="code">
162
+ * Mono<Account> result = client.get()
163
+ * .uri("/accounts/{id}", 43)
164
+ * .exchange()
165
+ * .then(response -> response.bodyToMono(Account.class));
166
+ *
167
+ * // Result: http://abc.com/v1/accounts/43
168
+ *
169
+ * Flux<Account> result = client.get()
170
+ * .uri(builder -> builder.path("/accounts").queryParam("q", "12").build())
171
+ * .exchange()
172
+ * .then(response -> response.bodyToFlux(Account.class));
173
+ *
174
+ * // Result: http://abc.com/v1/accounts?q=12
175
+ * </pre>
176
+ *
177
+ * <p>The base URL can be overridden with an absolute URI:
178
+ * <pre class="code">
179
+ * Mono<Account> result = client.get()
180
+ * .uri("http://xyz.com/path")
181
+ * .exchange()
182
+ * .then(response -> response.bodyToMono(Account.class));
183
+ *
184
+ * // Result: http://xyz.com/path
185
+ * </pre>
186
+ *
187
+ * <p>Or partially overridden with a {@code UriBuilder}:
188
+ * <pre class="code">
189
+ * Flux<Account> result = client.get()
190
+ * .uri(builder -> builder.replacePath("/v2/accounts").queryParam("q", "12").build())
191
+ * .exchange()
192
+ * .then(response -> response.bodyToFlux(Account.class));
193
+ *
194
+ * // Result: http://abc.com/v2/accounts?q=12
195
+ * </pre>
196
+ *
192
197
* @see #defaultUriVariables(Map)
193
198
* @see #uriBuilderFactory(UriBuilderFactory)
194
199
*/
@@ -510,51 +515,72 @@ interface RequestBodySpec extends RequestHeadersSpec<RequestBodySpec> {
510
515
RequestBodySpec contentType (MediaType contentType );
511
516
512
517
/**
513
- * Set the body of the request to the given {@code BodyInserter}.
514
- * @param inserter the {@code BodyInserter} that writes to the request
518
+ * Set the body of the request using the given body inserter.
519
+ * {@link BodyInserters} provides access to built-in implementations of
520
+ * {@link BodyInserter}.
521
+ * @param inserter the body inserter to use for the request body
515
522
* @return this builder
523
+ * @see org.springframework.web.reactive.function.BodyInserters
516
524
*/
517
525
RequestHeadersSpec <?> body (BodyInserter <?, ? super ClientHttpRequest > inserter );
518
526
519
527
/**
520
- * Set the body of the request to the given asynchronous {@code Publisher}.
521
- * <p>This method is a convenient shortcut for {@link #body(BodyInserter)} with a
522
- * {@linkplain org.springframework.web.reactive.function.BodyInserters#fromPublisher}
523
- * Publisher body inserter}.
528
+ * A shortcut for {@link #body(BodyInserter)} with a
529
+ * {@linkplain BodyInserters#fromPublisher Publisher inserter}.
530
+ * For example:
531
+ * <p><pre>
532
+ * Mono<Person> personMono = ... ;
533
+ *
534
+ * Mono<Void> result = client.post()
535
+ * .uri("/persons/{id}", id)
536
+ * .contentType(MediaType.APPLICATION_JSON)
537
+ * .body(personMono, Person.class)
538
+ * .retrieve()
539
+ * .bodyToMono(Void.class);
540
+ * </pre>
524
541
* @param publisher the {@code Publisher} to write to the request
525
- * @param typeReference the type reference of elements contained in the publisher
542
+ * @param elementClass the class of elements contained in the publisher
526
543
* @param <T> the type of the elements contained in the publisher
527
544
* @param <P> the type of the {@code Publisher}
528
545
* @return this builder
529
546
*/
530
- <T , P extends Publisher <T >> RequestHeadersSpec <?> body (P publisher , ParameterizedTypeReference <T > typeReference );
547
+ <T , P extends Publisher <T >> RequestHeadersSpec <?> body (P publisher , Class <T > elementClass );
531
548
532
549
/**
533
- * Set the body of the request to the given asynchronous {@code Publisher}.
534
- * <p>This method is a convenient shortcut for {@link #body(BodyInserter)} with a
535
- * {@linkplain org.springframework.web.reactive.function.BodyInserters#fromPublisher}
536
- * Publisher body inserter}.
550
+ * A variant of {@link #body(Publisher, Class)} that allows providing
551
+ * element type information that includes generics via a
552
+ * {@link ParameterizedTypeReference}.
537
553
* @param publisher the {@code Publisher} to write to the request
538
- * @param elementClass the class of elements contained in the publisher
554
+ * @param typeReference the type reference of elements contained in the publisher
539
555
* @param <T> the type of the elements contained in the publisher
540
556
* @param <P> the type of the {@code Publisher}
541
557
* @return this builder
542
558
*/
543
- <T , P extends Publisher <T >> RequestHeadersSpec <?> body (P publisher , Class <T > elementClass );
559
+ <T , P extends Publisher <T >> RequestHeadersSpec <?> body (P publisher ,
560
+ ParameterizedTypeReference <T > typeReference );
544
561
545
562
/**
546
- * Set the body of the request to the given synchronous {@code Object}.
547
- * <p>This method is a convenient shortcut for:
548
- * <pre class="code">
549
- * .body(BodyInserters.fromObject(object))
563
+ * A shortcut for {@link #body(BodyInserter)} with an
564
+ * {@linkplain BodyInserters#fromObject Object inserter}.
565
+ * For example:
566
+ * <p><pre class="code">
567
+ * Person person = ... ;
568
+ *
569
+ * Mono<Void> result = client.post()
570
+ * .uri("/persons/{id}", id)
571
+ * .contentType(MediaType.APPLICATION_JSON)
572
+ * .syncBody(person)
573
+ * .retrieve()
574
+ * .bodyToMono(Void.class);
550
575
* </pre>
551
- * <p>The body can be a
552
- * {@link org.springframework.util.MultiValueMap MultiValueMap} to create
553
- * a multipart request. The values in the {@code MultiValueMap} can be
554
- * any Object representing the body of the part, or an
555
- * {@link org.springframework.http.HttpEntity HttpEntity} representing a
556
- * part with body and headers. The {@code MultiValueMap} can be built
557
- * conveniently using
576
+ * <p>For multipart requests, provide a
577
+ * {@link org.springframework.util.MultiValueMap MultiValueMap}. The
578
+ * values in the {@code MultiValueMap} can be any Object representing
579
+ * the body of the part, or an
580
+ * {@link org.springframework.http.HttpEntity HttpEntity} representing
581
+ * a part with body and headers. The {@code MultiValueMap} can be built
582
+ * with {@link org.springframework.http.client.MultipartBodyBuilder
583
+ * MultipartBodyBuilder}.
558
584
* @param body the {@code Object} to write to the request
559
585
* @return this builder
560
586
*/
0 commit comments