Documentation Index
Fetch the complete documentation index at: https://mintlify.com/spring-projects/spring-boot/llms.txt
Use this file to discover all available pages before exploring further.
Spring Boot provides three HTTP clients for calling remote REST services: RestClient (the modern imperative API), WebClient (for reactive applications), and RestTemplate (the classic API). Each is auto-configured with sensible defaults and supports customization through builders and customizer beans. This guide covers how to configure each client, apply timeouts and SSL, add interceptors, and test HTTP interactions.
Using RestClient
RestClient is the recommended HTTP client for non-reactive Spring Boot applications (Spring Boot 3.2+ / Spring Framework 6.1+). It provides a fluent, functional-style API for synchronous HTTP calls.
Inject the pre-configured builder
Spring Boot auto-configures a prototype RestClient.Builder bean that is pre-loaded with HttpMessageConverters and the auto-detected ClientHttpRequestFactory. Inject it into your component:import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@Service
public class MyService {
private final RestClient restClient;
public MyService(RestClient.Builder restClientBuilder) {
this.restClient = restClientBuilder.baseUrl("https://example.org").build();
}
public Details someRestCall(String name) {
return this.restClient.get()
.uri("/{name}/details", name)
.retrieve()
.body(Details.class);
}
}
Or create a client directly
If you do not need Spring Boot’s auto-configuration (converters, factory), use RestClient.create() directly:RestClient client = RestClient.create("https://example.org");
No auto-configuration or RestClientCustomizer beans are applied in this case.
Application-wide customization
To apply a customization to every RestClient.Builder in the application, declare a RestClientCustomizer bean:
import org.springframework.boot.restclient.RestClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRestClientConfiguration {
@Bean
public RestClientCustomizer myRestClientCustomizer() {
return restClientBuilder -> restClientBuilder
.defaultHeader("X-Custom-Header", "my-value");
}
}
RestClient.Builder instances are stateful. If you inject the same builder into multiple components, consider cloning it first: RestClient.Builder copy = builder.clone();
Using WebClient for reactive applications
Use WebClient when your application uses Spring WebFlux. Spring Boot auto-configures a prototype WebClient.Builder bean backed by Reactor Netty (default), Jetty RS client, Apache HttpClient, or JDK HttpClient depending on what is on the classpath.
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class MyService {
private final WebClient webClient;
public MyService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://example.org").build();
}
public Mono<Details> someRestCall(String name) {
return this.webClient.get()
.uri("/{name}/details", name)
.retrieve()
.bodyToMono(Details.class);
}
}
Customizing the Reactor Netty connector
To configure network-level settings such as connect and read timeouts on the Reactor Netty connector, declare a ClientHttpConnector bean:
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ReactorResourceFactory;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import reactor.netty.http.client.HttpClient;
import java.util.concurrent.TimeUnit;
@Configuration
public class MyReactorNettyClientConfiguration {
@Bean
ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
HttpClient httpClient = HttpClient.create(resourceFactory.getConnectionProvider())
.runOn(resourceFactory.getLoopResources())
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
.doOnConnected((connection) -> connection.addHandlerLast(
new ReadTimeoutHandler(60, TimeUnit.SECONDS)));
return new ReactorClientHttpConnector(httpClient);
}
}
Using ReactorResourceFactory for the connection provider and event loop resources enables efficient sharing of those resources between the server receiving requests and the client making requests.
Using RestTemplate (legacy)
RestTemplate is the classic Spring HTTP client. Spring Boot does not auto-configure a RestTemplate bean, but it does auto-configure a RestTemplateBuilder that you can use to create instances:
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public Details someRestCall(String name) {
return this.restTemplate.getForObject("/{name}/details", Details.class, name);
}
}
RestTemplateBuilder ensures HttpMessageConverters and the appropriate ClientHttpRequestFactory are applied automatically. It also has convenience methods for common needs: builder.basicAuthentication("user", "password").build().
Configuring connect and read timeouts
Apply timeouts globally to all HTTP clients (RestClient, WebClient, RestTemplate) using spring.http.clients properties:
spring:
http:
clients:
connect-timeout: 2s
read-timeout: 5s
For per-client timeout control using RestTemplate, use RestTemplateBuilderConfigurer to retain auto-configuration defaults while adding custom timeouts:
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.restclient.autoconfigure.RestTemplateBuilderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
@Configuration
public class MyRestTemplateBuilderConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
return configurer.configure(new RestTemplateBuilder())
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(2));
}
}
Adding custom interceptors and filters
RestTemplate interceptors
Add a RestTemplateCustomizer bean to apply interceptors application-wide. The following example configures a proxy for all hosts except 192.168.0.5:
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.springframework.boot.restclient.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class MyRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
// configure proxy, interceptors, or error handlers here
restTemplate.getInterceptors().add(new MyClientHttpRequestInterceptor());
}
@Bean
public MyRestTemplateCustomizer myRestTemplateCustomizer() {
return new MyRestTemplateCustomizer();
}
}
WebClient filters
For WebClient, add a filter via WebClientCustomizer:
import org.springframework.boot.webclient.WebClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class MyWebClientConfiguration {
@Bean
public WebClientCustomizer myWebClientCustomizer() {
return builder -> builder.filter((request, next) -> {
// modify or log request before forwarding
return next.exchange(request);
});
}
}
Configuring SSL for outbound calls
RestClient with SSL bundles
Inject RestClientSsl and apply a named SSL bundle to the builder:
import org.springframework.boot.restclient.autoconfigure.RestClientSsl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
@Configuration
public class MySslRestClientConfiguration {
@Bean
public RestClient myRestClient(RestClient.Builder builder, RestClientSsl ssl) {
return builder
.baseUrl("https://example.org")
.apply(ssl.fromBundle("my-bundle"))
.build();
}
}
WebClient with SSL bundles
import org.springframework.boot.webclient.autoconfigure.WebClientSsl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class MySslWebClientConfiguration {
@Bean
public WebClient myWebClient(WebClient.Builder builder, WebClientSsl ssl) {
return builder
.baseUrl("https://example.org")
.apply(ssl.fromBundle("my-bundle"))
.build();
}
}
SSL bundles are defined in application.yaml under spring.ssl.bundle.*. See the SSL Bundles reference for configuration details.
RestTemplate with SSL bundles
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class MySslRestTemplateConfiguration {
@Bean
public RestTemplate myRestTemplate(RestTemplateBuilder builder) {
return builder.sslBundle("my-bundle").build();
}
}
Choosing the HTTP client library
Spring Boot auto-detects which underlying HTTP client to use for RestClient and RestTemplate. The preference order is:
- Apache HttpClient
- Jetty HttpClient
- Reactor Netty HttpClient
- JDK
java.net.http.HttpClient
- Simple JDK
java.net.HttpURLConnection
To explicitly select a factory:
spring:
http:
clients:
imperative:
factory: jetty
For WebClient, the preference order is Reactor Netty → Jetty RS → Apache → JDK. To override:
spring:
http:
clients:
reactive:
connector: jetty
Testing with @RestClientTest
@RestClientTest slices the application context to include only the beans needed to test an HTTP client component. It configures a MockRestServiceServer automatically.
Annotate your test class
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.test.web.client.MockRestServiceServer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
@RestClientTest(MyService.class)
class MyServiceTest {
@Autowired
private MyService service;
@Autowired
private MockRestServiceServer server;
@Test
void greetingLoadsFromServer() {
this.server.expect(requestTo("/greeting"))
.andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
String greeting = this.service.loadGreeting();
assertThat(greeting).isEqualTo("hello");
}
}
@RestClientTest only loads the service class under test, auto-configured JSON support, and MockRestServiceServer. Use it for focused unit tests of individual HTTP clients — not for full integration tests.