关于Spring RestTemplate


一、概述


RestTemplate 是 Spring Framework 提供的一个同步 HTTP 客户端工具,用于简化与 RESTful API 的交互。它封装了底层 HTTP 通信细节,提供了统一的 API 来发送各种 HTTP 请求(GET、POST、PUT、DELETE 等),并自动处理响应数据的序列化和反序列化。

二、依赖配置


如果使用 Maven 项目,需要在 pom.xml 中添加以下依赖:

xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、基本使用流程

RestTemplate restTemplate = new RestTemplate();

// 示例:发送 GET 请求获取用户信息

String url = "https://api.example.com/users/{id}";
User user = restTemplate.getForObject(url, User.class, 123);

四、HTTP 请求方法详解


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<User> 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<User> 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<String, Object> updates = new HashMap<>();
updates.put("age", 31);HttpEntity<Map<String, Object>> request = new HttpEntity<>(updates, headers);
String url = "https://api.example.com/users/{id}";ResponseEntity<User> response = restTemplate.exchange(url, HttpMethod.PATCH, request, User.class, 123
);

五、处理复杂请求


1. 自定义请求头
使用 HttpEntity 包装请求体和请求头:

HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token123");
headers.setContentType(MediaType.APPLICATION_JSON);User requestBody = new User("Charlie", 35);
HttpEntity<User> request = new HttpEntity<>(requestBody, headers);String url = "https://api.example.com/secure/users";
ResponseEntity<User> 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<User[]> response = restTemplate.getForEntity(url, User[].class);

3. 处理文件上传
使用 MultiValueMap 和 HttpEntity:

MultiValueMap<String, Object> 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<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String url = "https://api.example.com/upload";ResponseEntity<String> 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() {@Overridepublic boolean hasError(ClientHttpResponse response) throws IOException {return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR|| response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;}@Overridepublic 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<User> 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<String, String> 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<Map<String, String>> request = new HttpEntity<>(requestBody, headers);// 发送 POST 请求
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts";ResponseEntity<Post> response = restTemplate.exchange(url,HttpMethod.POST,request,Post.class
);// 处理响应
if (response.getStatusCode() == HttpStatus.CREATED) {Post createdPost = response.getBody();System.out.println("创建的帖子 ID: " + createdPost.getId());
}

九、替代方案


从 Spring 5 开始,推荐使用 WebClient 替代 RestTemplate,因为它支持响应式编程和非阻塞 I/O:

WebClient webClient = WebClient.create();// 异步 GET 请求示例
Mono<User> 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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915311.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

异步解决一切问题 |消息队列 |减少嵌套 |hadoop |rabbitmq |postsql

设计准则“为什么要考虑这个问题”The forward logic is only about 10% of your code, everything else is 90%.主流逻辑 10%保障扩容和稳健的代码设计90%同步代码就是绑在一个绳上的蚂蚱异步就是实现了解耦这个异步或许有点类似于--一些分布式数据的处理 设计如何实现的呢?…

Spring AI 项目实战(十八):Spring Boot + AI + Vue3 + OSS + DashScope 实现高效语音识别系统(附完整源码)

系列文章 序号 文章名称 1 Spring AI 项目实战(一):Spring AI 核心模块入门 2 Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码) 3 Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码) 4

指针数组和数组指针的应用案例

1. 指针数组应用&#xff1a;查找最长字符串用指针数组存储若干字符串&#xff0c;编写函数找出其中最长的字符串&#xff08;若有多个&#xff0c;返回第一个&#xff09;。#include <stdio.h> #include <string.h>// 函数原型&#xff1a;找出最长字符串 const c…

MCU进入低功耗模式前的引脚处理原则和方法 --> 以最小化低功耗电流

