RestTemplate #

一、RestTemplate概述 #

1.1 什么是RestTemplate #

RestTemplate是Spring提供的用于访问REST服务的客户端模板工具类,提供了多种便捷访问远程HTTP服务的方法。

text
┌─────────────────────────────────────────────────────────────┐
│                    RestTemplate架构                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                  RestTemplate                        │  │
│   │                                                      │  │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐            │  │
│   │   │  GET    │  │  POST   │  │  PUT    │            │  │
│   │   └─────────┘  └─────────┘  └─────────┘            │  │
│   │   ┌─────────┐  ┌─────────┐  ┌─────────┐            │  │
│   │   │ DELETE  │  │  HEAD   │  │ OPTIONS │            │  │
│   │   └─────────┘  └─────────┘  └─────────┘            │  │
│   │                                                      │  │
│   │   ┌─────────────────────────────────────────────┐  │  │
│   │   │           ClientHttpRequestFactory           │  │  │
│   │   │   SimpleClientHttpRequestFactory (默认)      │  │  │
│   │   │   HttpComponentsClientHttpRequestFactory     │  │  │
│   │   └─────────────────────────────────────────────┘  │  │
│   │                                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 RestTemplate方法分类 #

方法组 说明 方法数量
getForObject GET请求,返回对象 2
getForEntity GET请求,返回ResponseEntity 2
postForObject POST请求,返回对象 2
postForEntity POST请求,返回ResponseEntity 2
postForLocation POST请求,返回Location 1
put PUT请求 1
delete DELETE请求 1
exchange 通用请求方法 5
execute 最底层的请求方法 2

二、基本配置 #

2.1 创建RestTemplate #

java
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

2.2 配置超时时间 #

java
@Bean
public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setConnectTimeout(5000);
    factory.setReadTimeout(10000);
    return new RestTemplate(factory);
}

2.3 使用HttpClient #

xml
<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
</dependency>
java
@Bean
public RestTemplate restTemplate() {
    HttpComponentsClientHttpRequestFactory factory = 
        new HttpComponentsClientHttpRequestFactory();
    factory.setConnectTimeout(5000);
    factory.setReadTimeout(10000);
    return new RestTemplate(factory);
}

2.4 负载均衡配置 #

java
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

三、GET请求 #

3.1 getForObject #

java
@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    public User getUserById(Long id) {
        String url = "http://user-service/users/{id}";
        return restTemplate.getForObject(url, User.class, id);
    }

    public User getUserById2(Long id) {
        String url = "http://user-service/users/{id}";
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);
        return restTemplate.getForObject(url, User.class, params);
    }

    public List<User> getUsers(List<Long> ids) {
        String url = "http://user-service/users?ids={ids}";
        String idsStr = ids.stream()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
        return restTemplate.getForObject(url, List.class, idsStr);
    }
}

3.2 getForEntity #

java
public User getUserWithHeaders(Long id) {
    String url = "http://user-service/users/{id}";
    ResponseEntity<User> response = restTemplate.getForEntity(url, User.class, id);
    
    if (response.getStatusCode() == HttpStatus.OK) {
        HttpHeaders headers = response.getHeaders();
        String contentType = headers.getFirst(HttpHeaders.CONTENT_TYPE);
        System.out.println("Content-Type: " + contentType);
        return response.getBody();
    }
    
    return null;
}

public ResponseEntity<User> getUserResponse(Long id) {
    String url = "http://user-service/users/{id}";
    return restTemplate.getForEntity(url, User.class, id);
}

四、POST请求 #

4.1 postForObject #

java
public User createUser(User user) {
    String url = "http://user-service/users";
    return restTemplate.postForObject(url, user, User.class);
}

public User createUserWithHeaders(User user) {
    String url = "http://user-service/users";
    
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.set("Authorization", "Bearer token");
    
    HttpEntity<User> request = new HttpEntity<>(user, headers);
    return restTemplate.postForObject(url, request, User.class);
}

4.2 postForEntity #

java
public ResponseEntity<User> createUserResponse(User user) {
    String url = "http://user-service/users";
    return restTemplate.postForEntity(url, user, User.class);
}

4.3 postForLocation #

java
public URI createUserAndGetLocation(User user) {
    String url = "http://user-service/users";
    return restTemplate.postForLocation(url, user);
}

4.4 表单提交 #

