RestTemplate 是 Spring Framework 提供的一个同步 HTTP 客户端工具,用于简化与 RESTful API 的交互。它封装了底层 HTTP 通信细节,提供了统一的 API 来发送各种 HTTP 请求(GET、POST、PUT、DELETE 等),并自动处理响应数据的序列化和反序列化。
如果使用 Maven 项目,需要在 pom.xml 中添加以下依赖:
xml
org.springframework.boot
spring-boot-starter-web
RestTemplate restTemplate = new RestTemplate();
// 示例:发送 GET 请求获取用户信息
String url = "https://api.example.com/users/{id}";
User user = restTemplate.getForObject(url, User.class, 123);
1. GET 请求
获取资源的基本方法有两种:
1.1 getForObject() - 直接返回响应体
String url = "https://api.example.com/users/{id}";
User user = restTemplate.getForObject(url, User.class, 123);
参数说明:
url:请求 URL,可以包含占位符(如 {id})
responseType:响应数据类型(通常是实体类)
uriVariables:占位符参数值(可变参数或 Map)
1.2 getForEntity() - 返回完整响应实体
ResponseEntity response = restTemplate.getForEntity(url, User.class, 123);
if (response.getStatusCode() == HttpStatus.OK) {
User user = response.getBody();
HttpHeaders headers = response.getHeaders();
}
2. POST 请求
用于创建资源,常用方法有三种:
2.1 postForObject() - 直接返回响应体
User newUser = new User("Alice", 25);
String url = "https://api.example.com/users";
User createdUser = restTemplate.postForObject(url, newUser, User.class);
参数说明:
url:请求 URL
request:请求体对象(会自动序列化为 JSON/XML)
responseType:响应数据类型
2.2 postForEntity() - 返回完整响应实体
ResponseEntity response = restTemplate.postForEntity(url, newUser, User.class);
2.3 postForLocation() - 返回新创建资源的 URL
URI location = restTemplate.postForLocation(url, newUser);
3. PUT 请求
用于更新资源(全量更新):
User updatedUser = new User(123, "Bob", 30);
String url = "https://api.example.com/users/{id}";
restTemplate.put(url, updatedUser, 123);
4. DELETE 请求
用于删除资源:
String url = "https://api.example.com/users/{id}";
restTemplate.delete(url, 123);
5. PATCH 请求(部分更新)
使用通用的 exchange() 方法:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 创建包含部分更新数据的 Map
Map updates = new HashMap<>();
updates.put("age", 31);
HttpEntity
1. 自定义请求头
使用 HttpEntity 包装请求体和请求头:
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token123");
headers.setContentType(MediaType.APPLICATION_JSON);
User requestBody = new User("Charlie", 35);
HttpEntity request = new HttpEntity<>(requestBody, headers);
String url = "https://api.example.com/secure/users";
ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, request, User.class);
2. 处理查询参数
使用 UriComponentsBuilder 构建带查询参数的 URL:
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://api.example.com/users")
.queryParam("page", 1)
.queryParam("size", 20)
.build();
String url = uriComponents.toUriString();
ResponseEntity response = restTemplate.getForEntity(url, User[].class);
3. 处理文件上传
使用 MultiValueMap 和 HttpEntity:
MultiValueMap body = new LinkedMultiValueMap<>();
body.add("file", new FileSystemResource(new File("path/to/file.jpg")));
body.add("name", "test-file");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity> requestEntity = new HttpEntity<>(body, headers);
String url = "https://api.example.com/upload";
ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
RestTemplate 在遇到 HTTP 错误(4xx/5xx)时会抛出异常:
HttpClientErrorException:4xx 客户端错误
HttpServerErrorException:5xx 服务器错误
ResourceAccessException:网络连接错误
使用 try-catch 块捕获并处理异常:
try {
User user = restTemplate.getForObject(url, User.class, 999);
} catch (HttpClientErrorException e) {
if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
System.out.println("用户不存在");
} else if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
System.out.println("未授权访问");
}
System.out.println("错误响应体: " + e.getResponseBodyAsString());
} catch (HttpServerErrorException e) {
System.out.println("服务器内部错误: " + e.getStatusCode());
} catch (ResourceAccessException e) {
System.out.println("网络连接失败: " + e.getMessage());
}
1. 注册消息转换器
RestTemplate restTemplate = new RestTemplate();
// 添加 JSON 消息转换器(默认使用 Jackson)
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
// 添加 XML 消息转换器
restTemplate.getMessageConverters().add(new Jaxb2RootElementHttpMessageConverter());
2. 配置超时
使用 SimpleClientHttpRequestFactory:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(5000); // 连接超时 5 秒
requestFactory.setReadTimeout(5000); // 读取超时 5 秒
RestTemplate restTemplate = new RestTemplate(requestFactory);
3. 配置错误处理器
自定义 ResponseErrorHandler:
restTemplate.setErrorHandler(new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
|| response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// 自定义错误处理逻辑
if (response.getStatusCode() == HttpStatus.NOT_FOUND) {
throw new MyResourceNotFoundException("资源未找到");
}
}
});
1. 完整的 GET 请求示例
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.github.com/users/{username}";
try {
ResponseEntity response = restTemplate.exchange(
url,
HttpMethod.GET,
null,
User.class,
"octocat"
);
if (response.getStatusCode() == HttpStatus.OK) {
User user = response.getBody();
System.out.println("用户名: " + user.getLogin());
System.out.println("ID: " + user.getId());
}
} catch (HttpClientErrorException e) {
System.out.println("GitHub API 错误: " + e.getStatusCode());
} catch (Exception e) {
System.out.println("发生异常: " + e.getMessage());
}
2. 完整的 POST 请求示例
// 创建请求对象
Map requestBody = new HashMap<>();
requestBody.put("title", "foo");
requestBody.put("body", "bar");
requestBody.put("userId", "1");
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 创建 HttpEntity 对象
HttpEntity
从 Spring 5 开始,推荐使用 WebClient 替代 RestTemplate,因为它支持响应式编程和非阻塞 I/O:
WebClient webClient = WebClient.create();
// 异步 GET 请求示例
Mono userMono = webClient.get()
.uri("https://api.example.com/users/{id}", 123)
.retrieve()
.bodyToMono(User.class);
// 订阅并处理结果
userMono.subscribe(user -> System.out.println("用户: " + user.getName()));
RestTemplate 是 Spring 框架中处理 REST API 的经典工具,适合同步、阻塞的 HTTP 通信场景。它提供了简洁的 API 和强大的消息转换机制,能大幅简化与外部服务的交互。不过,对于高并发场景,建议使用更现代的 WebClient。