diff --git a/spring-5/pom.xml b/spring-5/pom.xml
index 4b373923ef..c2c565aef6 100644
--- a/spring-5/pom.xml
+++ b/spring-5/pom.xml
@@ -39,6 +39,11 @@
org.springframework.boot
spring-boot-starter-webflux
+
+ org.projectreactor
+ reactor-spring
+ 1.0.1.RELEASE
+
diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java b/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java
new file mode 100644
index 0000000000..3a2e1b1a75
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/web/reactive/client/WebClientController.java
@@ -0,0 +1,86 @@
+package com.baeldung.web.reactive.client;
+
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import org.springframework.http.*;
+import org.springframework.http.client.reactive.ClientHttpRequest;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.BodyInserter;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.time.ZonedDateTime;
+import java.util.Collections;
+
+@RestController
+public class WebClientController {
+
+ @ResponseStatus(HttpStatus.OK)
+ @GetMapping("/resource")
+ public void getResource() {
+ }
+
+ public void demonstrateWebClient() {
+ // request
+ WebClient.UriSpec request1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST);
+ WebClient.UriSpec request2 = createWebClientWithServerURLAndDefaultValues().post();
+
+ // request body specifications
+ WebClient.RequestBodySpec uri1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST).uri("/resource");
+ WebClient.RequestBodySpec uri2 = createWebClientWithServerURLAndDefaultValues().post().uri(URI.create("/resource"));
+
+ // request header specification
+ WebClient.RequestHeadersSpec> requestSpec1 = uri1.body(BodyInserters.fromPublisher(Mono.just("data"), String.class));
+ WebClient.RequestHeadersSpec> requestSpec2 = uri2.body(BodyInserters.fromObject("data"));
+
+ // inserters
+ BodyInserter, ReactiveHttpOutputMessage> inserter1 = BodyInserters
+ .fromPublisher(Subscriber::onComplete, String.class);
+
+
+ LinkedMultiValueMap map = new LinkedMultiValueMap<>();
+ map.add("key1", "value1");
+ map.add("key2", "value2");
+
+ BodyInserter, ClientHttpRequest> inserter2 = BodyInserters.fromMultipartData(map);
+ BodyInserter inserter3 = BodyInserters.fromObject("body");
+
+ // responses
+ WebClient.ResponseSpec response1 = uri1
+ .body(inserter3)
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
+ .acceptCharset(Charset.forName("UTF-8"))
+ .ifNoneMatch("*")
+ .ifModifiedSince(ZonedDateTime.now())
+ .retrieve();
+ WebClient.ResponseSpec response2 = requestSpec2.retrieve();
+
+ }
+
+ private WebClient createWebClient() {
+ return WebClient.create();
+ }
+
+ private WebClient createWebClientWithServerURL() {
+ return WebClient.create("http://localhost:8081");
+ }
+
+ private WebClient createWebClientWithServerURLAndDefaultValues() {
+ return WebClient
+ .builder()
+ .baseUrl("http://localhost:8081")
+ .defaultCookie("cookieKey", "cookieValue")
+ .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+ .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
+ .build();
+ }
+
+}
diff --git a/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java b/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java
new file mode 100644
index 0000000000..4127f22c01
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/web/client/WebTestClientTest.java
@@ -0,0 +1,58 @@
+package com.baeldung.web.client;
+
+import com.baeldung.Spring5Application;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import org.springframework.web.server.WebHandler;
+import reactor.core.publisher.Mono;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Spring5Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class WebTestClientTest {
+
+ @LocalServerPort
+ private int port;
+
+ private final RouterFunction ROUTER_FUNCTION = RouterFunctions.route(
+ RequestPredicates.GET("/resource"),
+ request -> ServerResponse.ok().build()
+ );
+ private final WebHandler WEB_HANDLER = exchange -> Mono.empty();
+
+ @Test
+ public void testWebTestClientWithServerWebHandler() {
+ WebTestClient.bindToWebHandler(WEB_HANDLER).build();
+ }
+
+ @Test
+ public void testWebTestClientWithRouterFunction() {
+ WebTestClient
+ .bindToRouterFunction(ROUTER_FUNCTION)
+ .build().get().uri("/resource")
+ .exchange()
+ .expectStatus().isOk()
+ .expectBody().isEmpty();
+ }
+
+ @Test
+ public void testWebTestClientWithServerURL() {
+ WebTestClient
+ .bindToServer()
+ .baseUrl("http://localhost:" + port)
+ .build()
+ .get()
+ .uri("/resource")
+ .exchange()
+ .expectStatus().is4xxClientError()
+ .expectBody();
+ }
+
+}