当前位置: 首页 > news >正文

spring boot 外部 API 调用 ----22

 

 

覆盖 Spring Boot 3 官方推荐的两种调用方式:RestClient(命令式灵活调用) + HTTP Service Client(声明式接口调用)。基于公开测试接口 JSONPlaceholder 演示,无需额外搭建服务,复制即可运行,严格遵循生产级最佳实践。

一、项目结构

plaintext
 
 
com.example.apicall
├── ApiCallApplication.java        # 启动类
├── entity
│   └── Post.java                  # 通用响应实体
├── config
│   └── ApiClientConfig.java       # 客户端统一配置
├── client
│   └── JsonPlaceholderApi.java    # 声明式HTTP接口
└── service├── RestClientDemoService.java # RestClient用法演示└── HttpServiceDemoService.java# 声明式调用演示
└── controller└── ApiTestController.java     # 测试接口

 

 

二、pom.xml 核心依赖

Spring Boot 3.x 内置 RestClientHTTP Service,只需 Web 基础依赖即可,无需额外第三方包。
xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version></parent><groupId>com.example</groupId><artifactId>rest-api-call-demo</artifactId><version>1.0.0</version><properties><java.version>17</java.version></properties><dependencies><!-- Web 基础:内置 RestClient + HTTP Service 能力 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok 简化代码 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>
</project>

 

 

三、通用响应实体

模拟外部接口返回的帖子数据,对接公开测试接口 jsonplaceholder.typicode.com
java
 
运行
 
 
package com.example.apicall.entity;import lombok.Data;@Data
public class Post {private Integer id;private Integer userId;private String title;private String body;
}

 


四、第一部分:RestClient 灵活调用(对应 227、228 集)

Spring 6 推出的现代 HTTP 客户端,替代旧版 RestTemplate,流式 API 更简洁,支持同步调用。

1. 配置类(生产级最佳实践)

统一配置 baseUrl、超时、默认请求头,注册为 Spring Bean,避免每次调用重复创建。
java
 
