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

Spring Boot项目通过RestTemplate调用三方接口详细教程

目录

一、简单说明

1. 准备工作

2. 添加依赖

3. 配置RestTemplate Bean

4. 使用RestTemplate发送请求

5. 处理响应

6. 错误处理

7. 完整示例:集成到Controller

8. 注意事项和最佳实践

二、抽象设计

1. 通用API服务类设计

2. 业务服务类实现

3. 控制器调用示例

4. 定时任务示例

5.关键设计说明:


在Spring Boot项目中,使用RestTemplate调用第三方接口是一种常见的HTTP客户端操作。RestTemplate是Spring框架提供的一个简单、同步的HTTP客户端工具,支持发送GET、POST等请求,并处理响应。本教程将逐步指导您完成整个过程,确保结构清晰、易于理解。教程基于Spring Boot 2.x版本(如2.7.x),如果您使用Spring Boot 3.x,部分配置可能需调整(例如,RestTemplate不再自动配置,需手动添加依赖和Bean)。

一、简单说明

1. 准备工作
  • 确保项目已创建:如果您还没有Spring Boot项目,请先创建一个。可以使用Spring Initializr生成项目,选择以下依赖:
    • Spring Web (spring-boot-starter-web)
  • 项目结构:确保您的项目包含基本的Spring Boot结构,如src/main/javapom.xml文件等。
  • 第三方接口信息:准备好要调用的第三方接口URL、请求方法(GET/POST等)、请求参数和响应格式(如JSON)。例如,假设我们调用一个天气API:https://api.weather.com/data?city=Beijing
2. 添加依赖
  • 在Spring Boot 2.x中,spring-boot-starter-web已包含RestTemplate。打开pom.xml文件,添加或确认以下依赖:
    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 如果需要JSON处理,添加Jackson依赖(通常已包含在starter-web中) -->
    </dependencies>
    

  • 保存文件后,运行mvn clean install或使用IDE重新加载项目。
3. 配置RestTemplate Bean
  • RestTemplate需要被Spring容器管理。创建一个配置类来定义Bean。
  • 在项目中新建一个类,例如RestTemplateConfig.java
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;@Configuration
    public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
    }
    

  • 说明
    • @Configuration注解标记为配置类。
    • @Bean方法创建RestTemplate实例,Spring会自动注入到其他组件。
    • 如果需要自定义(如设置超时),可以添加HttpComponentsClientHttpRequestFactory
      @Bean
      public RestTemplate restTemplate() {HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();factory.setConnectTimeout(5000); // 连接超时5秒factory.setReadTimeout(5000);    // 读取超时5秒return new RestTemplate(factory);
      }
      

