spring mvc 中 RestTemplate 全面详解及示例


RestTemplate 全面详解及示例


1. RestTemplate 简介
  • 定义:Spring 提供的同步 HTTP 客户端,支持多种 HTTP 方法(GET/POST/PUT/DELETE 等),用于调用 RESTful API。

  • 核心特性

    • 支持请求头、请求体、URI 参数的灵活配置。
    • 可直接返回 ResponseEntity 获取状态码和响应头。
    • 支持对象序列化(如 JSON)和反序列化。
  • 依赖 (Spring Boot 项目):

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

2. 示例代码详解

示例 1:GET 请求(带请求头,获取状态码和响应头)
java 复制代码
// 1. 创建 RestTemplate 实例
RestTemplate restTemplate = new RestTemplate();

// 2. 构建请求 URI(包含路径参数)
String uri = "http://api.example.com/users/{id}";
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("id", "123");

// 3. 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token_123");
headers.setContentType(MediaType.APPLICATION_JSON);

// 4. 发送 GET 请求并获取 ResponseEntity
ResponseEntity<User> response = restTemplate.exchange(
    uri,
    HttpMethod.GET,
    new HttpEntity<>(headers), // 请求体为空,仅传递头
    User.class, // 响应体反序列化类型
    uriVariables
);

// 5. 处理响应
int statusCode = response.getStatusCodeValue(); // 获取状态码
HttpHeaders responseHeaders = response.getHeaders(); // 获取响应头
User user = response.getBody(); // 获取响应体对象

示例 2:POST 请求(传递 JSON 请求体)
java 复制代码
// 1. 创建请求体对象(使用 Jackson 自动序列化)
User newUser = new User("John", 25);

// 2. 构建请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

// 3. 创建 HttpEntity(包含头和请求体)
HttpEntity<User> request = new HttpEntity<>(newUser, headers);

// 4. 发送 POST 请求
ResponseEntity<String> response = restTemplate.postForEntity(
    "http://api.example.com/users",
    request,
    String.class // 返回的响应类型(如成功返回 "Created")
);

// 5. 处理响应
String locationHeader = response.getHeaders().getFirst("Location"); // 获取 Location 头

示例 3:PUT/PATCH 请求(更新资源)
java 复制代码
// 1. 更新对象
User updatedUser = new User("John Doe", 26);

// 2. 构建请求头和请求体
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<User> request = new HttpEntity<>(updatedUser, headers);

// 3. 发送 PUT 请求
ResponseEntity<Void> response = restTemplate.exchange(
    "http://api.example.com/users/123",
    HttpMethod.PUT,
    request,
    Void.class // 无响应体时使用 Void
);

// 4. 检查状态码
if (response.getStatusCode() == HttpStatus.OK) {
    System.out.println("Update successful");
}

示例 4:DELETE 请求
java 复制代码
// 发送 DELETE 请求
ResponseEntity<Void> response = restTemplate.exchange(
    "http://api.example.com/users/123",
    HttpMethod.DELETE,
    null, // 无请求体
    Void.class
);

if (response.getStatusCode() == HttpStatus.NO_CONTENT) {
    System.out.println("Resource deleted");
}

示例 5:自定义响应类型(如 Map)
java 复制代码
// 将响应体反序列化为 Map
ResponseEntity<Map<String, Object>> response = restTemplate.getForEntity(
    "http://api.example.com/data",
    new ParameterizedTypeReference<Map<String, Object>>() {}
);

Map<String, Object> data = response.getBody();

示例 6:使用 ResponseExtractor 定制响应
java 复制代码
// 自定义提取器:提取响应体中的某个字段
ResponseExtractor<String> extractor = response -> {
    if (response.getStatusCode() == HttpStatus.OK) {
        return response.getHeaders().getFirst("X-Custom-Header"); // 提取自定义头
    }
    return null;
};

// 使用 exchange 方法
String customHeader = restTemplate.exchange(
    "http://api.example.com/headers",
    HttpMethod.GET,
    null,
    extractor // 传递自定义提取器
);

示例 7:批量操作(查询多个资源)
java 复制代码
// 使用 UriComponentsBuilder 构建带查询参数的 URI
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://api.example.com/users")
    .queryParam("page", 1)
    .queryParam("size", 10);

// 发送 GET 请求并获取列表
ResponseEntity<User[]> response = restTemplate.getForEntity(
    builder.toUriString(),
    User[].class
);

