在SpringBoot项目直接使用okhttp、httpClient或者RestTemplate发起HTTP请求,既繁琐又不方便统一管理。
因此,在这里推荐一个适用于SpringBoot项目的轻量级HTTP客户端框架retrofit-spring-boot-starter,使用非常简单方便,同时又提供诸多功能增强。目前项目已经更新至2.2.2版本,并且会持续进行迭代优化。
前言
Retrofit是适用于Android和Java且类型安全的HTTP客户端,其最大的特性的是支持通过接口的方式发起HTTP请求。而spring-boot是使用最广泛的Java开发框架,但是Retrofit官方没有支持与spring-boot框架快速整合,因此我们开发了retrofit-spring-boot-starter。
retrofit-spring-boot-starter实现了Retrofit与spring-boot框架快速整合,并且支持了诸多功能增强,极大简化开发。
项目持续优化迭代。
功能特性
自定义注入OkHttpClient 注解式拦截器 连接池管理 日志打印 请求重试 错误解码器 全局拦截器 熔断降级 微服务之间的HTTP调用 调用适配器 数据转换器
快速使用
引入依赖
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
定义http接口
接口必须使用@RetrofitClient注解标记!http相关注解可参考官方文档:retrofit官方文档。Spring Boot 学习笔记,学习下吧。
@RetrofitClient( Url ="${test. Url}")
publicinterfaceHttpApi{
@GET("person")
Result<Person>getPerson(@Query("id")Long id);
}
注入使用
将接口注入到其它Service中即可使用!
@Service
publicclassTestService{
@Autowired
privateHttpApi httpApi;
publicvoidtest(){
// 通过httpApi发起http请求
}
}
HTTP请求相关注解
HTTP请求相关注解,全部使用了retrofit原生注解。详细信息可参考官方文档:retrofit官方文档,以下是一个简单说明。
| 注解分类 | 支持的注解 |
|---|---|
| 请求方式 | @GET@HEAD@POST@PUT@DELETE@OPTIONS |
| 请求头 | @Header@HeaderMap@Headers |
| Query参数 | @Query@QueryMap@QueryName |
| path参数 | @Path |
| form-encoded参数 | @Field@FieldMap@FormUrlEncoded |
| 文件上传 | @Multipart@Part@PartMap |
| url参数 | @Url |
配置项说明
retrofit-spring-boot-starter支持了多个可配置的属性,用来应对不同的业务场景。您可以视情况进行修改,具体说明如下:
| 配置 | 默认值 | 说明 |
|---|---|---|
| enable-log | true | 启用日志打印 |
| logging-interceptor | DefaultLoggingInterceptor | 日志打印拦截器 |
| pool | 连接池配置 | |
| disable-void-return-type | false | 禁用java.lang.Void返回类型 |
| retry-interceptor | DefaultRetryInterceptor | 请求重试拦截器 |
| global-converter-factories | JacksonConverterFactory | 全局转换器工厂 |
| global-call-adapter-factories | BodyCallAdapterFactory,ResponseCallAdapterFactory | 全局调用适配器工厂 |
| enable-degrade | false | 是否启用熔断降级 |
| degrade-type | sentinel | 熔断降级实现方式(目前仅支持Sentinel) |
| resource-name-parser | DefaultResourceNameParser | 熔断资源名称解析器,用于解析资源名称 |
yml配置方式:
retrofit:
enable-response-call-adapter:true
# 启用日志打印
enable-log:true
# 连接池配置
pool:
test1:
max-idle-connections:3
keep-alive-second:100
test2:
max-idle-connections:5
keep-alive-second:50
# 禁用void返回值类型
disable-void-return-type:false
# 日志打印拦截器
logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
# 请求重试拦截器
retry-interceptor: com.github.lianjiatech.retrofit.spring.boot.retry.DefaultRetryInterceptor
# 全局转换器工厂
global-converter-factories:
- retrofit2.converter.jackson.JacksonConverterFactory
# 全局调用适配器工厂
global-call-adapter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
- com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory
# 是否启用熔断降级
enable-degrade:true
# 熔断降级实现方式
degrade-type: sentinel
# 熔断资源名称解析器
resource-name-parser: com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser
高级功能
自定义注入OkHttpClient
通常情况下,通过@RetrofitClient注解属性动态创建OkHttpClient对象能够满足大部分使用场景。但是在某些情况下,用户可能需要自定义OkHttpClient,这个时候,可以在接口上定义返回类型是OkHttpClient.Builder的静态方法来实现。
插播一条:如果你近期准备面试跳槽,点击Java面试库小程序刷题吧,共 2500+ 道,几乎覆盖了所有主流 Java 技术面试题。
代码示例如下:
@RetrofitClient( Url ="http://ke.com")
publicinterfaceHttpApi3{
@OkHttpClientBuilder
staticOkHttpClient.BuilderokhttpClientBuilder(){
returnnewOkHttpClient.Builder()
.connectTimeout(1, TimeUnit.SECONDS)
.readTimeout(1, TimeUnit.SECONDS)
.writeTimeout(1, TimeUnit.SECONDS);
}
@GET
Result<Person>getPerson(@Url String url, @Query("id")Long id);
}
方法必须使用
@OkHttpClientBuilder注解标记!
注解式拦截器
很多时候,我们希望某个接口下的某些http请求执行统一的拦截处理逻辑。为了支持这个功能,retrofit-spring-boot-starter提供了注解式拦截器,做到了基于url路径的匹配拦截。
使用的步骤主要分为2步:
继承 PathMatchInterceptor编写拦截处理器;接口上使用 @Intercept进行标注。如需配置多个拦截器,在接口上标注多个@Intercept注解即可!
下面以给指定请求的url后面拼接timestamp时间戳为例,介绍下如何使用注解式拦截器。Spring Boot 学习笔记,分享学习下。
继承 PathMatchInterceptor编写拦截处理器
@Component
publicclassTimeStampInterceptorextends PathMatchInterceptor{
@Override
publicResponsedoIntercept(Chain chain)throwsIOException{
Request request = chain.request();
HttpUrl url = request.url();
longtimestamp = System.currentTimeMillis();
HttpUrl newUrl = url.newBuilder()
.addQueryParameter("timestamp", String.valueOf(timestamp))
.build();
Request newRequest = request.newBuilder()
.url(newUrl)
.build();
returnchain.proceed(newRequest);
}
}
接口上使用@Intercept进行标注
@RetrofitClient( Url ="${test. Url}")
@Intercept(handler = TimeStampInterceptor.class,include= {"/api/**"}, exclude ="/api/test/savePerson")
publicinterfaceHttpApi{
@GET("person")
Result<Person>getPerson(@Query("id")Long id);
@POST("savePerson")
Result<Person>savePerson(@Body Person person);
}
上面的@Intercept配置表示:拦截HttpApi接口下/api/**路径下(排除/api/test/savePerson)的请求,拦截处理器使用TimeStampInterceptor。
扩展注解式拦截器
有的时候,我们需要在拦截注解动态传入一些参数,然后再执行拦截的时候需要使用这个参数。这种时候,我们可以扩展实现自定义拦截注解。自定义拦截注解必须使用@InterceptMark标记,并且注解中必须包括include()、exclude()、handler()属性信息。使用的步骤主要分为3步:
自定义拦截注解 继承 PathMatchInterceptor编写拦截处理器接口上使用自定义拦截注解;
例如我们需要在请求头里面动态加入accessKeyId、accessKeySecret签名信息才能正常发起http请求,这个时候可以自定义一个加签拦截器注解@Sign来实现。
插播一条:如果你近期准备面试跳槽,点击Java面试库小程序刷题吧,共 2500+ 道,几乎覆盖了所有主流 Java 技术面试题。
下面以自定义@Sign拦截注解为例进行说明。
自定义@Sign注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public@interfaceSign {
/**
* 密钥key
* 支持占位符形式配置。
*
*@return
*/
StringaccessKeyId();
/**
* 密钥
* 支持占位符形式配置。
*
*@return
*/
StringaccessKeySecret();
/**
* 拦截器匹配路径
*
*@return
*/
String[] include()default{"/**"};
/**
* 拦截器排除匹配,排除指定路径拦截
*
*@return
*/
String[] exclude()default{};
/**
* 处理该注解的拦截器类
* 优先从spring容器获取对应的Bean,如果获取不到,则使用反射创建一个!
*
*@return
*/
Class<? extends PathMatchInterceptor> handler()defaultSignInterceptor.class;
}
扩展自定义拦截注解有以下2点需要注意:
自定义拦截注解必须使用@InterceptMark标记。注解中必须包括 include()、exclude()、handler()属性信息。
实现SignInterceptor
@Component
publicclassSignInterceptorextends PathMatchInterceptor{
privateString accessKeyId;
privateString accessKeySecret;
publicvoidsetAccessKeyId(String accessKeyId){
this.accessKeyId = accessKeyId;
}
publicvoidsetAccessKeySecret(String accessKeySecret){
this.accessKeySecret = accessKeySecret;
}
@Override
publicResponsedoIntercept(Chain chain)throwsIOException{
Request request = chain.request();
Request newReq = request.newBuilder()
.addHeader("accessKeyId", accessKeyId)
.addHeader("accessKeySecret", accessKeySecret)
.build();
returnchain.proceed(newReq);
}
}
上述accessKeyId和accessKeySecret字段值会依据@Sign注解的accessKeyId()和accessKeySecret()值自动注入,如果@Sign指定的是占位符形式的字符串,则会取配置属性值进行注入。另外,accessKeyId和accessKeySecret字段必须提供setter方法。
接口上使用@Sign
@RetrofitClient( Url ="${test. Url}")
@Sign(accessKeyId ="${test.accessKeyId}", accessKeySecret ="${test.accessKeySecret}", exclude = {"/api/test/person"})
publicinterfaceHttpApi{
@GET("person")
Result<Person>getPerson(@Query("id")Long id);
@POST("savePerson")
Result<Person>savePerson(@Body Person person);
}
这样就能在指定url的请求上,自动加上签名信息了。
连接池管理
默认情况下,所有通过Retrofit发送的http请求都会使用max-idle-connections=5 keep-alive-second=300的默认连接池。当然,我们也可以在配置文件中配置多个自定义的连接池,然后通过@RetrofitClient的poolName属性来指定使用。比如我们要让某个接口下的请求全部使用poolName=test1的连接池,代码实现如下:
配置连接池。
retrofit:
# 连接池配置
pool:
test1:
max-idle-connections:3
keep-alive-second:100
test2:
max-idle-connections:5
keep-alive-second:50
通过 @RetrofitClient的poolName属性来指定使用的连接池。
@RetrofitClient( Url ="${test. Url}", poolName="test1")
publicinterfaceHttpApi{
@GET("person")
Result<Person>getPerson(@Query("id")Long id);
}
日志打印
很多情况下,我们希望将http请求日志记录下来。通过retrofit.enableLog配置可以全局控制日志是否开启。针对每个接口,可以通过@RetrofitClient的enableLog控制是否开启,通过logLevel和logStrategy,可以指定每个接口的日志打印级别以及日志打印策略。retrofit-spring-boot-starter支持了5种日志打印级别(ERROR,WARN,INFO,DEBUG,TRACE),默认INFO;支持了4种日志打印策略(NONE,BASIC,HEADERS,BODY),默认BASIC。4种日志打印策略含义如下:
NONE:No logs.BASIC:Logs request and response lines.HEADERS:Logs request and response lines and their respective headers.BODY:Logs request and response lines and their respective headers and bodies (if present).
retrofit-spring-boot-starter默认使用了DefaultLoggingInterceptor执行真正的日志打印功能,其底层就是okhttp原生的HttpLoggingInterceptor。当然,你也可以自定义实现自己的日志打印拦截器,只需要继承 LoggingInterceptor(具体可以参考DefaultLoggingInterceptor的实现),然后在配置文件中进行相关配置即可。
retrofit:
# 日志打印拦截器
logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
请求重试
retrofit-spring-boot-starter支持请求重试功能,只需要在接口或者方法上加上@Retry注解即可。@Retry支持重试次数maxRetries、重试时间间隔intervalMs以及重试规则retryRules配置。
重试规则支持三种配置:
RESPONSE_STATUS_NOT_2XX:响应状态码不是2xx时执行重试;OCCUR_IO_EXCEPTION:发生IO异常时执行重试;OCCUR_EXCEPTION:发生任意异常时执行重试;
默认响应状态码不是2xx或者发生IO异常时自动进行重试。需要的话,你也可以继承 RetryInterceptor实现自己的请求重试拦截器,然后将其配置上去。
retrofit:< 继续阅读与本文标签相同的文章
爬虫逆向面试题
在.NET中正确使用HttpClient的方式
-
性能优化之卡顿延迟
2026-05-14栏目: 教程
-
第16问:Filecoin从DSN角度解读
2026-05-14栏目: 教程
-
C/C+从零基础到精通,究竟是如何快速完成的?其实只需要这6步!
2026-05-14栏目: 教程
-
谷歌再爆重大安全漏洞!华为却成最大赢家?网友:这谁还敢用!
2026-05-14栏目: 教程
-
Excel崩溃文件如何找回
2026-05-14栏目: 教程