4. 使用RestTemplate发送请求
  • 现在,您可以在Service或Controller中使用RestTemplate。以下以发送GET和POST请求为例。

  • 步骤

    • 注入RestTemplate实例。
    • 使用getForObjectpostForObject等方法发送请求。
    • 处理响应数据(假设响应为JSON)。
  • 示例1:GET请求

    • 假设调用天气API:https://api.weather.com/data?city={city},返回JSON数据。
    • 创建一个Service类,例如WeatherService.java
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.web.client.RestTemplate;@Service
      public class WeatherService {private final RestTemplate restTemplate;@Autowiredpublic WeatherService(RestTemplate restTemplate) {this.restTemplate = restTemplate;}public String getWeatherData(String city) {String url = "https://api.weather.com/data?city={city}";// 发送GET请求,将响应解析为StringString response = restTemplate.getForObject(url, String.class, city);return response; // 实际项目中,应解析JSON为对象}
      }
      

    • 说明
      • getForObject方法:第一个参数是URL(使用占位符{city}),第二个是响应类型,第三个是占位符值。
      • 响应直接返回字符串,实际中应使用POJO类解析JSON(见第5步)。
  • 示例2:POST请求

    • 假设调用登录API:https://api.example.com/login,需要发送JSON请求体。
    • WeatherService中添加方法:
      public String loginUser(String username, String password) {String url = "https://api.example.com/login";// 创建请求体(例如Map或自定义对象)Map<String, String> requestBody = new HashMap<>();requestBody.put("username", username);requestBody.put("password", password);// 发送POST请求,请求体自动序列化为JSONString response = restTemplate.postForObject(url, requestBody, String.class);return response;
      }
      

    • 说明
      • postForObject方法:第一个参数是URL,第二个是请求体对象,第三个是响应类型。
      • Spring会自动使用Jackson库将对象序列化为JSON。
5. 处理响应
  • 第三方接口通常返回JSON数据。建议定义POJO类来映射响应。
  • 步骤
    • 创建响应实体类。
    • 使用RestTemplategetForObjectpostForObject直接映射到对象。
  • 示例:假设天气API返回{"city":"Beijing","temp":25}
    • 创建POJO类WeatherResponse.java
      public class WeatherResponse {private String city;private int temp;// Getters and Setterspublic String getCity() { return city; }public void setCity(String city) { this.city = city; }public int getTemp() { return temp; }public void setTemp(int temp) { this.temp = temp; }
      }
      

    • 在Service中修改方法:
      public WeatherResponse getWeatherData(String city) {String url = "https://api.weather.com/data?city={city}";WeatherResponse response = restTemplate.getForObject(url, WeatherResponse.class, city);return response;
      }
      

    • 说明getForObject会自动将JSON反序列化为WeatherResponse对象。
6. 错误处理
  • 调用三方接口可能失败(如网络问题、接口错误)。使用try-catch捕获异常。
  • 常见异常
    • HttpClientErrorException:4xx错误(如404 Not Found)。
    • HttpServerErrorException:5xx错误(如500 Internal Server Error)。
    • RestClientException:通用错误(如超时)。
  • 示例:在Service中添加错误处理。
    import org.springframework.web.client.HttpClientErrorException;
    import org.springframework.web.client.RestClientException;public WeatherResponse getWeatherData(String city) {String url = "https://api.weather.com/data?city={city}";try {return restTemplate.getForObject(url, WeatherResponse.class, city);} catch (HttpClientErrorException e) {// 处理客户端错误(如参数无效)System.err.println("客户端错误: " + e.getStatusCode());return null;} catch (HttpServerErrorException e) {// 处理服务端错误System.err.println("服务端错误: " + e.getStatusCode());return null;} catch (RestClientException e) {// 处理其他错误(如超时)System.err.println("请求失败: " + e.getMessage());return null;}
    }
    

  • 最佳实践:使用全局异常处理(如@ControllerAdvice)统一管理错误。
7. 完整示例:集成到Controller
  • 创建一个Controller来调用Service,并测试接口。
  • 示例WeatherController.java
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;@RestController
    public class WeatherController {private final WeatherService weatherService;@Autowiredpublic WeatherController(WeatherService weatherService) {this.weatherService = weatherService;}@GetMapping("/weather/{city}")public WeatherResponse getWeather(@PathVariable String city) {return weatherService.getWeatherData(city);}
    }
    

  • 测试
    • 启动Spring Boot应用。
    • 访问http://localhost:8080/weather/Beijing,将返回天气数据。
    • 使用Postman或curl测试POST请求。
8. 注意事项和最佳实践
  • 线程安全RestTemplate是线程安全的,可以注入到多个组件。
  • 性能:在高并发场景,考虑使用异步客户端(如WebClient),但RestTemplate适用于简单同步调用。
  • 安全性:如果接口需要认证,添加Headers:
    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "Bearer token");
    HttpEntity<Object> entity = new HttpEntity<>(requestBody, headers);
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
    

  • 日志:启用日志查看请求细节(在application.properties添加logging.level.org.springframework.web.client=DEBUG)。
  • Spring Boot 3.x调整:在Spring Boot 3中,添加spring-boot-starter-webflux依赖,并使用RestTemplate自定义Bean(如上第3步)。
  • 测试:编写单元测试(使用MockRestServiceServer模拟响应)。

通过以上步骤,您可以轻松在Spring Boot项目中集成RestTemplate调用三方接口。如果有具体接口需求,可进一步优化代码。

二、抽象设计

以下是为SpringBoot项目设计的通用API调用封装方案,满足您的所有需求:

1. 通用API服务类设计

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;public abstract class AbstractApiService {private static final Logger logger = LoggerFactory.getLogger(AbstractApiService.class);protected final RestTemplate syncRestTemplate;protected final AsyncRestTemplate asyncRestTemplate;private final ObjectMapper objectMapper = new ObjectMapper();protected AbstractApiService(RestTemplate restTemplate, AsyncRestTemplate asyncRestTemplate) {this.syncRestTemplate = restTemplate;this.asyncRestTemplate = asyncRestTemplate;}// 同步调用protected <T> ResponseEntity<String> executeSync(String url, HttpMethod method, HttpHeaders headers, T body) {logRequest(url, method, headers, body);HttpEntity<T> requestEntity = new HttpEntity<>(body, headers);ResponseEntity<String> response = syncRestTemplate.exchange(url, method, requestEntity, String.class);logResponse(response);return response;}// 异步调用protected <T> ListenableFuture<ResponseEntity<String>> executeAsync(String url, HttpMethod method, HttpHeaders headers, T body) {logRequest(url, method, headers, body);HttpEntity<T> requestEntity = new HttpEntity<>(body, headers);ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.exchange(url, method, requestEntity, String.class);future.addCallback(result -> logResponse(result),ex -> logger.error("Async call failed: {}", ex.getMessage()));return future;}// JSON格式日志记录private <T> void logRequest(String url, HttpMethod method, HttpHeaders headers, T body) {try {String logData = String.format("{\"url\":\"%s\", \"method\":\"%s\", \"headers\":%s, \"body\":%s}",url, method, objectMapper.writeValueAsString(headers), objectMapper.writeValueAsString(body));logger.info("API请求: {}", logData);} catch (Exception e) {logger.error("请求日志序列化失败", e);}}private void logResponse(ResponseEntity<String> response) {try {String logData = String.format("{\"status\":%s, \"headers\":%s, \"body\":%s}",response.getStatusCodeValue(),objectMapper.writeValueAsString(response.getHeaders()),response.getBody());logger.info("API响应: {}", logData);} catch (Exception e) {logger.error("响应日志序列化失败", e);}}
}

2. 业务服务类实现

import org.springframework.http.*;
import org.springframework.stereotype.Service;@Service
public class BusinessApiService extends AbstractApiService {public BusinessApiService(RestTemplate restTemplate, AsyncRestTemplate asyncRestTemplate) {super(restTemplate, asyncRestTemplate);}// 带请求体的业务调用public BusinessResponse callBusinessApi(BusinessRequest request) {HttpHeaders headers = new HttpHeaders();headers.set("X-API-KEY", "your-api-key");headers.setContentType(MediaType.APPLICATION_JSON);ResponseEntity<String> response = executeSync("https://api.example.com/business",HttpMethod.POST,headers,request);return parseResponse(response.getBody(), BusinessResponse.class);}// GET请求示例public BusinessData getBusinessData(String id) {String url = "https://api.example.com/data/" + id;HttpHeaders headers = new HttpHeaders();headers.set("Authorization", "Bearer token");ResponseEntity<String> response = executeSync(url, HttpMethod.GET, headers, null);return parseResponse(response.getBody(), BusinessData.class);}// 异步调用示例public ListenableFuture<ResponseEntity<String>> asyncFetchData(AsyncRequest request) {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);return executeAsync("https://api.example.com/async",HttpMethod.POST,headers,request);}private <T> T parseResponse(String body, Class<T> valueType) {try {return objectMapper.readValue(body, valueType);} catch (Exception e) {logger.error("响应解析失败: {}", body, e);throw new RuntimeException("API响应解析异常");}}
}// 请求响应对象示例
public class BusinessRequest {private String param1;private int param2;// getters/setters
}public class BusinessResponse {private String result;private int statusCode;// getters/setters
}

3. 控制器调用示例

import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api")
public class BusinessController {private final BusinessApiService apiService;public BusinessController(BusinessApiService apiService) {this.apiService = apiService;}@PostMapping("/business")public BusinessResponse handleBusiness(@RequestBody BusinessRequest request) {return apiService.callBusinessApi(request);}@GetMapping("/data/{id}")public BusinessData getData(@PathVariable String id) {return apiService.getBusinessData(id);}
}

4. 定时任务示例

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class ScheduledTasks {private final BusinessApiService apiService;public ScheduledTasks(BusinessApiService apiService) {this.apiService = apiService;}@Scheduled(fixedRate = 3600000) // 每小时执行public void hourlySync() {BusinessRequest request = new BusinessRequest();// 设置请求参数BusinessResponse response = apiService.callBusinessApi(request);// 处理响应}
}

5.关键设计说明:

  1. 请求类型支持

    • 通过HttpMethod参数支持GET/POST/PUT/DELETE等所有HTTP方法
    • 请求体支持任意对象类型(自动JSON序列化)
  2. 参数传递

    • 请求头:通过HttpHeaders对象设置
    • 请求体:支持对象自动序列化为JSON
    • GET参数:通过URL路径参数或查询参数传递
  3. 日志记录

    • 使用SLF4J的@Slf4j注解(需Lombok支持)
    • 请求/响应日志以JSON格式记录
    • 包含URL、方法、头信息、请求体、状态码等完整信息
  4. 异常处理

    • 日志记录所有序列化异常
    • 响应解析异常时抛出RuntimeException
    • 异步调用通过回调函数处理错误
  5. 扩展性

    • 抽象类提供基础实现
    • 业务服务继承并添加具体业务方法
    • 支持同步/异步两种调用模式

注意:实际使用需在Spring配置中初始化RestTemplateAsyncRestTemplate Bean,并配置连接池、超时时间等参数。

http://www.lryc.cn/news/619166.html

相关文章:

  • 带宽受限信道下的数据传输速率计算:有噪声与无噪声场景
  • mysql锁+索引
  • 自然语言处理关键库解析和使用方法- FuzzyWuzzy
  • 【3】Transformers快速入门:大语言模型LLM是啥?
  • 【4】Transformers快速入门:自然语言模型 vs 统计语言模型
  • GaussDB 数据库架构师修炼(十三)安全管理(2)-数据库权限管理
  • 如何构建PHP表单页面及验证相关原理(PHP基础)
  • 前后端分离项目中Spring MVC的请求执行流程
  • Kubernetes 资源管理全解析:从基础到企业级实践
  • TDengine 可观测性最佳实践
  • VBS 时间函数
  • 移动端网页调试实战,键盘弹出与视口错位问题的定位与优化
  • 需求跟踪矩阵是什么
  • mysql参数调优之 sync_binlog (二)
  • python技巧:控制转台的2个坑。
  • [激光原理与应用-253]:理论 - 几何光学 - 变焦镜头的组成原理及图示解析
  • 分布式事务Seata使用不当引发的全局锁问题
  • hashmap如何解决碰撞
  • JavaWeb从入门到精通!第二天!(Servlet)
  • 揭开Spectre漏洞的神秘面纱
  • 【后端】Spring @Resource和@Autowired的用法和区别
  • 告别数据孤岛!React 路由 3 种传参方法全解析
  • [Robotics_py] 定位滤波器 | 预测与更新 | 扩展卡尔曼滤波器(`EKF`)
  • 嵌入式学习 标准IO(完整版)
  • 浏览器面试题及详细答案 88道(12-22)
  • 【C#补全计划】StringBuilder
  • 【shell脚本编程】-4 shell脚本编写冒泡排序
  • C++11新增关键字和范围for循环
  • Flutter ExpansionPanel组件(可收缩的列表)
  • Qt中定时器介绍和使用