diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java index e3ed0817b3..7b8a503689 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java @@ -16,7 +16,10 @@ package org.springframework.web.reactive.function.client; +import org.springframework.http.client.reactive.ClientHttpConnector; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.util.Assert; +import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.UriBuilderFactory; /** @@ -27,26 +30,41 @@ import org.springframework.web.util.UriBuilderFactory; */ class DefaultWebClientBuilder implements WebClient.Builder { - private final ExchangeFunction exchangeFunction; - private UriBuilderFactory uriBuilderFactory; + private ClientHttpConnector connector; - public DefaultWebClientBuilder(ExchangeFunction exchangeFunction) { - Assert.notNull(exchangeFunction, "'exchangeFunction' must not be null"); - this.exchangeFunction = exchangeFunction; + private ExchangeStrategies exchangeStrategies = ExchangeStrategies.withDefaults(); + + + public DefaultWebClientBuilder(String baseUrl) { + this(new DefaultUriBuilderFactory(baseUrl)); + } + + public DefaultWebClientBuilder(UriBuilderFactory uriBuilderFactory) { + Assert.notNull(uriBuilderFactory, "UriBuilderFactory is required."); + this.uriBuilderFactory = uriBuilderFactory; } @Override - public WebClient.Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory) { - this.uriBuilderFactory = uriBuilderFactory; + public WebClient.Builder clientConnector(ClientHttpConnector connector) { + this.connector = connector; + return this; + } + + @Override + public WebClient.Builder exchangeStrategies(ExchangeStrategies strategies) { + Assert.notNull(strategies, "ExchangeStrategies is required."); + this.exchangeStrategies = strategies; return this; } @Override public WebClient build() { - return new DefaultWebClient(this.exchangeFunction, this.uriBuilderFactory); + ClientHttpConnector connector = this.connector != null ? this.connector : new ReactorClientHttpConnector(); + ExchangeFunction exchangeFunction = ExchangeFunctions.create(connector, this.exchangeStrategies); + return new DefaultWebClient(exchangeFunction, this.uriBuilderFactory); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java index b78c66b734..0700fc3f48 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java @@ -30,6 +30,7 @@ import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.util.DefaultUriBuilderFactory; import org.springframework.web.util.UriBuilderFactory; /** @@ -117,39 +118,35 @@ public interface WebClient { // Static, factory methods /** - * Create {@code WebClient} that uses the given {@link ClientHttpConnector}. - * @param connector the underlying connector to use + * Shortcut for: + *
+	 * WebClient client = builder(baseUrl).build();
+	 * 
+ * @param baseUrl the base URI for all requests */ - static WebClient create(ClientHttpConnector connector) { - return create(ExchangeFunctions.create(connector)); - + static WebClient create(String baseUrl) { + return new DefaultWebClientBuilder(baseUrl).build(); } /** - * Create {@code WebClient} that uses the given {@link ClientHttpConnector} and - * {@link ExchangeStrategies}. - * @param connector the underlying connector to use - * @param strategies the strategies to use + * Obtain a {@code WebClient} builder with a base URI to be used as the + * base for expanding URI templates during exchanges. The given String + * is used to create an instance of {@link DefaultUriBuilderFactory} whose + * {@link DefaultUriBuilderFactory#DefaultUriBuilderFactory(String) + * constructor} provides more details on how the base URI is applied. + * @param baseUrl the base URI for all requests */ - static WebClient create(ClientHttpConnector connector, ExchangeStrategies strategies) { - return create(ExchangeFunctions.create(connector, strategies)); + static WebClient.Builder builder(String baseUrl) { + return new DefaultWebClientBuilder(baseUrl); } /** - * Create {@code WebClient} that wraps the given {@link ExchangeFunction}. - * @param exchangeFunction the underlying exchange function to use + * Obtain a {@code WebClient} builder with the {@link UriBuilderFactory} + * to use for expanding URI templates during exchanges. + * @param uriBuilderFactory the factory to use */ - static WebClient create(ExchangeFunction exchangeFunction) { - return builder(exchangeFunction).build(); - } - - /** - * Create {@code WebClient} with a builder for additional - * configuration options. - * @param exchangeFunction the underlying exchange function to use - */ - static WebClient.Builder builder(ExchangeFunction exchangeFunction) { - return new DefaultWebClientBuilder(exchangeFunction); + static WebClient.Builder builder(UriBuilderFactory uriBuilderFactory) { + return new DefaultWebClientBuilder(uriBuilderFactory); } @@ -159,11 +156,22 @@ public interface WebClient { interface Builder { /** - * Configure a {@code UriBuilderFactory} for use with this client for - * example to define a common "base" URI. - * @param uriBuilderFactory the URI builder factory + * Configure the {@link ClientHttpConnector} to use. + *

By default an instance of + * {@link org.springframework.http.client.reactive.ReactorClientHttpConnector + * ReactorClientHttpConnector} is created if this is not set. However a + * shared instance may be passed instead, e.g. for use with multiple + * {@code WebClient}'s targeting different base URIs. + * @param connector the connector to use */ - Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory); + Builder clientConnector(ClientHttpConnector connector); + + /** + * Configure the {@link ExchangeStrategies} to use. + *

By default {@link ExchangeStrategies#withDefaults()} is used. + * @param strategies the strategies to use + */ + Builder exchangeStrategies(ExchangeStrategies strategies); /** * Builder the {@link WebClient} instance. @@ -187,14 +195,14 @@ public interface WebClient { * Specify the URI for the request using a URI template and URI variables. * If a {@link UriBuilderFactory} was configured for the client (e.g. * with a base URI) it will be used to expand the URI template. - * @see Builder#uriBuilderFactory(UriBuilderFactory) + * @see #builder(String) */ HeaderSpec uri(String uri, Object... uriVariables); /** * Build the URI for the request using the {@link UriBuilderFactory} * configured for this client. - * @see Builder#uriBuilderFactory(UriBuilderFactory) + * @see #builder(String) */ HeaderSpec uri(Function uriFunction); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java index aca5c1614b..3d0fa231cd 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java @@ -58,10 +58,7 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest Assume.assumeFalse(this.server instanceof RxNettyHttpServer); super.setup(); - - ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); - UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port); - this.webClient = WebClient.builder(exchange).uriBuilderFactory(factory).build(); + this.webClient = WebClient.create("http://localhost:" + this.port); } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java index 209cf4c93c..254a0bd762 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java @@ -33,10 +33,7 @@ import reactor.test.StepVerifier; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.Pojo; -import org.springframework.web.util.DefaultUriBuilderFactory; -import org.springframework.web.util.UriBuilderFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -58,13 +55,8 @@ public class WebClientIntegrationTests { @Before public void setup() { this.server = new MockWebServer(); - - ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector()); - UriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(this.server.url("/").toString()); - - this.webClient = WebClient.builder(exchangeFunction) - .uriBuilderFactory(uriBuilderFactory) - .build(); + String baseUrl = this.server.url("/").toString(); + this.webClient = WebClient.create(baseUrl); } @After diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java index a4d923bbd7..c25cb3692c 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java @@ -24,13 +24,8 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.ServerSentEvent; -import org.springframework.web.reactive.function.client.ExchangeFunction; -import org.springframework.web.reactive.function.client.ExchangeFunctions; import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.util.DefaultUriBuilderFactory; -import org.springframework.web.util.UriBuilderFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -51,10 +46,7 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn @Before public void setup() throws Exception { super.setup(); - ExchangeFunction exchangeFunction = - ExchangeFunctions.create(new ReactorClientHttpConnector()); - UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port); - this.webClient = WebClient.builder(exchangeFunction).uriBuilderFactory(factory).build(); + this.webClient = WebClient.create("http://localhost:" + this.port); } @Override diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java index 252ac12491..c6ad286137 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java @@ -27,7 +27,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.ResolvableType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.codec.ServerSentEvent; import org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests; import org.springframework.http.server.reactive.HttpHandler; @@ -35,12 +34,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.config.EnableWebReactive; -import org.springframework.web.reactive.function.client.ExchangeFunction; -import org.springframework.web.reactive.function.client.ExchangeFunctions; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; -import org.springframework.web.util.DefaultUriBuilderFactory; -import org.springframework.web.util.UriBuilderFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -63,9 +58,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { @Before public void setup() throws Exception { super.setup(); - ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector()); - UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port + "/sse"); - this.webClient = WebClient.builder(exchangeFunction).uriBuilderFactory(factory).build(); + this.webClient = WebClient.create("http://localhost:" + this.port + "/sse"); }