运行
 
 
package com.example.apicall.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestClient;@Configuration
public class ApiClientConfig {/*** RestClient 客户端 Bean* 对应227集:现代REST调用方式* 最佳实践:预配置baseUrl、超时时间、默认头,复用实例*/@Beanpublic RestClient jsonPlaceholderRestClient() {// 配置超时:连接3秒,读取5秒,防止外部接口卡住SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(3000);factory.setReadTimeout(5000);return RestClient.builder().baseUrl("https://jsonplaceholder.typicode.com").defaultHeader("Content-Type", "application/json").requestFactory(factory).build();}
}

 

2. 业务服务类(基础 + 高级用法)

java
 
运行
 
 
package com.example.apicall.service;import com.example.apicall.entity.Post;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;import java.util.List;@Service
@RequiredArgsConstructor
public class RestClientDemoService {private final RestClient jsonPlaceholderRestClient;/*** 1. 基础GET:根据ID查询单条数据* 对应227集:简单GET调用*/public Post getPostById(Integer id) {return jsonPlaceholderRestClient.get().uri("/posts/{id}", id)    // 路径参数占位符.retrieve()                 // 发起请求并解析响应.body(Post.class);          // 响应体自动转成Java对象
    }/*** 2. 基础GET:查询列表*/public List<Post> getAllPosts() {return jsonPlaceholderRestClient.get().uri("/posts").retrieve().body(List.class);}/*** 3. POST请求:提交数据* 对应228集:超出简单GET的高级用法*/public Post createPost(Post post) {return jsonPlaceholderRestClient.post().uri("/posts").body(post)                 // 请求体
                .retrieve().body(Post.class);}/*** 4. 高级:自定义异常处理 + 获取响应状态* 对应228集:错误处理、状态码判断*/public Post getPostWithErrorHandle(Integer id) {return jsonPlaceholderRestClient.get().uri("/posts/{id}", id).retrieve()// 4xx/5xx 状态码自定义处理.onStatus(status -> status.is4xxClientError(), (req, resp) -> {throw new RuntimeException("客户端错误,状态码:" + resp.getStatusCode());}).onStatus(status -> status.is5xxServerError(), (req, resp) -> {throw new RuntimeException("外部服务异常");}).body(Post.class);}
}

 

 

五、第二部分:HTTP Service Client 声明式调用(对应 229~231 集)

类似 OpenFeign 的声明式写法,只需要定义接口,Spring 自动生成实现,代码更简洁,维护性更强,是固定接口调用的首选方案。

1. 声明式接口定义

java
 
运行
 
 
package com.example.apicall.client;import com.example.apicall.entity.Post;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.PostExchange;
import org.springframework.web.service.annotation.HttpExchange;import java.util.List;/*** 声明式HTTP接口* 对应229集:声明式REST调用* 只写接口和注解,Spring自动生成实现类*/
@HttpExchange("/posts")
public interface JsonPlaceholderApi {// 查询单条@GetExchange("/{id}")Post getPostById(Integer id);// 查询列表
    @GetExchangeList<Post> listPosts();// 新建
    @PostExchangePost createPost(Post post);
}

 

2. 注册为 Spring Bean(配置类补充)

ApiClientConfig.java 中追加 Bean 定义,通过代理工厂创建接口实现。
java
 
运行
 
 
/*** HTTP Service 声明式客户端 Bean* 对应230集:消费REST API* 对应231集:按服务分组管理,不同服务对应不同接口Bean*/
@Bean
public JsonPlaceholderApi jsonPlaceholderApi(RestClient.Builder builder) {// 复用RestClient的配置能力作为底层客户端RestClient restClient = builder.baseUrl("https://jsonplaceholder.typicode.com").defaultHeader("Content-Type", "application/json").build();// 创建代理工厂,生成接口实现return HttpServiceProxyFactory.builderFor(RestClientAdapter.create(restClient)).build().createClient(JsonPlaceholderApi.class);
}

 

3. 使用示例

java
 
运行
 
 
package com.example.apicall.service;import com.example.apicall.client.JsonPlaceholderApi;
import com.example.apicall.entity.Post;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;import java.util.List;@Service
@RequiredArgsConstructor
public class HttpServiceDemoService {// 直接注入声明式接口,和调用本地方法一样private final JsonPlaceholderApi jsonPlaceholderApi;public Post getPost(Integer id) {return jsonPlaceholderApi.getPostById(id);}public List<Post> listPosts() {return jsonPlaceholderApi.listPosts();}public Post addPost(Post post) {return jsonPlaceholderApi.createPost(post);}
}

 

 
💡 分组说明(对应 231 集):如果有多个外部服务,就定义多个接口 + 多个 Bean,每个对应不同的 baseUrl,按服务分组管理,结构清晰互不干扰。

六、测试接口 Controller

java
 
运行
 package com.example.apicall.controller;import com.example.apicall.entity.Post;
import com.example.apicall.service.HttpServiceDemoService;
import com.example.apicall.service.RestClientDemoService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/api/test")
@RequiredArgsConstructor
public class ApiTestController {private final RestClientDemoService restClientDemoService;private final HttpServiceDemoService httpServiceDemoService;// ===== RestClient 测试 =====@GetMapping("/rest/post/{id}")public Post restGetPost(@PathVariable Integer id) {return restClientDemoService.getPostById(id);}@PostMapping("/rest/post")public Post restCreatePost(@RequestBody Post post) {return restClientDemoService.createPost(post);}// ===== HTTP Service 测试 =====@GetMapping("/http/post/{id}")public Post httpGetPost(@PathVariable Integer id) {return httpServiceDemoService.getPost(id);}@GetMapping("/http/posts")public List<Post> httpListPosts() {return httpServiceDemoService.listPosts();}
}

 


七、启动类

java
 
运行
 
 
package com.example.apicall;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ApiCallApplication {public static void main(String[] args) {SpringApplication.run(ApiCallApplication.class, args);}
}

 

 

八、课程对应表

表格
 
集数核心内容对应代码
226 REST API 消费者概念 前置说明 + 整体设计
227 RestClient 现代 REST 调用方式 RestClient 配置 + 基础 GET 方法
228 RestClient 高级用法(POST、错误处理) createPost、异常状态码处理
229 HTTP Service Client 声明式调用介绍 JsonPlaceholderApi 接口定义
230 用 HTTP Service 消费 REST 接口 接口代理 Bean + 服务层调用
231 HTTP Service 分组管理 按服务拆分接口 + 独立 Bean 的设计

九、最佳实践总结

