Starter for building web, including RESTful, applications using Spring MVC with embedded Tomcat server.
—
Spring Boot provides auto-configured HTTP client support with RestTemplate and RestClient for making HTTP requests to external services.
Auto-configured RestTemplate builder for creating HTTP clients.
/**
* RestTemplate builder provided by Spring Boot
*/
@Autowired
private RestTemplateBuilder restTemplateBuilder;
/**
* Create RestTemplate instance
*/
public RestTemplate restTemplate() {
return restTemplateBuilder
.rootUri("https://api.example.com")
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(30))
.build();
}
/**
* RestTemplate with custom configuration
*/
@Bean
public RestTemplate customRestTemplate() {
return new RestTemplateBuilder()
.messageConverters(new MappingJackson2HttpMessageConverter())
.errorHandler(new CustomResponseErrorHandler())
.basicAuthentication("username", "password")
.build();
}Usage Examples:
@Service
public class ExternalApiService {
private final RestTemplate restTemplate;
public ExternalApiService(RestTemplateBuilder builder) {
this.restTemplate = builder
.rootUri("https://jsonplaceholder.typicode.com")
.setConnectTimeout(Duration.ofSeconds(5))
.build();
}
public User getUser(Long id) {
return restTemplate.getForObject("/users/{id}", User.class, id);
}
public User createUser(User user) {
return restTemplate.postForObject("/users", user, User.class);
}
public void updateUser(Long id, User user) {
restTemplate.put("/users/{id}", user, id);
}
public void deleteUser(Long id) {
restTemplate.delete("/users/{id}", id);
}
}Comprehensive HTTP method support for RESTful operations.
/**
* GET requests
*/
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables);
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
/**
* POST requests
*/
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables);
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables);
public URI postForLocation(String url, Object request, Object... uriVariables);
/**
* PUT requests
*/
public void put(String url, Object request, Object... uriVariables);
/**
* DELETE requests
*/
public void delete(String url, Object... uriVariables);
/**
* Generic exchange method
*/
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables);
public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType);Usage Examples:
@Service
public class UserApiClient {
private final RestTemplate restTemplate;
public UserApiClient(RestTemplateBuilder builder) {
this.restTemplate = builder.build();
}
public List<User> getAllUsers() {
ResponseEntity<User[]> response = restTemplate.getForEntity(
"https://api.example.com/users", User[].class);
return Arrays.asList(response.getBody());
}
public User getUserWithHeaders(Long id) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token");
headers.set("Accept", "application/json");
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<User> response = restTemplate.exchange(
"https://api.example.com/users/{id}",
HttpMethod.GET,
entity,
User.class,
id
);
return response.getBody();
}
public User createUserWithCustomHeaders(User user) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-API-Key", "my-api-key");
HttpEntity<User> requestEntity = new HttpEntity<>(user, headers);
return restTemplate.postForObject(
"https://api.example.com/users",
requestEntity,
User.class
);
}
}Modern HTTP client with fluent API and improved ergonomics.
/**
* RestClient builder provided by Spring Boot
*/
@Autowired
private RestClient.Builder restClientBuilder;
/**
* Create RestClient instance
*/
public RestClient restClient() {
return restClientBuilder
.baseUrl("https://api.example.com")
.defaultHeader("User-Agent", "MyApp/1.0")
.build();
}
/**
* RestClient fluent API
*/
public interface RestClient {
RequestHeadersUriSpec<?> get();
RequestBodyUriSpec post();
RequestBodyUriSpec put();
RequestBodyUriSpec patch();
RequestHeadersUriSpec<?> delete();
RequestBodyUriSpec method(HttpMethod method);
}Usage Examples:
@Service
public class ModernApiClient {
private final RestClient restClient;
public ModernApiClient(RestClient.Builder builder) {
this.restClient = builder
.baseUrl("https://jsonplaceholder.typicode.com")
.defaultHeader("Accept", "application/json")
.build();
}
public User getUser(Long id) {
return restClient.get()
.uri("/users/{id}", id)
.retrieve()
.body(User.class);
}
public List<User> getUsersWithPagination(int page, int size) {
return restClient.get()
.uri(uriBuilder -> uriBuilder
.path("/users")
.queryParam("page", page)
.queryParam("size", size)
.build())
.retrieve()
.body(new ParameterizedTypeReference<List<User>>() {});
}
public User createUser(User user) {
return restClient.post()
.uri("/users")
.contentType(MediaType.APPLICATION_JSON)
.body(user)
.retrieve()
.body(User.class);
}
public ResponseEntity<User> createUserWithResponseEntity(User user) {
return restClient.post()
.uri("/users")
.body(user)
.retrieve()
.toEntity(User.class);
}
public void handleErrorResponse(Long id) {
try {
User user = restClient.get()
.uri("/users/{id}", id)
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
throw new UserNotFoundException("User not found: " + id);
})
.body(User.class);
} catch (UserNotFoundException e) {
// Handle specific error
}
}
}Auto-configured message converters for request/response serialization.
/**
* Common HTTP message converters automatically configured
*/
// Jackson JSON converter
MappingJackson2HttpMessageConverter jsonConverter;
// String converter for text/plain
StringHttpMessageConverter stringConverter;
// Form data converter
FormHttpMessageConverter formConverter;
// Resource converter for file downloads
ResourceHttpMessageConverter resourceConverter;
/**
* Custom message converter configuration
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
// Add custom JSON converter
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
jsonConverter.setObjectMapper(customObjectMapper());
converters.add(0, jsonConverter);
return restTemplate;
}
private ObjectMapper customObjectMapper() {
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new JavaTimeModule());
}
}Custom error handling for HTTP client responses.
/**
* Custom response error handler
*/
public class CustomResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return response.getStatusCode().is4xxClientError() ||
response.getStatusCode().is5xxServerError();
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatusCode statusCode = response.getStatusCode();
if (statusCode.is4xxClientError()) {
if (statusCode == HttpStatus.NOT_FOUND) {
throw new ResourceNotFoundException("Resource not found");
} else if (statusCode == HttpStatus.BAD_REQUEST) {
throw new BadRequestException("Invalid request");
}
} else if (statusCode.is5xxServerError()) {
throw new ServiceUnavailableException("Service temporarily unavailable");
}
}
}
/**
* Apply custom error handler
*/
@Bean
public RestTemplate restTemplateWithErrorHandler() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomResponseErrorHandler());
return restTemplate;
}Configure SSL certificates and authentication for HTTPS endpoints.
/**
* SSL configuration for RestTemplate
*/
@Bean
public RestTemplate secureRestTemplate() throws Exception {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
return new RestTemplate(requestFactory);
}
/**
* Basic authentication configuration
*/
@Bean
public RestTemplate authenticatedRestTemplate() {
return new RestTemplateBuilder()
.basicAuthentication("username", "password")
.build();
}
/**
* OAuth2 client configuration (requires spring-security-oauth2-client)
*/
@Bean
public RestTemplate oauth2RestTemplate(OAuth2AuthorizedClientManager authorizedClientManager) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new OAuth2ClientHttpRequestInterceptor(authorizedClientManager));
return restTemplate;
}// RestTemplate for HTTP client operations
public class RestTemplate {
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables);
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables);
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables);
public void put(String url, Object request, Object... uriVariables);
public void delete(String url, Object... uriVariables);
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables);
}
// RestTemplate builder for configuration
public class RestTemplateBuilder {
public RestTemplateBuilder rootUri(String rootUri);
public RestTemplateBuilder messageConverters(HttpMessageConverter<?>... messageConverters);
public RestTemplateBuilder errorHandler(ResponseErrorHandler errorHandler);
public RestTemplateBuilder basicAuthentication(String username, String password);
public RestTemplateBuilder setConnectTimeout(Duration connectTimeout);
public RestTemplateBuilder setReadTimeout(Duration readTimeout);
public RestTemplate build();
}
// Modern RestClient (Spring 6.1+)
public interface RestClient {
RequestHeadersUriSpec<?> get();
RequestBodyUriSpec post();
RequestBodyUriSpec put();
RequestBodyUriSpec patch();
RequestHeadersUriSpec<?> delete();
interface Builder {
Builder baseUrl(String baseUrl);
Builder defaultHeader(String header, String... values);
Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer);
RestClient build();
}
}
// HTTP entity for request/response wrapping
public class HttpEntity<T> {
public HttpEntity();
public HttpEntity(T body);
public HttpEntity(HttpHeaders headers);
public HttpEntity(T body, HttpHeaders headers);
public HttpHeaders getHeaders();
public T getBody();
}
// Response entity with status and headers
public class ResponseEntity<T> extends HttpEntity<T> {
public HttpStatusCode getStatusCode();
public int getStatusCodeValue();
public static <T> ResponseEntity<T> ok(T body);
public static <T> ResponseEntity<T> status(HttpStatusCode status);
}
// HTTP headers utility
public class HttpHeaders {
public void add(String headerName, String headerValue);
public void set(String headerName, String headerValue);
public void setContentType(MediaType mediaType);
public void setAccept(List<MediaType> acceptableMediaTypes);
public void setBearerAuth(String token);
public void setBasicAuth(String username, String password);
}
// Parameterized type reference for generic types
public abstract class ParameterizedTypeReference<T> {
protected ParameterizedTypeReference() {}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-web