在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 web (
- 项目结构:确保您的项目包含基本的spring boot结构,如
src/main/java
、pom.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 { @bean public 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
实例。 - 使用
getforobject
、postforobject
等方法发送请求。 - 处理响应数据(假设响应为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; @autowired public weatherservice(resttemplate resttemplate) { this.resttemplate = resttemplate; } public string getweatherdata(string city) { string url = "https://api.weather.com/data?city={city}"; // 发送get请求,将响应解析为string string 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请求,请求体自动序列化为json string response = resttemplate.postforobject(url, requestbody, string.class); return response; }
说明:
postforobject
方法:第一个参数是url,第二个是请求体对象,第三个是响应类型。- spring会自动使用jackson库将对象序列化为json。
5.处理响应
第三方接口通常返回json数据。建议定义pojo类来映射响应。
步骤:
- 创建响应实体类。
- 使用
resttemplate
的getforobject
或postforobject
直接映射到对象。
示例:假设天气api返回{"city":"beijing","temp":25}
。
创建pojo类weatherresponse.java
:
public class weatherresponse { private string city; private int temp; // getters and setters public 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; @autowired public 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.关键设计说明:
- 请求类型支持:
- 通过
httpmethod
参数支持get/post/put/delete等所有http方法 - 请求体支持任意对象类型(自动json序列化)
- 通过
- 参数传递:
- 请求头:通过
httpheaders
对象设置 - 请求体:支持对象自动序列化为json
- get参数:通过url路径参数或查询参数传递
- 请求头:通过
- 日志记录:
- 使用slf4j的
@slf4j
注解(需lombok支持) - 请求/响应日志以json格式记录
- 包含url、方法、头信息、请求体、状态码等完整信息
- 使用slf4j的
- 异常处理:
- 日志记录所有序列化异常
- 响应解析异常时抛出runtimeexception
- 异步调用通过回调函数处理错误
- 扩展性:
- 抽象类提供基础实现
- 业务服务继承并添加具体业务方法
- 支持同步/异步两种调用模式
注意:实际使用需在spring配置中初始化resttemplate
和asyncresttemplate
bean,并配置连接池、超时时间等参数。
到此这篇关于spring boot项目通过resttemplate调用三方接口详细教程的文章就介绍到这了,更多相关spring boot resttemplate调用三方接口内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论