Mastering Spring Boot RestTemplate and WebClient: Configuration and Customization
Learn how Spring Boot 2.6.14 simplifies calling remote REST services using RestTemplate and WebClient, including automatic configuration with RestTemplateBuilder, customization options via RestTemplateCustomizer and WebClient.Builder, and detailed code examples for building, customizing, and selecting appropriate HTTP connectors.
Environment: Spring Boot 2.6.14
RestTemplate
When an application needs to call a remote REST service, Spring Boot provides RestTemplate (or the reactive WebClient ) for convenient access.
RestTemplate instances usually require customization before use, so Spring Boot does not expose a single auto‑configured RestTemplate bean. Instead, it auto‑configures a RestTemplateBuilder that can create RestTemplate instances with sensible HttpMessageConverters .
<code>@Service
public class RemoteService {
private final RestTemplate restTemplate;
public RemoteService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public Details storageService(Long storageId, Integer count) {
return this.restTemplate.getForObject(
"http://localhost:8080/storage/deduct/{storageId}/{count}",
Boolean.class, storageId, count);
}
}
</code>RestTemplateBuilder includes many useful methods for quick configuration. For example, to add BASIC authentication support you can use builder.basicAuthentication("admin", "123").build() .
Customizing RestTemplate
There are three main ways to customize RestTemplate, depending on the desired scope:
For the narrowest scope, inject the auto‑configured RestTemplateBuilder and call its methods; each call returns a new builder instance, so customization only affects that usage.
For application‑wide additional customization, define a RestTemplateCustomizer bean. All such beans are automatically registered with the auto‑configured RestTemplateBuilder and applied to any RestTemplate built from it.
For the most extreme case, define your own RestTemplateBuilder bean, replacing the auto‑configuration entirely.
Auto‑configuration example
<code>public class RestTemplateAutoConfiguration {
@Bean
@Lazy
@ConditionalOnMissingBean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer restTemplateBuilderConfigurer) {
RestTemplateBuilder builder = new RestTemplateBuilder();
return restTemplateBuilderConfigurer.configure(builder);
}
}
</code>Custom RestTemplateCustomizer
<code>public class CustomRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
</code>Defining a custom RestTemplateBuilder bean
<code>@Configuration(proxyBeanMethods = false)
public class CustomRestTemplateBuilderConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
return configurer.configure(new RestTemplateBuilder())
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2));
}
}
</code>Spring Boot also provides a default RestTemplateBuilderConfigurer that configures sensible HttpMessageConverters.
WebClient
If Spring WebFlux is on the classpath, you can use the reactive WebClient instead of RestTemplate. WebClient offers richer functionality and full reactive support.
Spring Boot auto‑configures a WebClient.Builder . It is recommended to inject this builder into components and use it to create WebClient instances, sharing HTTP resources and codec settings.
<code>@Service
public class WebClientService {
private final WebClient webClient;
public WebClientService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("http://localhost:8080").build();
}
public Mono<Details> storageService(Long storageId, Integer count) {
return this.webClient.get()
.uri("/storage/deduct/{storageId}/{count}", storageId, count)
.retrieve()
.bodyToMono(Boolean.class);
}
}
</code>WebClient runtime
Spring Boot automatically detects which ClientHttpConnector to use based on the libraries present on the classpath. Supported connectors include Reactor Netty, Jetty, and Apache HttpClient.
WebClient source snippet
<code>public interface WebClient {
static WebClient.Builder builder() {
return new DefaultWebClientBuilder();
}
}
final class DefaultWebClientBuilder implements WebClient.Builder {
private static final boolean reactorClientPresent;
private static final boolean jettyClientPresent;
private static final boolean httpComponentsClientPresent;
static {
ClassLoader loader = DefaultWebClientBuilder.class.getClassLoader();
reactorClientPresent = ClassUtils.isPresent("reactor.netty.http.client.HttpClient", loader);
jettyClientPresent = ClassUtils.isPresent("org.eclipse.jetty.client.HttpClient", loader);
httpComponentsClientPresent = ClassUtils.isPresent("org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient", loader) &&
ClassUtils.isPresent("org.apache.hc.core5.reactive.ReactiveDataConsumer", loader);
}
public WebClient build() {
ClientHttpConnector connectorToUse = (this.connector != null ? this.connector : initConnector());
// ...
return new DefaultWebClient(...);
}
private ClientHttpConnector initConnector() {
if (reactorClientPresent) {
return new ReactorClientHttpConnector();
} else if (jettyClientPresent) {
return new JettyClientHttpConnector();
} else if (httpComponentsClientPresent) {
return new HttpComponentsClientHttpConnector();
}
throw new IllegalStateException("No suitable default ClientHttpConnector found");
}
}
</code>The default spring-boot-starter-webflux starter pulls in io.projectreactor.netty:reactor-netty , which provides both server and client implementations. If Jetty is chosen as the reactive server, a Jetty client dependency should also be added to keep client and server implementations consistent.
Developers can override the default resources by providing custom ReactorResourceFactory or JettyResourceFactory beans, affecting both client and server.
To fully control the client configuration, define a custom ClientHttpConnector bean.
WebClient customization
Inject the auto‑configured WebClient.Builder and call its methods for narrow‑scope customizations; the builder is stateful, so changes affect all clients created from it. Use WebClient.Builder other = builder.clone(); to create independent clients.
For application‑wide customizations, declare a WebClientCustomizer bean that modifies the builder at injection points.
Alternatively, use the raw API WebClient.create() , which bypasses auto‑configuration and any customizers.
End of tutorial.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.