RestTemplate工具类用法总结
前言
这篇博客主要记录下boot项目中我们比较常用的一个工具类,RestTemplate,一个非常实用的用来调用其他微服务接口的这样一个工具类,主要总结一下他的常见用法。
RestTemplate
- RestTemplate 是 Spring 框架提供的一个同步的、阻塞式的 HTTP 客户端工具,用于简化与其他服务的交互。它提供了丰富的 HTTP 方法支持,能自动处理 JSON/XML 等数据格式的序列化与反序列化。
- 什么是同步和阻塞式的,调用者发起操作后,必须等待结果返回才能继续执行后续任务,在等待结果返回的期间,自身线程被挂起,无法执行任何其他操作。
- 下面是RestTemplate的常见用法总结,我们主要关注POST、GET、通用请求这几种用法,其他用法用到的时候再查
方法类别 | 常用方法 | 主要功能描述 | 典型使用场景 |
---|---|---|---|
GET | getForObject() | 发送 GET 请求,返回响应体反序列化后的对象 | 获取资源数据,如查询用户信息、商品详情等 |
getForEntity() | 发送 GET 请求,返回包含响应体及状态码等详细信息的 ResponseEntity | 获需要检查 HTTP 状态码或响应头时 | |
POST | postForObject() | 发送 POST 请求,提交请求体并返回响应体反序列化后的对象 | 创建新资源,如提交订单、用户注册等 |
postForEntity() | 发送 POST 请求,返回包含响应详细信息的 ResponseEntity | 需要检查响应状态和头信息的创建操作 | |
PUT | put() | 发送 PUT 请求,通常不返回响应体 | 更新已有资源,如修改用户信息、更新库存等 |
DELETE | delete() | 发送 DELETE 请求,通常不返回响应体 | 删除资源,如删除用户、商品等 |
通用请求 | exchange() | 发送任何 HTTP 方法的请求,可灵活设置请求头和请求体 | 需要自定义请求方法、头信息或处理复杂场景时 |
表单提交 | postForEntity()与 MultiValueMap | 发送 application/x-www-form-urlencoded 格式的请求 | 提交表单登录、搜索等 |
文件上传 | postForEntity()与 MultiValueMap | 发送 multipart/form-data 格式的请求,上传文件 | 用户上传头像、文件等 |
文件下载 | getForEntity()或 execute() | 下载文件,返回 byte[]或通过回调流式处理 | 下载图片、文档等 |
添加依赖
在 Spring Boot 项目中,RestTemplate已包含在 spring-boot-starter-web依赖中:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
创建与配置实例
- 我们可以在方法中直接new一个RestTemplate使用,使用完等待被JVM垃圾回收掉
- 也可以通过简单的bean注入,注册到IOC容器中,然后通过@Autowired注解注入使用
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate(); // 使用默认配置}
}@Service
public class MyService {@Autowiredprivate RestTemplate restTemplate; // 注入RestTemplatepublic String someMethod() {return restTemplate.getForObject("https://api.example.com/data", String.class);}
}
- SpringBoot官方更推荐通过RestTemplateBuilder工具类将配置好的RestTemplate实例注册到IOC容器中,当然最后也是通过@Autowired注解注入使用
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {return builder.setConnectTimeout(Duration.ofSeconds(5)) // 设置连接超时为5秒.setReadTimeout(Duration.ofSeconds(10)) // 设置读取超时为10秒.defaultHeader("User-Agent", "My-App") // 设置默认请求头.build();}
}
- 这三种方式没有好坏之分,根据需要自己选择即可
通用请求(exchange)
exchange()是 RestTemplate中最灵活的方法,可以发送任何类型的 HTTP 请求(GET, POST, PUT, DELETE, PATCH等),精细控制请求细节和处理响应。
exchange方法的主要主要参数如下:
public <T> ResponseEntity<T> exchange(String url,HttpMethod method,HttpEntity<?> requestEntity,Class<T> responseType,Object... uriVariables)throws RestClientException
- url: 请求的目标 URL,可以包含占位符(如 {id})。
- method: HTTP 方法,使用 HttpMethod 枚举指定(例如 GET, POST, PUT, DELETE)。
- requestEntity: HttpEntity 对象,封装了请求体和请求头。如果不需要请求体(如 GET 请求),可以将请求体设为 null。
- responseType: 期望的响应体类型(例如 String.class, User.class),RestTemplate 会尝试将响应反序列化为此类型。
- uriVariables: 用于替换 URL 中的占位符的变量值。
发送get请求
// 1. 创建 RestTemplate
RestTemplate restTemplate = new RestTemplate();// 2. 设置请求头 (例如添加认证token)
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer your-access-token");
headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型// 3. 封装请求实体 (GET请求通常没有body, 所以是null)
HttpEntity<String> requestEntity = new HttpEntity<>(null, headers); // 4. 定义URL,包含占位符
String url = "https://api.example.com/users/{userId}";// 5. 发送GET请求
// 使用ResponseEntity接收完整响应,包括状态码、头和体
ResponseEntity<User> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, User.class, // 指定希望将响应体转换成的类型12345 // 这是URI变量,用于替换URL中的{userId}
);// 6. 处理响应
if (response.getStatusCode().is2xxSuccessful()) {User user = response.getBody(); // 获取响应体对象System.out.println("User: " + user);
} else {// 处理非2xx状态码System.err.println("Request failed with status: " + response.getStatusCode());
}
发送post请求
// 1. 创建 RestTemplate
RestTemplate restTemplate = new RestTemplate();// 2. 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); // 表明请求体是JSON// 3. 准备要发送的数据对象
User newUser = new User("John Doe", "john.doe@example.com");// 4. 封装请求实体 (将对象作为请求体)
HttpEntity<User> requestEntity = new HttpEntity<>(newUser, headers);// 5. 定义URL
String url = "https://api.example.com/users";// 6. 发送POST请求
ResponseEntity<User> response = restTemplate.exchange(url,HttpMethod.POST,requestEntity,User.class // 期望服务器返回创建好的User对象
);// 7. 处理响应
if (response.getStatusCode().is2xxSuccessful()) {User createdUser = response.getBody();System.out.println("Created User: " + createdUser);
} else {System.err.println("Failed to create user: " + response.getStatusCode());
}
POST/GET专用方法
- 我们除了可以使用exchange这个通用方法发送所有方式的请求,也可以使用每个请求方式对应的方法完成任务,这里只介绍get和post这两种方式
- 如果你只想要响应体内容,并且希望直接得到对象,选择 getForObject 或 postForObject。
- 如果你需要检查 HTTP 状态码、读取响应头信息,或者需要更全面地处理响应,选择 getForEntity 或 postForEntity。
- 下面是两种请求方式的示例代码
// 1. 创建 RestTemplate 实例
RestTemplate restTemplate = new RestTemplate();// 2. 准备请求数据
User newUser = new User("Jane", 28); // 要发送的 JSON 对象
String postUrl = "http://example.com/api/users";// 3. 使用 postForObject - 提交并获取响应对象
// 提交 JSON 对象
User returnedUser = restTemplate.postForObject(postUrl, newUser, User.class);// 4. 使用 postForEntity - 提交并获取完整响应
ResponseEntity<User> responseEntityPost = restTemplate.postForEntity(postUrl, newUser, User.class);
HttpStatus statusCodePost = responseEntityPost.getStatusCode();
User createdUser = responseEntityPost.getBody();
HttpHeaders headersPost = responseEntityPost.getHeaders();
// 1. 创建 RestTemplate 实例
RestTemplate restTemplate = new RestTemplate();// 2. 使用 getForObject - 获取字符串响应
String url = "http://example.com/api/data";
String resultString = restTemplate.getForObject(url, String.class);
System.out.println(resultString);// 3. 使用 getForObject - 获取 JSON 并转换为自定义对象
// 假设返回的 JSON 格式为 {"name": "John", "age": 30}
public class User {private String name;private int age;// 省略 getter 和 setter
}
User user = restTemplate.getForObject(url, User.class);
System.out.println(user.getName());// 4. 使用 getForEntity - 获取包含响应细节的 ResponseEntity
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
HttpStatus statusCode = responseEntity.getStatusCode(); // 获取状态码
String body = responseEntity.getBody(); // 获取响应体
HttpHeaders headers = responseEntity.getHeaders(); // 获取响应头