SpringCloud-RestTemplate发送Http请求讲解
一、RestTemplate 讲解1. 没有 RestTemplate 时Java 怎么发 HTTP 请求1.1 用 JDK 原生的 HttpURLConnection// 发一个 GET 请求获取用户信息 public String getUser(Long id) { try { URL url new URL(http://api.example.com/users/ id); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(GET); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); // 读取响应 BufferedReader reader new BufferedReader( new InputStreamReader(conn.getInputStream()) ); StringBuilder response new StringBuilder(); String line; while ((line reader.readLine()) ! null) { response.append(line); } reader.close(); return response.toString(); // 返回的是 JSON 字符串 } catch (IOException e) { throw new RuntimeException(e); } }弊端每发一个请求要写 20 行样板代码没有自动的 JSON 转换返回的是字符串你需要自己用ObjectMapper转成对象错误处理繁琐HTTP 404、500 需要手动判断conn.getResponseCode()没有连接复用每次openConnection()都新建 TCP 连接没有请求模板化每个接口都要重复写超时、请求头设置1.2 所以 Spring 设计了 RestTemplateRestTemplate的核心设计目标像调用本地方法一样发起 HTTP 请求2. RestTemplate 是什么它是Spring 提供的同步 HTTP 客户端封装了 JDK 的HttpURLConnection或 Apache HttpClient、OkHttp让你用更简洁的方式发送 HTTP 请求。它在 Spring 生态中的定位你的 Service 层 ↓ RestTemplate 发 HTTP 请求 ↓ HttpMessageConverter 对象 ↔ JSON/XML 转换 ↓ ClientHttpRequestFactory 实际网络层HttpURLConnection / HttpClient / OkHttp ↓ 目标服务器3. 基本用法对比原生代码3.1 GET 请求原生写法对比// 返回 JSON 字符串自己解析 String json getUser(1L); User user objectMapper.readValue(json, User.class);RestTemplate 写法Autowired private RestTemplate restTemplate; public User getUser(Long id) { // 直接返回 User 对象JSON 转换自动完成 User user restTemplate.getForObject( http://api.example.com/users/{id}, // URL{id} 是占位符 User.class, // 返回类型 id // 占位符的值 ); return user; }为什么能直接返回User对象因为RestTemplate内部注册了MappingJackson2HttpMessageConverter它自动把响应的 JSON 字符串反序列化成User对象。3.2 POST 请求带请求体public User createUser(UserDTO dto) { // 发送 POST 请求dto 自动序列化为 JSON User user restTemplate.postForObject( http://api.example.com/users, dto, // 请求体自动转 JSON User.class // 返回类型 ); return user; }3.3 带请求头如 Token 鉴权public User getUserWithAuth(Long id, String token) { // 构建请求头 HttpHeaders headers new HttpHeaders(); headers.set(Authorization, Bearer token); headers.setContentType(MediaType.APPLICATION_JSON); // 构建请求实体头 体 HttpEntityVoid requestEntity new HttpEntity(headers); // 发送请求 ResponseEntityUser response restTemplate.exchange( http://api.example.com/users/{id}, HttpMethod.GET, requestEntity, User.class, id ); // 获取状态码、响应头、响应体 HttpStatus status response.getStatusCode(); User user response.getBody(); return user; }exchange是最通用的方法可以处理所有 HTTP 方法并且能拿到完整的响应信息状态码、Header、Body。4. 核心设计为什么 RestTemplate 要这样设计4.1 为什么有getForObject和getForEntity两个方法// 方法 1只关心返回的数据 User user restTemplate.getForObject(url, User.class, id); // 方法 2关心完整响应状态码 Header Body ResponseEntityUser response restTemplate.getForEntity(url, User.class, id); HttpStatus status response.getStatusCode(); HttpHeaders headers response.getHeaders(); User user response.getBody();设计原因80% 的场景你只需要数据所以getForObject简化了调用20% 的场景你需要判断 HTTP 状态码或读取响应头所以提供getForEntity4.2 为什么 URL 支持{id}占位符restTemplate.getForObject( http://api.example.com/users/{id}/orders/{orderId}, Order.class, 1L, // 对应 {id} 100L // 对应 {orderId} );设计原因避免字符串拼接url / id容易出错且可读性差内部自动做 URL 编码比如参数里有空格、中文会自动转义4.3 HttpMessageConverter自动转换的秘密RestTemplate能自动处理 JSON是因为它内部维护了一个转换器列表RestTemplate ├── MappingJackson2HttpMessageConverter ← 处理 application/json ├── StringHttpMessageConverter ← 处理 text/plain ├── FormHttpMessageConverter ← 处理 application/x-www-form-urlencoded ├── ByteArrayHttpMessageConverter ← 处理二进制 └── ...执行流程发请求时 UserDTO 对象 ↓ 遍历 converters找到能处理 application/json 的 ↓ MappingJackson2HttpMessageConverter.write() ↓ JSON 字符串 → 发送 收响应时 响应 Content-Type: application/json ↓ 遍历 converters找到能处理 JSON 的 ↓ MappingJackson2HttpMessageConverter.read() ↓ User 对象5. 企业级用法RestTemplate 的配置5.1 为什么需要手动创建 RestTemplateSpring Boot 不会自动注入RestTemplate不像RedisTemplate你需要自己配置。原因HTTP 客户端的配置差异很大超时时间、连接池、SSL、代理框架无法预设一个适合所有场景的默认值。5.2 企业级配置类Configuration public class RestTemplateConfig { Bean public RestTemplate restTemplate() { // 使用 Apache HttpClient 作为底层比 JDK 的 HttpURLConnection 性能更好 HttpClient httpClient HttpClientBuilder.create() .setMaxConnTotal(200) // 最大连接数 .setMaxConnPerRoute(50) // 每个路由的最大连接如 api.example.com .setConnectionTimeToLive(30, TimeUnit.SECONDS) // 连接存活时间 .build(); // 创建工厂 HttpComponentsClientHttpRequestFactory factory new HttpComponentsClientHttpRequestFactory(httpClient); factory.setConnectTimeout(5000); // 连接超时 5 秒 factory.setReadTimeout(10000); // 读取超时 10 秒 RestTemplate restTemplate new RestTemplate(factory); // 添加拦截器如统一加请求头、记录日志 restTemplate.getInterceptors().add(new LoggingInterceptor()); return restTemplate; } }5.3 为什么要用连接池没有连接池的问题每次请求都新建 TCP 连接三次握手高并发时TCP 连接数暴涨导致TIME_WAIT状态过多响应延迟高使用 Apache HttpClient 连接池后连接复用避免重复握手控制最大连接数防止资源耗尽支持 HTTP/1.1 的 Keep-Alive6. RestTemplate 的局限为什么 Spring 官方不推荐在新项目使用6.1 它是同步阻塞的User user restTemplate.getForObject(url, User.class); // 这行代码会阻塞当前线程直到 HTTP 响应返回 // 在高并发下线程池很快被耗尽弊端线程阻塞等待网络 IOCPU 空转不适合高并发场景如网关、聚合服务需要同时调多个下游接口6.2 替代方案WebClientSpring 5 引入Autowired private WebClient webClient; public MonoUser getUser(Long id) { return webClient.get() .uri(http://api.example.com/users/{id}, id) .retrieve() .bodyToMono(User.class); // 非阻塞返回 Mono响应式 }WebClient的优势基于 Netty异步非阻塞一个线程可以并发处理多个请求适合微服务架构下的高并发调用6.3 但 RestTemplate 仍然广泛使用因为代码简单直观适合大多数 CRUD 场景团队熟悉度高维护成本低很多老项目仍在使用7. 总结问题RestTemplate 的解决方案发 HTTP 请求代码繁琐封装为getForObject、postForObject等一行调用JSON 转换麻烦HttpMessageConverter自动序列化/反序列化URL 拼接易出错占位符{id}自动替换和编码需要处理响应状态码ResponseEntity封装完整响应连接管理低效可配置ClientHttpRequestFactory使用连接池同步阻塞性能差新项目推荐WebClient一句话RestTemplate是 Spring 对 HTTP 客户端的封装让你用调用本地方法的方式发起远程 HTTP 请求屏蔽了网络通信的底层细节。二、ObjectMapper 讲解1. 没有 ObjectMapper 时Java 怎么处理 JSON1.1 手动拼接 JSON 字符串假设你有一个User对象要返回给前端public class User { private Long id; private String name; private Integer age; private LocalDateTime createTime; // getter / setter }没有 ObjectMapper你只能手动拼字符串public String userToJson(User user) { return { \id\: user.getId() , \name\:\ user.getName() \, \age\: user.getAge() , \createTime\:\ user.getCreateTime() \ }; }弊端字段多了根本没法维护字符串拼接容易漏逗号、引号语法错误如果name里有特殊字符如或换行直接破坏 JSON 格式日期格式不统一有的接口返回2024-01-01有的返回毫秒时间戳嵌套对象User里有Address时拼接复杂度爆炸1.2 手动解析 JSON 更痛苦前端传过来一个 JSON 字符串你要转成 Java 对象{id:1,name:张三,age:25,createTime:2024-01-15 10:30:00}没有 ObjectMapper你只能手动解析public User jsonToUser(String json) { // 用字符串截取正则根本不可行 // 只能用 org.json 或 fastjson 的底层 API一行行 get JSONObject obj new JSONObject(json); User user new User(); user.setId(obj.getLong(id)); user.setName(obj.getString(name)); user.setAge(obj.getInt(age)); // ... 每个字段都要手动映射 return user; }弊端字段多了写死人字段名拼写错误在运行时才暴露类型转换容易出错比如 JSON 里age传了字符串25手动getInt可能抛异常嵌套对象需要递归解析1.3 所以 Jackson 库被创建出来Jackson 是 Java 世界最流行的 JSON 处理库而ObjectMapper是它的核心入口类。2. ObjectMapper 是什么ObjectMapper是 Jackson 库提供的对象映射器负责方向方法俗称Java 对象 → JSON 字符串writeValueAsString()序列化SerializationJSON 字符串 → Java 对象readValue()反序列化Deserialization3. 核心用法演示3.1 序列化对象 → JSONUser user new User(); user.setId(1L); user.setName(张三); user.setAge(25); ObjectMapper mapper new ObjectMapper(); String json mapper.writeValueAsString(user); System.out.println(json); // 输出{id:1,name:张三,age:25}对比手动拼接一行代码搞定自动处理引号、转义、特殊字符字段再多也不怕3.2 反序列化JSON → 对象String json {\id\:1,\name\:\张三\,\age\:25}; ObjectMapper mapper new ObjectMapper(); User user mapper.readValue(json, User.class); System.out.println(user.getName()); // 输出张三对比手动解析一行代码自动映射所有字段类型安全id自动转Longage自动转Integer字段名对应不上时报错明确3.3 处理集合和嵌套对象// List 序列化 ListUser list Arrays.asList(user1, user2); String json mapper.writeValueAsString(list); // 输出[{id:1,name:张三},{id:2,name:李四}] // List 反序列化 ListUser users mapper.readValue(json, new TypeReferenceListUser() {});TypeReference是什么因为 Java 泛型擦除mapper.readValue(json, List.class)无法知道 List 里是什么类型。TypeReference是 Jackson 提供的技巧利用匿名内部类保留泛型信息。4. Spring Boot 中 ObjectMapper 的自动配置4.1 你几乎不需要手动 new ObjectMapper()在 Spring Boot 项目中当你引入spring-boot-starter-webJackson 作为默认 JSON 库被引入Spring Boot 自动配置了一个ObjectMapperBean// Spring Boot 自动配置的源码简化 Bean Primary public ObjectMapper objectMapper() { ObjectMapper mapper new ObjectMapper(); // 自动应用 application.yml 中的配置 // 自动注册 classpath 下的模块 return mapper; }这意味着RestController返回对象时Spring 自动用这个ObjectMapper转 JSONRequestBody接收 JSON 时Spring 自动用这个ObjectMapper转对象你可以直接Autowired注入使用4.2 实际使用方式方式一让 Spring 自动处理最常用RestController public class UserController { GetMapping(/user/{id}) public User getUser(PathVariable Long id) { User user userService.getById(id); return user; // Spring 自动用 ObjectMapper 转成 JSON 返回 } PostMapping(/user) public User createUser(RequestBody UserDTO dto) { // Spring 自动用 ObjectMapper 把请求体的 JSON 转成 UserDTO return userService.save(dto); } }方式二手动注入使用特殊场景Service public class UserService { Autowired private ObjectMapper objectMapper; public void cacheUser(User user) { // 手动转成 JSON 字符串存入 Redis String json objectMapper.writeValueAsString(user); redisTemplate.opsForValue().set(user: user.getId(), json); } }5. ObjectMapper 的常用配置5.1 为什么需要配置默认的ObjectMapper行为不一定符合企业需求比如日期字段默认序列化为时间戳如1705312200000前端看不懂空对象可能抛异常字段命名风格可能不匹配Java 用驼峰userName前端要下划线user_name5.2 通过 application.yml 配置推荐spring: jackson: date-format: yyyy-MM-dd HH:mm:ss # 日期格式 time-zone: GMT8 # 时区 default-property-inclusion: non_null # 忽略 null 字段不输出 property-naming-strategy: SNAKE_CASE # 驼峰转下划线效果对比public class User { private Long id; private String name; private String email; // 假设为 null private LocalDateTime createTime; } // 默认配置输出 // {id:1,name:张三,email:null,createTime:1705312200000} // 加上面配置后输出 // {id:1,name:张三,create_time:2024-01-15 10:30:00} // 注意email 为 null 被忽略了createTime 变成了下划线 可读日期5.3 通过代码配置更灵活Bean public ObjectMapper objectMapper() { ObjectMapper mapper new ObjectMapper(); // 1. 日期格式转字符串不用时间戳 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.setDateFormat(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss)); // 2. 忽略 null 字段 mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 3. 驼峰转下划线 mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); // 4. 允许单引号前端有时传单引号 JSON mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); // 5. 未知字段不报错前端传了后端没有的字段忽略而不是抛异常 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); return mapper; }6. 核心配置项详解企业级常用配置作用场景WRITE_DATES_AS_TIMESTAMPS控制日期序列化格式禁用后输出2024-01-15启用后输出1705312200000NON_NULL忽略值为 null 的字段减少 JSON 体积前端不用判空SNAKE_CASE驼峰命名转下划线Java 用userNameJSON 用user_nameFAIL_ON_UNKNOWN_PROPERTIES遇到未知字段是否报错禁用后前端多传字段不会导致 400 错误ALLOW_SINGLE_QUOTES允许 JSON 用单引号包裹兼容不规范的前端 JSON7. 注意事项7.1 ObjectMapper 是线程安全的// 正确全局复用一个实例 Service public class UserService { Autowired private ObjectMapper mapper; // Spring 注入的单例线程安全 } // 错误每次方法调用都 new 一个浪费资源 public void bad() { ObjectMapper mapper new ObjectMapper(); // 不要这样写 }设计原因ObjectMapper内部有大量缓存如类结构反射信息创建成本高应该复用。7.2 不要混用不同的 ObjectMapper 实例如果你手动new ObjectMapper()它的配置和 Spring 自动配置的那个可能不一样导致Controller 返回的 JSON 格式是一套规则你手动序列化存 Redis 的 JSON 是另一套规则两边不一致反序列化时可能出问题企业级做法统一使用 Spring 注入的ObjectMapper或者确保手动创建的实例配置完全一致。8. 总结问题ObjectMapper 的解决方案手动拼 JSON 容易出错writeValueAsString()自动序列化手动解析 JSON 繁琐readValue()自动反序列化日期格式不统一配置date-format字段命名风格不一致配置SNAKE_CASEnull 字段污染 JSON配置NON_NULL前端多传字段导致报错配置FAIL_ON_UNKNOWN_PROPERTIES一句话ObjectMapper是 Java 世界处理 JSON 的翻译官负责 Java 对象和 JSON 字符串之间的双向转换。在 Spring Boot 中它已经被自动配置好你只需要通过application.yml或代码调整它的行为就能统一控制整个应用的 JSON 格式。

相关新闻

System.Numerics深度解析:dotnet-samples中的SIMD技术与高性能计算实战

System.Numerics深度解析:dotnet-samples中的SIMD技术与高性能计算实战

System.Numerics深度解析:dotnet-samples中的SIMD技术与高性能计算实战 【免费下载链接】dotnet-samples Contains samples and documentation for libraries and tools of the .NET framework. Pull requests welcome! 项目地址: https://gitcode.com/gh_mirrors…

2026/7/24 5:06:25 阅读更多 →
react-hooks-worker实战案例:打造响应式的图片处理应用

react-hooks-worker实战案例:打造响应式的图片处理应用

react-hooks-worker实战案例:打造响应式的图片处理应用 【免费下载链接】react-hooks-worker React custom hooks for web workers 项目地址: https://gitcode.com/gh_mirrors/re/react-hooks-worker 在现代Web应用开发中,处理大型图片或复杂计算…

2026/7/22 21:22:50 阅读更多 →
多工地考勤从3人天压缩至半天:工程机械租赁客户上线晋辉机联云实录

多工地考勤从3人天压缩至半天:工程机械租赁客户上线晋辉机联云实录

摘要华南某工程机械租赁公司,坐拥50台设备、80名现场人员、8个在建工地,将原有「微信群Excel」传统考勤模式,全面替换为晋辉机联云GPS留痕-后台自动汇总-APP工资条全流程数字化链路。系统上线约3个月,月度考勤汇总工作耗时从原3人…

2026/7/24 6:29:09 阅读更多 →

最新新闻

AI逆向设计如何革新材料研发流程

AI逆向设计如何革新材料研发流程

1. AI逆向设计改写材料研发的核心逻辑材料研发领域正在经历一场由AI驱动的范式转移。传统"试错法"研发周期通常需要10-15年,而MIT的研究团队通过AI逆向设计系统,仅用6周就发现了新型高强度合金。这种颠覆性突破的核心在于构建了"性能→结…

2026/7/24 8:31:48 阅读更多 →
CIMPro视频融合宽高比调整:解决画面拉伸变形的工程实践

CIMPro视频融合宽高比调整:解决画面拉伸变形的工程实践

在实际数字孪生项目中,视频融合是连接物理世界与虚拟空间的关键技术之一。CIMPro 作为国产数字孪生平台,其视频融合功能能够将实时监控视频、历史录像或第三方流媒体无缝叠加到三维场景中,用于安防监控、生产巡检、交通调度等场景。但视频源与…

2026/7/24 8:31:48 阅读更多 →
Metasploit实战利用CVE-2017-7269漏洞攻陷IIS 6.0服务器

Metasploit实战利用CVE-2017-7269漏洞攻陷IIS 6.0服务器

1. 项目概述:一次针对老旧系统的精准打击在渗透测试或安全研究领域,我们常常会遇到一些“古董级”的系统,它们因为各种原因(如业务连续性、升级成本等)仍在线上运行,却早已停止了官方安全更新。微软的IIS 6…

2026/7/24 8:31:48 阅读更多 →
科颜氏高保湿小样包材定制,老板别被便宜包材坑了客诉钱

科颜氏高保湿小样包材定制,老板别被便宜包材坑了客诉钱

拿着美系头部K家高保湿体系小样图来找我定包材的白牌定制老板,十个有八个第一句话就是:“这玩意儿包材成本能压到三毛一支不?”我直接跟你说,你要是真用三毛钱的包材灌K家同款高保湿体系,三个月后客户全跑光&#xff0…

2026/7/24 8:31:48 阅读更多 →
Sora国内怎么用?资深AIGC架构师亲授:避开3大法律雷区、2类账号封禁风险与1套本地化推理链路

Sora国内怎么用?资深AIGC架构师亲授:避开3大法律雷区、2类账号封禁风险与1套本地化推理链路

更多请点击: https://kaifayun.com 第一章:Sora 国内怎么用 目前,OpenAI 官方未向中国大陆地区开放 Sora 的直接访问权限,其官网( sora.openai.com)在国内无法正常加载,且不支持中国手机号注册…

2026/7/24 8:31:48 阅读更多 →
醒图APP开发的作用以及相关功能介绍

醒图APP开发的作用以及相关功能介绍

在这个大家普遍喜欢美颜修图的时代背景下,类似醒图APP开发也会逐渐备受关注,并形成一个具有商机的线上化服务平台。一、类似醒图APP开发具有什么作用?对于平台来说,类似醒图APP开发的作用在于吸引更多的方面,可以发挥重…

2026/7/24 8:30:48 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