在MCU进入低功耗模式(如Sleep, Stop, Standby, Deep Sleep等)前,精心处理每一个GPIO引脚的状态是最大限度降低功耗电流的关键一步。悬空或配置不当的引脚是导致“漏电”的常见原因。以下是处理引脚以达到最小低功耗电流的原则和方法: 📌 核心原则 避免浮空输入: 浮空(…

张 关于大语言模型(LLM)置信度研究的经典与前沿论文 :温度缩放;语义熵;自一致性;事实与反思;检索增强;黑盒引导;

关于大语言模型(LLM)置信度研究的经典与前沿论文 :温度缩放;语义熵;自一致性;事实与反思;检索增强;黑盒引导; 目录 关于大语言模型(LLM)置信度研究的经典与前沿论文 :温度缩放;语义熵;自一致性;事实与反思;检索增强;黑盒引导; 一、校准方法:让模型概率更贴近真实正确…

ICT测试原理之--什么是假短

ICT测试原理之–什么是假短 文章目录ICT测试原理之--什么是假短一、假短的由来防止假短二、无法检测的短路示例解决无法检测的短路调试短路文件调试意外断路调试意外短路三、调试假短报告短路和断路报告假短报告短路设备/引脚功能性短路测试功能性短路测试的语法一、假短的由来…

三种深度学习模型(LSTM、CNN-LSTM、贝叶斯优化的CNN-LSTM/BO-CNN-LSTM)对北半球光伏数据进行时间序列预测

代码功能 该代码实现了一个光伏发电量预测系统&#xff0c;采用三种深度学习模型&#xff08;LSTM、CNN-LSTM、贝叶斯优化的CNN-LSTM&#xff09;对北半球光伏数据进行时间序列预测&#xff0c;并通过多维度评估指标和可视化对比模型性能。 算法步骤 1. 数据预处理 数据导入&am…

Typecho+阿里云CDN完整配置:防止DDoS攻击与IP暴露

文章目录 Typecho使用阿里云CDN保护网站真实IP地址的完整指南 背景与问题分析 技术选型与方案设计 详细实施步骤 第一步:阿里云CDN基础配置 第二步:DNS解析设置 第三步:源站服务器防护配置 Nginx服务器配置 防火墙配置(以Ubuntu为例) 第四步:Typecho配置调整 高级防护措施…

[硬件]运算放大器对相位噪声的影响与设计提示

运算放大器对相位噪声的影响与设计提示 文章目录运算放大器对相位噪声的影响与设计提示运放影响位噪声的主要因素如何最小化运放对相位噪声的影响总结运算放大器是常用的模拟电路元器件&#xff0c;通常用于放大信号&#xff0c;增强驱动。但是当使用运放放大一个信号时&#x…

github jekyll+chirpy主题搭建博客

github jekyllchirpy主题搭建博客 标签&#xff1a;后端、blog、jekyll 全文链接 本文简要介绍了如何基于 GitHub Pages、Jekyll 及 Chirpy 主题搭建个人博客的流程和注意事项。 主要内容 GitHub Pages 站点简介 可免费搭建个人博客&#xff0c;支持自定义域名&#xff0c;适…

Flutter状态管理篇之ValueNotifier(三)

目录 前言 一、ValueNotifier 概述 二、ValueNotifier 的实现原理 1.类定义 1.类定义 2.关键字段 3.关键方法 1.构造函数 2.getter:value 3.setter:value: 4.toString 2.继承自ChangeNotifier的机制 3.ValueListenable 接口 三、ValueNotifier 的用法 1.基本用法…

Ubuntu togo 系统安装指南

制作一个 “Ubuntu To Go” 系统&#xff08;也就是一个可以随身携带、在不同电脑上启动并拥有持久化存储的U盘系统&#xff09;是解决你问题的完美方案。 这样一来&#xff0c;你就可以&#xff1a; 不改动你现有的电脑系统 (保留你的Ubuntu 20.04 或 Windows)。拥有一个完整…

Python爬虫实战:研究pefile库相关技术

一、引言 可执行文件(Portable Executable,PE)是 Windows 操作系统中最常见的文件格式,包括.exe、.dll、.sys 等多种类型。对 PE 文件的分析在软件逆向工程、恶意软件检测、系统安全研究等领域具有重要意义。传统的 PE 文件分析主要依赖手动操作和专业工具,效率较低且对分…

盟接之桥说制造:差异化定位与效率竞争的双轮驱动

在当今竞争日益激烈的商业环境中&#xff0c;企业如何在市场中脱颖而出&#xff0c;既避免陷入同质化的价格战&#xff0c;又能够通过效率提升实现可持续发展&#xff0c;是每一个经营者必须思考的问题。本文将围绕“差异化”与“效率竞争”两大核心战略展开分析&#xff0c;探…

Vue基础(前端教程①-路由)

项目结构src/├── router/│ └── index.js # 路由配置├── components/│ ├── Home.vue # 首页组件│ ├── About.vue # 关于页组件│ └── Contact.vue # 联系页组件├── App.vue # 根组件&#xff08;含导航栏&…

驾驭 Spring Boot 事件机制:8 个内置事件 + 自定义扩展实战

驾驭 Spring Boot 事件机制&#xff1a;8 个内置事件 自定义扩展实战在 Spring Boot 应用的完整生命周期中&#xff0c;框架为我们预埋了 8 个关键事件&#xff08;Application-level & Context-level&#xff09;。 理解并善用这些事件&#xff0c;可以在“不侵入框架、…

【kafka4源码学习系列】kafka4总体架构介绍

二 kafka架构介绍学习一个系统之前很重要的一点就是先了解这个系统整体的架构&#xff0c;这能够使我们对整个系统有个总体的认识&#xff0c;清楚地知道这个系统有什么能力。这不仅帮助我们学习时快速定位到我们想要的内容&#xff0c;还能避免我们学习过程中在庞大的系统中迷…

java内存图

java内存图java文件运行流程程序的内存空间认识虚拟机栈程序的执行流程认识堆java的类与对象的关系java文件运行流程 有这样的一份 java 文件 在该目录下的终端运行 javac Hello.java 命令&#xff0c;会生成 Hello.class 文件&#xff0c;内容如下&#xff1a; Hello.java 打…

vscode编辑Markdown文件

一.安装Markdown的插件 vscode的扩展&#xff0c;搜索Markdown Preview Enhanced的插件&#xff0c;并安装。 其他的常用插件&#xff0c;还包括&#xff1a; Markdown All in One &#xff1a;提供了许多有用的功能&#xff0c;如快捷键支持、自动预览、TOC&#xff08;目录&…

【PTA数据结构 | C语言版】查找树中带有指定数据的结点

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 请编写程序&#xff0c;创建有 4 个结点的树&#xff0c;然后查找给定的 x。 输入格式&#xff1a; 输入首先在第一行给出 4 个正整数&#xff0c;依次对应树的根结点、根的第 1、2、3 个孩子结点的…