Skip to main content

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.
1

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);
    }

}
2

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:
  1. Apache HttpClient
  2. Jetty HttpClient
  3. Reactor Netty HttpClient
  4. JDK java.net.http.HttpClient
  5. 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.
1

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.

Build docs developers (and LLMs) love