  1. 选型原则
    • 固定接口、标准化调用 → 优先用 HTTP Service,代码最少、维护性最强
    • 动态 URL、复杂请求、需要精细控制 → 用 RestClient
    • 旧项目兼容可保留 RestTemplate,新项目直接上 RestClient
  2. 配置规范
    • 统一抽取 baseUrl、超时、公共头到配置类,不要硬编码在业务代码里
    • 必须设置连接超时和读取超时,防止外部接口故障拖垮自身服务
    • 不同外部服务分组配置,各自独立 Bean,避免混淆
  3. 异常与容错
    • 对 4xx、5xx 状态码做分类处理,不要全吞异常
    • 生产环境建议配合重试、熔断组件(如 Resilience4j)
    • 外部调用必须打日志,记录入参、出参、耗时,方便排查问题
http://www.jsqmd.com/news/1304257/

相关文章:

  • 大厂系统设计面试:高并发抽奖系统架构解析
  • 2026年可伸缩遮阳棚厂家推荐榜单:别墅露台/户外庭院/商用摆摊折叠伸缩雨棚品牌实力深度解析 - 优企名品
  • 本科生学术写作必备AI工具全测评
  • 冒险岛资源提取器WzComparerR2:游戏素材可视化分析终极指南
  • 2026年目前口碑好的一次性超声波成型机厂家推荐,人造革皮超声波分切机/桌布超声波花边机,一次性超声波成型机公司有哪些 - 品牌推荐师
  • Summer Record-August
  • 年GMV从3000万到破亿的家居企业,如何通过AI陪跑实现战略落地的3步拆解?
  • 从SPWM到SVPWM:高性能电机FOC控制的核心调制技术详解
  • 技术人如何理性应对外界标签与自我认知:从Uzi案例看职业成长
  • HarmonyOS 应用开发《掌上英语》第79篇:@ReusableV2 全局复用池:单词卡片列表的极致性能优化
  • 模拟题6——CSP202506C 消息解码
  • 2026年近期吉林信誉好的中国著名美术家实力公司——袁惠民儿童版画艺术传承 - 装修教育财税推荐2026
  • 宝马i3提前开放订购,市场反响热烈
  • CSDN浏览器助手:开发者效率工具,全局搜索与智能工作流实战
  • Bilibili-Old:如何免费恢复B站经典界面?完整解决方案深度解析
  • LDO线性稳压器深度解析:从工作原理到选型与PCB布局实战
  • 一件代发看着简单实则利润微薄?抖音小店真实盈利空间客观剖析 - 抖掌柜
  • AI推理中Token优化策略:从隐藏位置到成本控制实战
  • 50 Cent地下音乐合集鉴别指南:从音质判断到资源管理
  • 高效时间管理:构建2026年2月28日周六的规划系统
  • 「开源项目」我不想再把密码和API Key 塞进接入了API中转站的 Agent 了,所以做了 Airlock
  • 2026年钢针源头厂家优选:不锈钢针、钨钢针、碳钢针、合金钢针、研磨钢针、304钢针、超细钢针及磁力钢针定制加工一站式实力厂家 - 优企名品
  • 模型玩具品控指南:从关节紧实度到漆面耐久性的深度把玩与修复
  • 商业路演活动参与全攻略:从信息确认到现场执行
  • Python字符串格式化全解析:从f-string到千位分隔符与精度控制
  • NMOS与PMOS核心差异详解:从原理到选型与电路设计实战
  • 工业级稳定性:C#通信程序异常处理、看门狗机制与容错设计
  • 如何快速实现智能图片分层:Layerdivider终极指南
  • 渗透实战|偷梁换柱!UUID 与数字 ID 混用引发水平越权漏洞全拆解 500$
  • CCS铁魄EVA二号机二式开箱评测:合金骨架、灯光效果与品控全解析