WebClient vs RestTemplate: A Detailed Guide
Intorduction
When dealing with HTTP requests in Spring, developers were traditionally using RestTemplate. However, since Spring 5, a new client called WebClient was introduced, offering a more modern approach to handling HTTP requests. In this article, we'll provide a comparative analysis of WebClient and RestTemplate, discussing when to use each, their respective pros and cons, along with detailed examples and unit tests.
RestTemplate
RestTemplate is a synchronous HTTP client and was a go-to choice for Spring developers when making HTTP requests to RESTful services, offering a convenient way to consume web services.
Pros:
1. Ease of Use: RestTemplate provides templates for all HTTP methods.
2. Synchronous Blocking Calls: Useful in scenarios where the request needs to complete before proceeding.
3. Wide Adoption: Extensively used in Spring projects, hence a lot of community support.
Cons:
1. Deprecated in Spring 5: RestTemplate is in maintenance mode, with no major updates planned.
2. Blocking Calls: Can lead to inefficient resource use in applications with high IO or network calls.
Example Usage:
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("https://example.com", String.class);
RestTemplate Unit Test:
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;
import static org.junit.jupiter.api.Assertions.*;
public class RestTemplateTest {
@Test
public void testRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://example.com", String.class);
assertNotNull(result);
}
}
WebClient
WebClient is a non-blocking, reactive web client introduced in Spring 5 as part of the Spring WebFlux module. WebClient operates on the publisher-subscriber model and supports both traditional Servlet-based environments and non-blocking ones.
Pros:
1. Non-Blocking Nature: WebClient makes efficient use of threads and can handle many concurrent connections, making it suitable for high-load applications.
2. Flexibility: WebClient works in both traditional Servlet-based environments and reactive ones.
3. Feature Rich: WebClient provides a fluent functional style API.
领英推荐
Cons:
1. Requires a Paradigm Shift: Developers must become familiar with reactive programming, which can be a steep learning curve.
Example Usage:
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("https://example.com")
.retrieve()
.bodyToMono(String.class);
WebClient Unit Test:
import org.junit.jupiter.api.Test;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import static org.junit.jupiter.api.Assertions.*;
public class WebClientTest {
@Test
public void testWebClient() {
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("https://example.com")
.retrieve()
.bodyToMono(String.class);
assertNotNull(response.block()); // block the Mono for testing
}
}
Additional WebClient Examples
Besides GET requests, WebClient can also handle POST, PUT and DELETE requests. Here are examples of these:
Making a POST Request
WebClient webClient = WebClient.create();
Mono<String> response = webClient.post()
.uri("https://example.com")
.bodyValue("Hello, World!")
.retrieve()
.bodyToMono(String.class);
Making a PUT Request
WebClient webClient = WebClient.create();
Mono<String> response = webClient.put()
.uri("https://example.com")
.bodyValue("Hello, World!")
.retrieve()
.bodyToMono(String.class);
Making a DELETE Request
WebClient webClient = WebClient.create();
Mono<Void> response = webClient.delete()
.uri("https://example.com")
.retrieve()
.bodyToMono(Void.class);
Asynchronous Examples
Async Example with RestTemplate
As of Spring 5, RestTemplate is deprecated and AsyncRestTemplate is also deprecated. However, if you are using an older version of Spring, you can use AsyncRestTemplate as follows:
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
ListenableFuture<ResponseEntity<String>> futureEntity = asyncRestTemplate.getForEntity("https://example.com", String.class);
// Do something else...
try {
ResponseEntity<String> entity = futureEntity.get();
System.out.println(entity.getBody());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
Async Example with WebClient
With WebClient, every request is asynchronous by default. Here's how you can handle responses asynchronously:
WebClient webClient = WebClient.create();
Mono<String> response = webClient.get()
.uri("https://example.com")
.retrieve()
.bodyToMono(String.class);
response.subscribe(
result -> System.out.println("Result: " + result),
error -> System.out.println("Error: " + error.getMessage()),
() -> System.out.println("Completed")
);
References: