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/22 21:22:50 阅读更多 →
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/22 21:21:50 阅读更多 →

最新新闻

Ziggy Pydust高级技巧:GIL控制与并发编程实战

Ziggy Pydust高级技巧:GIL控制与并发编程实战

Ziggy Pydust高级技巧:GIL控制与并发编程实战 【免费下载链接】ziggy-pydust A toolkit for building Python extensions in Zig. 项目地址: https://gitcode.com/gh_mirrors/zig/ziggy-pydust Ziggy Pydust是一个强大的工具包,用于在Zig中构建Py…

2026/7/22 22:06:05 阅读更多 →
一文读懂PyTorch-SoftDTW-CUDA的SoftDTW类:API详解与高级用法

一文读懂PyTorch-SoftDTW-CUDA的SoftDTW类:API详解与高级用法

一文读懂PyTorch-SoftDTW-CUDA的SoftDTW类:API详解与高级用法 【免费下载链接】pytorch-softdtw-cuda Fast CUDA implementation of (differentiable) soft dynamic time warping for PyTorch 项目地址: https://gitcode.com/gh_mirrors/py/pytorch-softdtw-cuda …

2026/7/22 22:06:05 阅读更多 →
2026跨境社媒百度SEO实操复盘:30个账号验证过的3个长尾词布局法,稳拿搜索流量

2026跨境社媒百度SEO实操复盘:30个账号验证过的3个长尾词布局法,稳拿搜索流量

跨境社媒内容与百度SEO融合的实战思考 在数字营销领域,跨境社交媒体与国内搜索引擎优化看似分属不同赛道,实则存在深刻的交汇点。经过一段时间的实践与观察,我们通过多个账号的测试,总结出一些关于关键词布局的有效方法&#xff0…

2026/7/22 22:06:05 阅读更多 →
oauth4webapi与FAPI合规开发:1.0高级与2.0安全配置最佳实践

oauth4webapi与FAPI合规开发:1.0高级与2.0安全配置最佳实践

oauth4webapi与FAPI合规开发:1.0高级与2.0安全配置最佳实践 【免费下载链接】oauth4webapi Low-Level OAuth 2 / OpenID Connect Client API for JavaScript Runtimes 项目地址: https://gitcode.com/gh_mirrors/oa/oauth4webapi oauth4webapi是一款面向Java…

2026/7/22 22:06:05 阅读更多 →
Trampoline RTOS核心功能详解:OSEK/VDX与AUTOSAR 4.2标准全支持

Trampoline RTOS核心功能详解:OSEK/VDX与AUTOSAR 4.2标准全支持

Trampoline RTOS核心功能详解:OSEK/VDX与AUTOSAR 4.2标准全支持 【免费下载链接】trampoline Trampoline is a static RTOS for small embedded systems. Its API is aligned with OSEK/VDX OS and AUTOSAR OS 4.2 standards. 项目地址: https://gitcode.com/gh_m…

2026/7/22 22:06:05 阅读更多 →
5分钟上手Threagile:Docker环境快速部署与模型创建全流程

5分钟上手Threagile:Docker环境快速部署与模型创建全流程

5分钟上手Threagile:Docker环境快速部署与模型创建全流程 【免费下载链接】threagile Agile Threat Modeling Toolkit 项目地址: https://gitcode.com/gh_mirrors/th/threagile Threagile是一款敏捷威胁建模工具包(Agile Threat Modeling Toolkit…

2026/7/22 22:05:04 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

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

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

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

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

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

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

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

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

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

2026/7/22 12:54:44 阅读更多 →

月新闻