java
public User login(String username, String password) {
    String url = "http://user-service/login";
    
    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("username", username);
    params.add("password", password);
    
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    
    HttpEntity<MultiValueMap<String, String>> request = 
        new HttpEntity<>(params, headers);
    
    return restTemplate.postForObject(url, request, User.class);
}

五、PUT请求 #

5.1 put方法 #

java
public void updateUser(Long id, User user) {
    String url = "http://user-service/users/{id}";
    restTemplate.put(url, user, id);
}

public void updateUser2(Long id, User user) {
    String url = "http://user-service/users/{id}";
    
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    
    HttpEntity<User> request = new HttpEntity<>(user, headers);
    restTemplate.put(url, request, id);
}

5.2 使用exchange #

java
public ResponseEntity<User> updateUserWithResponse(Long id, User user) {
    String url = "http://user-service/users/{id}";
    
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    
    HttpEntity<User> request = new HttpEntity<>(user, headers);
    
    return restTemplate.exchange(
        url, 
        HttpMethod.PUT, 
        request, 
        User.class, 
        id
    );
}

六、DELETE请求 #

6.1 delete方法 #

java
public void deleteUser(Long id) {
    String url = "http://user-service/users/{id}";
    restTemplate.delete(url, id);
}

6.2 使用exchange #

java
public ResponseEntity<Void> deleteUserWithResponse(Long id) {
    String url = "http://user-service/users/{id}";
    return restTemplate.exchange(
        url, 
        HttpMethod.DELETE, 
        null, 
        Void.class, 
        id
    );
}

七、通用方法exchange #

7.1 基本使用 #

java
public <T> ResponseEntity<T> exchange(
        String url,
        HttpMethod method,
        HttpEntity<?> requestEntity,
        Class<T> responseType,
        Object... uriVariables) {
    return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
}

7.2 带请求头 #

java
public User getUserWithAuth(Long id, String token) {
    String url = "http://user-service/users/{id}";
    
    HttpHeaders headers = new HttpHeaders();
    headers.setBearerAuth(token);
    headers.setContentType(MediaType.APPLICATION_JSON);
    
    HttpEntity<Void> request = new HttpEntity<>(headers);
    
    ResponseEntity<User> response = restTemplate.exchange(
        url,
        HttpMethod.GET,
        request,
        User.class,
        id
    );
    
    return response.getBody();
}

7.3 泛型返回 #

java
public <T> ResponseEntity<List<T>> exchangeList(
        String url,
        HttpMethod method,
        ParameterizedTypeReference<List<T>> responseType) {
    return restTemplate.exchange(url, method, null, responseType);
}

public List<User> getUsers() {
    String url = "http://user-service/users";
    
    ResponseEntity<List<User>> response = restTemplate.exchange(
        url,
        HttpMethod.GET,
        null,
        new ParameterizedTypeReference<List<User>>() {}
    );
    
    return response.getBody();
}

八、文件操作 #

8.1 文件上传 #

java
public String uploadFile(MultipartFile file) {
    String url = "http://file-service/upload";
    
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    
    MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    body.add("file", file.getResource());
    
    HttpEntity<MultiValueMap<String, Object>> request = 
        new HttpEntity<>(body, headers);
    
    return restTemplate.postForObject(url, request, String.class);
}

8.2 文件下载 #

java
public byte[] downloadFile(String fileId) {
    String url = "http://file-service/download/{id}";
    
    ResponseEntity<byte[]> response = restTemplate.getForEntity(
        url, 
        byte[].class, 
        fileId
    );
    
    return response.getBody();
}

public void downloadAndSave(String fileId, String localPath) throws IOException {
    String url = "http://file-service/download/{id}";
    
    ResponseEntity<Resource> response = restTemplate.getForEntity(
        url,
        Resource.class,
        fileId
    );
    
    if (response.getStatusCode() == HttpStatus.OK) {
        Files.copy(
            response.getBody().getInputStream(),
            Paths.get(localPath),
            StandardCopyOption.REPLACE_EXISTING
        );
    }
}

九、拦截器 #

9.1 自定义拦截器 #

java
public class LoggingInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger log = LoggerFactory.getLogger(LoggingInterceptor.class);

    @Override
    public ClientHttpResponse intercept(
            HttpRequest request,
            byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        
        logRequest(request, body);
        
        ClientHttpResponse response = execution.execute(request, body);
        
        logResponse(response);
        
        return response;
    }

    private void logRequest(HttpRequest request, byte[] body) {
        log.info("URI: {}", request.getURI());
        log.info("Method: {}", request.getMethod());
        log.info("Headers: {}", request.getHeaders());
        log.info("Body: {}", new String(body, StandardCharsets.UTF_8));
    }

    private void logResponse(ClientHttpResponse response) throws IOException {
        log.info("Status: {}", response.getStatusCode());
        log.info("Headers: {}", response.getHeaders());
    }
}

9.2 注册拦截器 #

java
@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setInterceptors(Collections.singletonList(new LoggingInterceptor()));
    return restTemplate;
}

9.3 认证拦截器 #

java
public class AuthInterceptor implements ClientHttpRequestInterceptor {

    private final String token;

    public AuthInterceptor(String token) {
        this.token = token;
    }

    @Override
    public ClientHttpResponse intercept(
            HttpRequest request,
            byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        
        request.getHeaders().setBearerAuth(token);
        
        return execution.execute(request, body);
    }
}

十、异常处理 #

10.1 默认异常处理 #

java
try {
    User user = restTemplate.getForObject(url, User.class, id);
} catch (HttpClientErrorException e) {
    if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
        System.out.println("User not found");
    } else if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
        System.out.println("Unauthorized");
    }
} catch (HttpServerErrorException e) {
    System.out.println("Server error: " + e.getStatusCode());
} catch (ResourceAccessException e) {
    System.out.println("Connection timeout or refused");
}

10.2 自定义错误处理器 #

java
public class CustomErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return response.getStatusCode().isError();
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        if (response.getStatusCode().is4xxClientError()) {
            throw new ClientException("Client error: " + response.getStatusCode());
        } else if (response.getStatusCode().is5xxServerError()) {
            throw new ServerException("Server error: " + response.getStatusCode());
        }
    }
}
java
@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new CustomErrorHandler());
    return restTemplate;
}

十一、最佳实践 #

11.1 封装工具类 #

java
@Component
public class RestTemplateUtil {

    @Autowired
    @LoadBalanced
    private RestTemplate restTemplate;

    public <T> T get(String url, Class<T> responseType, Object... uriVariables) {
        return restTemplate.getForObject(url, responseType, uriVariables);
    }

    public <T> T get(String url, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.getForObject(url, responseType, uriVariables);
    }

    public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) {
        return restTemplate.getForEntity(url, responseType, uriVariables);
    }

    public <T> T post(String url, Object request, Class<T> responseType) {
        return restTemplate.postForObject(url, request, responseType);
    }

    public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType) {
        return restTemplate.postForEntity(url, request, responseType);
    }

    public void put(String url, Object request, Object... uriVariables) {
        restTemplate.put(url, request, uriVariables);
    }

    public void delete(String url, Object... uriVariables) {
        restTemplate.delete(url, uriVariables);
    }

    public <T> ResponseEntity<T> exchange(
            String url,
            HttpMethod method,
            Object request,
            Class<T> responseType,
            Object... uriVariables) {
        HttpEntity<?> entity = request != null ? new HttpEntity<>(request) : null;
        return restTemplate.exchange(url, method, entity, responseType, uriVariables);
    }
}

11.2 连接池配置 #

java
@Bean
public RestTemplate restTemplate() {
    PoolingHttpClientConnectionManager connectionManager = 
        new PoolingHttpClientConnectionManager();
    connectionManager.setMaxTotal(200);
    connectionManager.setDefaultMaxPerRoute(50);
    
    CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(connectionManager)
        .build();
    
    HttpComponentsClientHttpRequestFactory factory = 
        new HttpComponentsClientHttpRequestFactory(httpClient);
    factory.setConnectTimeout(5000);
    factory.setReadTimeout(10000);
    
    return new RestTemplate(factory);
}

十二、总结 #

12.1 核心要点 #

要点 说明
getForObject GET请求返回对象
postForObject POST请求返回对象
exchange 通用请求方法
拦截器 请求/响应拦截处理
异常处理 自定义错误处理

12.2 下一步 #

现在你已经掌握了RestTemplate的使用,接下来让我们学习 OpenFeign,体验声明式服务调用的便捷!

最后更新:2026-03-28