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依赖中:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

创建与配置实例

  • 我们可以在方法中直接new一个RestTemplate使用,使用完等待被JVM垃圾回收掉
  • 也可以通过简单的bean注入,注册到IOC容器中,然后通过@Autowired注解注入使用
java 复制代码
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(); // 使用默认配置
    }
}

@Service
public class MyService {

    @Autowired
    private RestTemplate restTemplate; // 注入RestTemplate

    public String someMethod() {
        return restTemplate.getForObject("https://api.example.com/data", String.class);
    }
}
  • SpringBoot官方更推荐通过RestTemplateBuilder工具类将配置好的RestTemplate实例注册到IOC容器中,当然最后也是通过@Autowired注解注入使用
java 复制代码
@Configuration
public class RestTemplateConfig {

    @Bean
    public 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方法的主要主要参数如下:

java 复制代码
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请求

java 复制代码
// 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请求

java 复制代码
// 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。
  • 下面是两种请求方式的示例代码
java 复制代码
// 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();
java 复制代码
// 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(); // 获取响应头