User[] users = response.getBody();

3. 核心方法对比表格
方法 HTTP 方法 返回类型 关键代码片段 适用场景
getForObject GET 对象(如 User) restTemplate.getForObject(url, User.class); 简单 GET 请求,直接返回对象
getForEntity GET ResponseEntity<User> restTemplate.getForEntity(url, User.class); 需获取状态码或响应头
postForObject POST 对象(如 String) restTemplate.postForObject(url, request, String.class); POST 请求,直接返回结果
postForEntity POST ResponseEntity<Void> restTemplate.postForEntity(url, request, Void.class); 需检查状态码或 Location 头
exchange 任意方法 ResponseEntity<?> restTemplate.exchange(url, HttpMethod.POST, request, Class<T>); 自定义 HTTP 方法和响应类型
delete DELETE void restTemplate.delete(url); 简单删除操作

4. 关键配置与注意事项
  • 设置连接池(提升性能):

    java 复制代码
    RestTemplate restTemplate = new RestTemplate(
        new HttpClientErrorException.Factory(),
        new HttpComponentsClientHttpRequestFactory()
    );
  • 异常处理

    java 复制代码
    try {
        // 发送请求
    } catch (HttpClientErrorException e) {
        System.out.println("Client error: " + e.getStatusCode());
    } catch (HttpServerErrorException e) {
        System.out.println("Server error: " + e.getStatusCode());
    }
  • 自定义序列化器

    java 复制代码
    ObjectMapper objectMapper = new ObjectMapper();
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper);
    restTemplate.getMessageConverters().add(converter);

5. 总结对比表格
需求 实现方法 关键代码 注意事项
发送 JSON 请求体 使用 HttpEntity<User>HttpEntity<String> HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); 确保序列化配置正确
获取状态码和响应头 返回 ResponseEntity<T> response.getStatusCode(); response.getHeaders(); 处理 2xx/4xx/5xx 状态码
自定义响应类型 使用 ParameterizedTypeReference 或泛型 new ParameterizedTypeReference<List<User>>() {} 处理复杂泛型类型
响应提取器 实现 ResponseExtractor 接口或使用预定义提取器 restTemplate.exchange(url, HttpMethod.GET, null, extractor); 简化复杂响应处理逻辑

关键总结

  1. 核心类
    • RestTemplate:核心客户端,提供所有 HTTP 方法。
    • HttpEntity:封装请求头和请求体。
    • ResponseEntity:封装响应头、状态码和响应体。
  2. 最佳实践
    • 使用 exchange 方法统一处理复杂场景。
    • 通过 ResponseEntity 获取完整响应信息。
    • 自定义 HttpMessageConverter 处理特殊序列化需求。
  3. 替代方案
    Spring Boot 3.x 已弃用 RestTemplate,推荐使用 WebClient(响应式、非阻塞)。

通过以上示例和配置,开发者可以灵活实现 REST API 的全场景调用需求。

相关推荐
mfxcyh7 分钟前
基于xml、注解、JavaConfig实现spring的ioc
xml·java·spring
Flittly9 分钟前
【SpringAIAlibaba新手村系列】(13)Tool Calling 函数工具调用技术
java·spring boot·spring·ai
xdscode16 分钟前
Spring 依赖注入方式全景解析
java·后端·spring
爱吃烤鸡翅的酸菜鱼26 分钟前
Java 事件发布-订阅机制全解析:从原生实现到主流中间件
java·中间件·wpf·事件·发布订阅
无限码力35 分钟前
华为OD技术面真题 - JAVA开发- spring框架 - 7
java·开发语言·华为od·华为od面试真题·华为odjava八股文·华为odjava开发题目·华为odjava开发高频题目
Lyyaoo.41 分钟前
【JAVA基础面经】JAVA中的异常
java·开发语言
一定要AK1 小时前
JVM 全体系深度解析笔记
java·jvm·笔记
coder阿龙1 小时前
基于SpringAI+Qdrant+Ollama本地模型和向量数据库开发问答和RAG检索
java·数据库·spring boot·ai·数据库开发
Gofarlic_OMS1 小时前
HyperWorks用户仿真行为分析与许可证资源分点配置
java·大数据·运维·服务器·人工智能
徒 花1 小时前
Python知识学习08
java·python·算法