Skip to main content

restclient-migration

Migrate RestTemplate to RestClient in Spring Boot 3.2+. Use when replacing deprecated RestTemplate with modern fluent API, updating HTTP client code, or configuring RestClient beans. Covers GET/POST/DELETE migrations, error handling, and ParameterizedTypeReference usage.

Quellinformationen

Repository
benchflow-ai/skillsbench
Letzte Quellaktivität
22. Januar 2026 um 22:47
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.837
Forks
371

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
restclient-migration
description
Migrate RestTemplate to RestClient in Spring Boot 3.2+. Use when replacing deprecated RestTemplate with modern fluent API, updating HTTP client code, or configuring RestClient beans. Covers GET/POST/DELETE migrations, error handling, and ParameterizedTypeReference usage.
# RestTemplate to RestClient Migration Skill ## Overview Spring Framework 6.1 (Spring Boot 3.2+) introduces `RestClient`, a modern, fluent API for synchronous HTTP requests that replaces the older `RestTemplate`. While `RestTemplate` still works, `RestClient` is the recommended approach for new code. ## Key Differences | Feature | RestTemplate | RestClient | |---------|-------------|------------| | API Style | Template methods | Fluent builder | | Configuration | Constructor injection | Builder pattern | | Error handling | ResponseErrorHandler | Status handlers | | Type safety | Limited | Better with generics | ## Migration Examples ### 1. Basic GET Request #### Before (RestTemplate) ```java @Service public class ExternalApiService { private final RestTemplate restTemplate; public ExternalApiService() { this.restTemplate = new RestTemplate(); } public Map<String, Object> getUser(String userId) { String url = "https://api.example.com/users/" + userId; ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class); return response.getBody(); } } ``` #### After (RestClient) ```java @Service public class ExternalApiService { private final RestClient restClient; public ExternalApiService() { this.restClient = RestClient.create(); } public Map<String, Object> getUser(String userId) { return restClient.get() .uri("https://api.example.com/users/{id}", userId) .retrieve() .body(new ParameterizedTypeReference<Map<String, Object>>() {}); } } ``` ### 2. POST Request with Body #### Before (RestTemplate) ```java public void sendNotification(String userId, String message) { String url = baseUrl + "/notifications"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); Map<String, String> payload = Map.of( "userId", userId, "message", message ); HttpEntity<Map<String, String>> request = new HttpEntity<>(payload, headers); restTemplate.postForEntity(url, request, Void.class); } ``` #### After (RestClient) ```java public void sendNotification(String userId, String message) { Map<String, String> payload = Map.of( "userId", userId, "message", message ); restClient.post() .uri(baseUrl + "/notifications") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .body(payload) .retrieve() .toBodilessEntity(); } ``` ### 3. Exchange with Custom Headers #### Before (RestTemplate) ```java public Map<String, Object> enrichUserProfile(String userId) { String url = baseUrl + "/users/" + userId + "/profile"; HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); HttpEntity<?> request = new HttpEntity<>(headers); ResponseEntity<Map> response = restTemplate.exchange( url, HttpMethod.GET, request, Map.class ); return response.getBody(); } ``` #### After (RestClient) ```java public Map<String, Object> enrichUserProfile(String userId) { return restClient.get() .uri(baseUrl + "/users/{id}/profile", userId) .accept(MediaType.APPLICATION_JSON) .retrieve() .body(new ParameterizedTypeReference<Map<String, Object>>() {}); } ``` ### 4. DELETE Request #### Before (RestTemplate) ```java public boolean requestDataDeletion(String userId) { try { String url = baseUrl + "/users/" + userId + "/data"; restTemplate.delete(url); return true; } catch (Exception e) { return false; } } ``` #### After (RestClient) ```java public boolean requestDataDeletion(String userId) { try { restClient.delete() .uri(baseUrl + "/users/{id}/data", userId) .retrieve() .toBodilessEntity(); return true; } catch (Exception e) { return false; } } ``` ## RestClient Configuration ### Creating a Configured RestClient ```java @Configuration public class RestClientConfig { @Value("${external.api.base-url}") private String baseUrl; @Bean public RestClient restClient() { return RestClient.builder() .baseUrl(baseUrl) .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) .build(); } } ``` ### Using the Configured RestClient ```java @Service public class ExternalApiService { private final RestClient restClient; public ExternalApiService(RestClient restClient) { this.restClient = restClient; } // Methods can now use relative URIs public Map<String, Object> getUser(String userId) { return restClient.get() .uri("/users/{id}", userId) .retrieve() .body(new ParameterizedTypeReference<Map<String, Object>>() {}); } } ``` ## Error Handling ### RestClient Status Handlers ```java public Map<String, Object> getUserWithErrorHandling(String userId) { return restClient.get() .uri("/users/{id}", userId) .retrieve() .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> { throw new UserNotFoundException("User not found: " + userId); }) .onStatus(HttpStatusCode::is5xxServerError, (request, response) -> { throw new ExternalServiceException("External service error"); }) .body(new ParameterizedTypeReference<Map<String, Object>>() {}); } ``` ## Type-Safe Responses ### Using ParameterizedTypeReference ```java // For generic types like Map or List Map<String, Object> map = restClient.get() .uri("/data") .retrieve() .body(new ParameterizedTypeReference<Map<String, Object>>() {}); List<User> users = restClient.get() .uri("/users") .retrieve() .body(new ParameterizedTypeReference<List<User>>() {}); ``` ### Direct Class Mapping ```java // For simple types User user = restClient.get() .uri("/users/{id}", userId) .retrieve() .body(User.class); String text = restClient.get() .uri("/text") .retrieve() .body(String.class); ``` ## Complete Service Migration Example ### Before ```java @Service public class ExternalApiService { private final RestTemplate restTemplate; @Value("${external.api.base-url}") private String baseUrl; public ExternalApiService() { this.restTemplate = new RestTemplate(); } public boolean verifyEmail(String email) { try { String url = baseUrl + "/verify/email?email=" + email; ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class); return Boolean.TRUE.equals(response.getBody().get("valid")); } catch (Exception e) { return false; } } } ``` ### After ```java @Service public class ExternalApiService { private final RestClient restClient; @Value("${external.api.base-url}") private String baseUrl; public ExternalApiService() { this.restClient = RestClient.create(); } public boolean verifyEmail(String email) { try { Map<String, Object> response = restClient.get() .uri(baseUrl + "/verify/email?email={email}", email) .retrieve() .body(new ParameterizedTypeReference<Map<String, Object>>() {}); return response != null && Boolean.TRUE.equals(response.get("valid")); } catch (Exception e) { return false; } } } ``` ## WebClient Alternative For reactive applications, use `WebClient` instead: ```java // WebClient for reactive/async operations WebClient webClient = WebClient.create(baseUrl); Mono<User> userMono = webClient.get() .uri("/users/{id}", userId) .retrieve() .bodyToMono(User.class); ``` `RestClient` is preferred for synchronous operations in non-reactive applications.
Auf GitHub ansehen