{"id":15024504,"url":"https://github.com/lianjiatech/retrofit-spring-boot-starter","last_synced_at":"2026-02-12T09:04:27.117Z","repository":{"id":37442503,"uuid":"252883578","full_name":"LianjiaTech/retrofit-spring-boot-starter","owner":"LianjiaTech","description":"A spring-boot starter for retrofit, supports rapid integration and feature enhancements.（适用于retrofit的spring-boot-starter，支持快速集成和功能增强）","archived":false,"fork":false,"pushed_at":"2025-05-09T10:35:27.000Z","size":1070,"stargazers_count":1818,"open_issues_count":10,"forks_count":344,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-05-09T11:51:03.297Z","etag":null,"topics":["http","java","okhttp3","retrofit","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LianjiaTech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-04-04T01:44:57.000Z","updated_at":"2025-05-09T10:31:59.000Z","dependencies_parsed_at":"2023-12-17T13:24:19.733Z","dependency_job_id":"4246c937-b5d3-4178-831d-dd1d97f0b562","html_url":"https://github.com/LianjiaTech/retrofit-spring-boot-starter","commit_stats":null,"previous_names":["lianjiatech/retrofit-plus"],"tags_count":69,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LianjiaTech%2Fretrofit-spring-boot-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LianjiaTech%2Fretrofit-spring-boot-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LianjiaTech%2Fretrofit-spring-boot-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LianjiaTech%2Fretrofit-spring-boot-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LianjiaTech","download_url":"https://codeload.github.com/LianjiaTech/retrofit-spring-boot-starter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254029008,"owners_count":22002284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","java","okhttp3","retrofit","spring-boot"],"created_at":"2024-09-24T20:00:27.310Z","updated_at":"2026-02-12T09:04:27.109Z","avatar_url":"https://github.com/LianjiaTech.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# retrofit-spring-boot-starter\n\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)\n![Maven Central](https://img.shields.io/maven-central/v/com.github.lianjiatech/retrofit-spring-boot-starter.svg?label=Maven)\n[![License](https://img.shields.io/badge/JDK-1.8+-4EB1BA.svg)](https://docs.oracle.com/javase/8/docs/index.html)\n[![License](https://img.shields.io/badge/SpringBoot-1.4.2+-green.svg)](https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/LianjiaTech/retrofit-spring-boot-starter)\n\n[English Document](https://github.com/LianjiaTech/retrofit-spring-boot-starter/blob/master/README_EN.md)\n\n**[retrofit](https://square.github.io/retrofit/)支持将HTTP API转化成JAVA接口，本组件将Retrofit和SpringBoot深度整合，并支持了多种实用功能增强。**\n\n- **Spring Boot 3.x 项目，请使用retrofit-spring-boot-starter 3.x**\n- **Spring Boot 1.x/2.x\n  项目，请使用[retrofit-spring-boot-starter 2.x](https://github.com/LianjiaTech/retrofit-spring-boot-starter/tree/2.x)**\n  ，支持Spring Boot\n  1.4.2及以上版本。\n\n\u003e 🚀项目持续优化迭代，欢迎大家提ISSUE和PR！麻烦大家能给一颗star⭐️，您的star是我们持续更新的动力！\n\ngithub项目地址：[https://github.com/LianjiaTech/retrofit-spring-boot-starter](https://github.com/LianjiaTech/retrofit-spring-boot-starter)\n\ngitee项目地址：[https://gitee.com/lianjiatech/retrofit-spring-boot-starter](https://gitee.com/lianjiatech/retrofit-spring-boot-starter)\n\n## 快速开始\n\n### 引入依赖\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.lianjiatech\u003c/groupId\u003e\n   \u003cartifactId\u003eretrofit-spring-boot-starter\u003c/artifactId\u003e\n    \u003cversion\u003e3.2.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n对于绝大部分Spring-Boot项目，引入依赖即可使用。如果引入依赖之后，组件无法正常工作，可尝试如下方案解决：\n\n#### 手动自动配置导入\n\n有些场景下RetrofitAutoConfiguration可能无法正常加载执行，可以尝试手动配置导入，代码如下：\n\n```java\n\n@Configuration\n@ImportAutoConfiguration({RetrofitAutoConfiguration.class})\npublic class SpringBootAutoConfigBridge {\n}\n```\n\n如果项目仍然采用Spring XML配置文件，需要在XML配置文件加上SpringBoot自动配置类。\n\n```xml\n\u003c!-- 导入SpringBoot自动配置类 --\u003e\n\u003cbean class=\"com.yourpackage.config.SpringBootAutoConfig\"/\u003e\n```\n\n### 定义HTTP JAVA接口\n\n**接口必须使用`@RetrofitClient`注解标记！**\n\n```java\n@RetrofitClient(baseUrl = \"http://localhost:8080/api/user/\")\npublic interface UserService {\n\n   /**\n    * 根据id查询用户姓名\n    */\n   @POST(\"getName\")\n   String getName(@Query(\"id\") Long id);\n}\n```\n\n\u003e 注意：**方法请求路径慎用`/`开头**。对于`Retrofit`而言，如果`baseUrl=http://localhost:8080/api/test/`，方法请求路径如果是`person`，则该方法完整的请求路径是：`http://localhost:8080/api/test/person`。而方法请求路径如果是`/person`，则该方法完整的请求路径是：`http://localhost:8080/person`。\n\n### 注入使用\n\n**将接口注入到其它Service中即可使用！**\n\n```java\n@Service\npublic class BusinessService {\n\n    @Autowired\n    private UserService userService;\n\n    public void doBusiness() {\n       // call userService\n    }\n}\n```\n\n**默认情况下，自动使用`SpringBoot`扫描路径进行`RetrofitClient`注册**，你也可以在配置类加上`@RetrofitScan`手动指定扫描路径。\n\n## HTTP请求相关注解\n\n`HTTP`请求相关注解，全部使用了`Retrofit`原生注解，以下是一个简单说明：\n\n| 注解分类|支持的注解 |\n|------------|-----------|\n|请求方式|`@GET` `@HEAD` `@POST` `@PUT` `@DELETE` `@OPTIONS` `@HTTP`|\n|请求头|`@Header` `@HeaderMap` `@Headers`|\n|Query参数|`@Query` `@QueryMap` `@QueryName`|\n|path参数|`@Path`|\n|form-encoded参数|`@Field` `@FieldMap` `@FormUrlEncoded`|\n| 请求体 |`@Body`|\n|文件上传|`@Multipart` `@Part` `@PartMap`|\n|url参数|`@Url`|\n\n\u003e 详细信息可参考官方文档：[retrofit官方文档](https://square.github.io/retrofit/)\n\n## 功能特性\n\n- [x] [HTTP响应结果自动适配JAVA接口返回类型](#HTTP响应结果自动适配JAVA接口返回类型)\n- [x] [自定义数据转换器](#自定义数据转换器)\n- [x] [自定义OkHttpClient](#自定义OkHttpClient)\n- [x] [日志打印](#日志打印)\n- [x] [请求重试](#请求重试)\n- [x] [全局应用拦截器](#全局应用拦截器)\n- [x] [全局网络拦截器](#全局网络拦截器)\n- [x] [注解式url路径匹配拦截器](#注解式url路径匹配拦截器)\n- [x] [自定义拦截器注解](#自定义拦截器注解)\n- [x] [熔断降级](#熔断降级)\n- [x] [错误解码器](#错误解码器)\n- [x] [微服务之间的HTTP调用](#微服务之间的HTTP调用)\n- [x] [自定义RetrofitClient注解](#自定义RetrofitClient注解)\n- [x] [配置属性](#配置属性)\n\n### HTTP响应结果自动适配JAVA接口返回类型\n\n本组件会将HTTP响应结果自动适配成JAVA接口定义的返回类型，目前支持以下几种返回类型：\n\n- `Call\u003cT\u003e`: 不执行适配处理，直接返回`Call\u003cT\u003e`对象\n- `String`：将`Response Body`适配成`String`返回。\n- 基础类型(`Long`/`Integer`/`Boolean`/`Float`/`Double`)：将`Response Body`适配成上述基础类型\n- `CompletableFuture\u003cT\u003e`: 将`Response Body`适配成`CompletableFuture\u003cT\u003e`对象返回\n- `Void`: 不关注返回类型可以使用`Void`\n- `Response\u003cT\u003e`: 将`Response`适配成`Response\u003cT\u003e`对象返回\n- `Mono\u003cT\u003e`: `Project Reactor`响应式返回类型\n- `Single\u003cT\u003e`：`Rxjava`响应式返回类型（支持`Rxjava2/Rxjava3`）\n- `Completable`：`Rxjava`响应式返回类型，`HTTP`请求没有响应体（支持`Rxjava2/Rxjava3`）\n- 任意`POJO`类型： 将`Response Body`适配成对应的`POJO`对象返回\n\n#### 适配实现方式\n\n`Retrofit`底层是通过`CallAdapterFactory`将`Call\u003cT\u003e`对象适配成接口方法的返回值类型，本组件扩展了一些`CallAdapterFactory`实现：\n\n-  `BodyCallAdapterFactory`\n    - 同步执行`HTTP`请求，将响应体内容适配成方法的返回值类型。\n    - 任意方法返回值类型都可以使用`BodyCallAdapterFactory`，优先级最低。\n-  `ResponseCallAdapterFactory`\n    - 同步执行`HTTP`请求，将响应体内容适配成`Retrofit.Response\u003cT\u003e`返回。\n    - 只有方法返回值类型为`Retrofit.Response\u003cT\u003e`，才可以使用`ResponseCallAdapterFactory`。\n-  响应式编程相关`CallAdapterFactory`\n\n通过继承`CallAdapter.Factory`，可以实现任何方式的HTTP响应报文到JAVA接口返回类型的适配处理。 组件支持通过`retrofit.global-call-adapter-factories`配置全局调用适配器工厂：\n```yaml\nretrofit:\n  # 全局适配器工厂(组件扩展的`CallAdaptorFactory`工厂已经内置，这里请勿重复配置)\n  global-call-adapter-factories:\n    # ...\n```\n\n针对每个JAVA接口，还可以通过`@RetrofitClient.callAdapterFactories`指定当前接口采用的`CallAdapter.Factory`。\n\n### 自定义数据转换器\n\n`Retrofit`使用`Converter`将`@Body`注解的对象转换成HTTP请求体，将HTTP响应体转换成一个`Java`对象，支持以下几种`Converter`：\n\n- [Gson](https://github.com/google/gson): com.squareup.Retrofit:converter-gson\n- [Jackson](https://github.com/FasterXML/jackson): com.squareup.Retrofit:converter-jackson\n- [Moshi](https://github.com/square/moshi/): com.squareup.Retrofit:converter-moshi\n- [Protobuf](https://developers.google.com/protocol-buffers/): com.squareup.Retrofit:converter-protobuf\n- [Wire](https://github.com/square/wire): com.squareup.Retrofit:converter-wire\n- [Simple XML](http://simple.sourceforge.net/): com.squareup.Retrofit:converter-simplexml\n- [JAXB](https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html): com.squareup.retrofit2:converter-jaxb\n- fastJson：com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory\n\n组件支持通过`retrofit.global-converter-factories`配置全局`Converter.Factory`，默认的是`retrofit2.converter.jackson.JacksonConverterFactory`。\n\n如果需要修改`Jackson`配置，自行覆盖`JacksonConverterFactory`的`bean`配置即可。\n\n```yaml\nretrofit:\n   # 全局转换器工厂\n   global-converter-factories:\n      - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory\n      - retrofit2.converter.jackson.JacksonConverterFactory\n```\n\n针对每个`Java`接口，还可以通过`@RetrofitClient.converterFactories`指定当前接口采用的`Converter.Factory`。\n\n### 自定义OkHttpClient\n\n对于OkHttpClient超时相关配置，可以通过配置文件或者`@RetrofitClient`设置。但是如果需要修改更灵活复杂的`OkHttpClient`配置，推荐通过自定义`OkHttpClient`来实现，步骤如下：\n\n#### 实现`SourceOkHttpClientRegistrar`接口\n   \n```java\n@Component\npublic class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar {\n\n   @Override\n   public void register(SourceOkHttpClientRegistry registry) {\n      // 注册customOkHttpClient，超时时间设置为1s\n      registry.register(\"customOkHttpClient\", new OkHttpClient.Builder()\n              .connectTimeout(Duration.ofSeconds(1))\n              .writeTimeout(Duration.ofSeconds(1))\n              .readTimeout(Duration.ofSeconds(1))\n              .addInterceptor(chain -\u003e chain.proceed(chain.request()))\n              .build());\n   }\n}\n```\n\n#### 通过`@RetrofitClient.sourceOkHttpClient`指定当前接口要使用的`OkHttpClient`\n\n```java\n@RetrofitClient(baseUrl = \"${test.baseUrl}\", sourceOkHttpClient = \"customOkHttpClient\")\npublic interface CustomOkHttpUserService {\n\n   /**\n    * 根据id查询用户信息\n    */\n   @GET(\"getUser\")\n   User getUser(@Query(\"id\") Long id);\n}\n```\n\n### 日志打印\n\n组件支持支持全局日志打印和声明式日志打印。\n\n#### 全局日志打印\n\n默认情况下，全局日志打印是开启的，默认配置如下：\n\n```yaml\nretrofit:\n   # 全局日志打印配置\n   global-log:\n      # 启用日志打印\n      enable: true\n      # 全局日志打印级别\n      log-level: info\n      # 全局日志打印策略\n      log-strategy: basic\n      # 是否聚合打印请求日志\n      aggregate: true\n      # 日志名称，默认为{@link LoggingInterceptor} 的全类名\n      logName: com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor\n     # 日志中需要隐藏的敏感请求头\n      redact-headers: \n```\n\n四种日志打印策略含义如下：\n\n1. `NONE`：No logs.\n2. `BASIC`：Logs request and response lines.\n3. `HEADERS`：Logs request and response lines and their respective headers.\n4. `BODY`：Logs request and response lines and their respective headers and bodies (if present).\n\n#### 声明式日志打印\n\n如果只需要部分请求才打印日志，可以在相关接口或者方法上使用`@Logging`注解。\n\n#### 日志打印自定义扩展\n\n如果需要修改日志打印行为，可以继承`LoggingInterceptor`，并将其配置成`Spring bean`。\n\n### 请求重试\n\n组件支持支持全局重试和声明式重试。\n\n#### 全局重试\n\n全局重试默认关闭，默认配置项如下：\n\n```yaml\nretrofit:\n  # 全局重试配置\n  global-retry:\n     # 是否启用全局重试\n     enable: false\n     # 全局重试间隔时间\n     interval-ms: 100\n     # 全局最大重试次数\n     max-retries: 2\n     # 全局重试规则\n     retry-rules:\n        - response_status_not_2xx\n        - occur_io_exception\n ```\n\n重试规则支持三种配置：\n\n1. `RESPONSE_STATUS_NOT_2XX`：响应状态码不是`2xx`时执行重试\n2. `OCCUR_IO_EXCEPTION`：发生IO异常时执行重试\n3. `OCCUR_EXCEPTION`：发生任意异常时执行重试\n\n#### 声明式重试\n\n如果只有一部分请求需要重试，可以在相应的接口或者方法上使用`@Retry`注解。\n\n#### 请求重试自定义扩展\n\n如果需要修改请求重试行为，可以继承`RetryInterceptor`，并将其配置成`Spring bean`。\n\n### 全局应用拦截器\n\n如果我们需要对整个系统的的`HTTP`请求执行统一的拦截处理，可以实现全局拦截器`GlobalInterceptor`, 并配置成`spring Bean`。\n\n```java\n@Component\npublic class MyGlobalInterceptor implements GlobalInterceptor {\n   @Override\n   public Response intercept(Chain chain) throws IOException {\n      Response response = chain.proceed(chain.request());\n      // response的Header加上global\n      return response.newBuilder().header(\"global\", \"true\").build();\n   }\n}\n```\n\n### 全局网络拦截器\n\n实现`NetworkInterceptor`接口，并配置成`spring Bean`。\n\n### 注解式url路径匹配拦截器\n\n很多场景下，我们需要仅针对某些HTTP接口做一些特殊逻辑，此时可以使用url路径匹配拦截器，优雅实现该功能，使用的步骤如下：\n\n#### 继承`BasePathMatchInterceptor`编写拦截处理器\n\n```java\n@Component\npublic class PathMatchInterceptor extends BasePathMatchInterceptor {\n   @Override\n   protected Response doIntercept(Chain chain) throws IOException {\n      Response response = chain.proceed(chain.request());\n      // response的Header加上path.match\n      return response.newBuilder().header(\"path.match\", \"true\").build();\n   }\n}\n```\n\n#### 接口上使用`@Intercept`进行标注\n\n```java\n@RetrofitClient(baseUrl = \"${test.baseUrl}\")\n@Intercept(handler = PathMatchInterceptor.class, include = {\"/api/user/**\"}, exclude = \"/api/user/getUser\")\n// @Intercept() 如果需要使用多个路径匹配拦截器，继续添加@Intercept即可\npublic interface InterceptorUserService {\n\n   /**\n    * 根据id查询用户姓名\n    */\n   @POST(\"getName\")\n   Response\u003cString\u003e getName(@Query(\"id\") Long id);\n\n   /**\n    * 根据id查询用户信息\n    */\n   @GET(\"getUser\")\n   Response\u003cUser\u003e getUser(@Query(\"id\") Long id);\n\n}\n```\n\n上面的`@Intercept`配置表示：拦截`InterceptorUserService`接口下`/api/user/**`路径下（排除`/api/user/getUser`）的请求，拦截处理器使用`PathMatchInterceptor`。如果需要使用多个拦截器，在接口上标注多个`@Intercept`注解即可。\n\n### 自定义拦截器注解\n\n有的时候，我们需要在\"拦截注解\"动态传入一些参数，然后在拦截的时候使用这些参数。 这时候，我们可以使用\"自定义拦截注解\"，步骤如下：\n\n1. 自定义注解。必须使用`@InterceptMark`标记，并且注解中必须包括`include、exclude、handler`字段。\n2. 继承`BasePathMatchInterceptor`编写拦截处理器\n3. 接口上使用自定义注解\n\n例如，我们需要\"在请求头里面动态加入`accessKeyId`、`accessKeySecret`签名信息才能再发起HTTP请求\"，这时候可以自定义`@Sign`注解来实现。\n\n\n#### 自定义`@Sign`注解\n\n```java\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Documented\n@InterceptMark\npublic @interface Sign {\n    \n    String accessKeyId();\n\n    String accessKeySecret();\n\n    String[] include() default {\"/**\"};\n\n    String[] exclude() default {};\n\n    Class\u003c? extends BasePathMatchInterceptor\u003e handler() default SignInterceptor.class;\n}\n```\n\n在`@Sign`注解中指定了使用的拦截器是`SignInterceptor`。\n\n#### 实现`SignInterceptor`\n\n```java\n@Component\n@Setter\npublic class SignInterceptor extends BasePathMatchInterceptor {\n\n   private String accessKeyId;\n\n   private String accessKeySecret;\n\n   @Override\n   public Response doIntercept(Chain chain) throws IOException {\n      Request request = chain.request();\n      Request newReq = request.newBuilder()\n              .addHeader(\"accessKeyId\", accessKeyId)\n              .addHeader(\"accessKeySecret\", accessKeySecret)\n              .build();\n      Response response = chain.proceed(newReq);\n      return response.newBuilder().addHeader(\"accessKeyId\", accessKeyId)\n              .addHeader(\"accessKeySecret\", accessKeySecret).build();\n   }\n}\n```\n\n\u003e 注意：`accessKeyId`和`accessKeySecret`字段必须提供`setter`方法。\n\n拦截器的`accessKeyId`和`accessKeySecret`字段值会依据`@Sign`注解的`accessKeyId()`和`accessKeySecret()`值自动注入，如果`@Sign`指定的是占位符形式的字符串，则会取配置属性值进行注入。\n\n#### 接口上使用`@Sign`\n\n```java\n@RetrofitClient(baseUrl = \"${test.baseUrl}\")\n@Sign(accessKeyId = \"${test.accessKeyId}\", accessKeySecret = \"${test.accessKeySecret}\", include = \"/api/user/getAll\")\npublic interface InterceptorUserService {\n\n   /**\n    * 查询所有用户信息\n    */\n   @GET(\"getAll\")\n   Response\u003cList\u003cUser\u003e\u003e getAll();\n\n}\n```\n\n### 熔断降级\n\n熔断降级默认关闭，当前支持`sentinel`和`resilience4j`两种实现。\n\n```yaml\nretrofit:\n   # 熔断降级配置\n   degrade:\n      # 熔断降级类型。默认none，表示不启用熔断降级\n      degrade-type: sentinel\n```\n\n#### Sentinel\n\n配置`degrade-type=sentinel`开启，然后在相关接口或者方法上声明`@SentinelDegrade`注解即可。\n\n记得手动引入`Sentinel`依赖：\n\n```xml\n\n\u003cdependency\u003e\n   \u003cgroupId\u003ecom.alibaba.csp\u003c/groupId\u003e\n   \u003cartifactId\u003esentinel-core\u003c/artifactId\u003e\n   \u003cversion\u003e1.6.3\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n此外，还支持全局`Sentinel`熔断降级：\n\n```yaml\nretrofit:\n  # 熔断降级配置\n  degrade:\n    # 熔断降级类型。默认none，表示不启用熔断降级\n    degrade-type: sentinel\n    # 全局sentinel降级配置\n    global-sentinel-degrade:\n      # 是否开启\n      enable: true\n      # ...其他sentinel全局配置\n```\n\n#### Resilience4j\n\n配置`degrade-type=resilience4j`开启。然后在相关接口或者方法上声明`@Resilience4jDegrade`即可。\n\n记得手动引入`Resilience4j`依赖：\n\n```xml\n\n\u003cdependency\u003e\n   \u003cgroupId\u003eio.github.resilience4j\u003c/groupId\u003e\n   \u003cartifactId\u003eresilience4j-circuitbreaker\u003c/artifactId\u003e\n   \u003cversion\u003e1.7.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n通过以下配置可开启全局resilience4j熔断降级：\n\n```yaml\nretrofit:\n   # 熔断降级配置\n   degrade:\n      # 熔断降级类型。默认none，表示不启用熔断降级\n      degrade-type: resilience4j\n      # 全局resilience4j降级配置\n      global-resilience4j-degrade:\n         # 是否开启\n         enable: true\n         # 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig，作为全局熔断配置\n         circuit-breaker-config-name: defaultCircuitBreakerConfig\n```\n\n熔断配置管理：\n\n实现`CircuitBreakerConfigRegistrar`接口，注册`CircuitBreakerConfig`。\n\n```java\n@Component\npublic class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar {\n   @Override\n   public void register(CircuitBreakerConfigRegistry registry) {\n   \n         // 替换默认的CircuitBreakerConfig\n         registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults());\n   \n         // 注册其它的CircuitBreakerConfig\n         registry.register(\"testCircuitBreakerConfig\", CircuitBreakerConfig.custom()\n                 .slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED)\n                 .failureRateThreshold(20)\n                 .minimumNumberOfCalls(5)\n                 .permittedNumberOfCallsInHalfOpenState(5)\n                 .build());\n   }\n}\n ```\n   \n通过`circuitBreakerConfigName`指定`CircuitBreakerConfig`。包括`retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name`或者`@Resilience4jDegrade.circuitBreakerConfigName`\n\n#### 扩展熔断降级\n\n如果用户需要使用其他的熔断降级实现，继承`BaseRetrofitDegrade`，并将其配置`Spring Bean`。\n\n#### 配置fallback或者fallbackFactory (可选)\n\n如果`@RetrofitClient`不设置`fallback`或者`fallbackFactory`，当触发熔断时，会直接抛出`RetrofitBlockException`异常。 用户可以通过设置`fallback`或者`fallbackFactory`来定制熔断时的方法返回值。\n\n\u003e 注意：`fallback`类必须是当前接口的实现类，`fallbackFactory`必须是`FallbackFactory\u003cT\u003e`\n\u003e 实现类，泛型参数类型为当前接口类型。另外，`fallback`和`fallbackFactory`实例必须配置成`Spring Bean`。\n\n`fallbackFactory`相对于`fallback`，主要差别在于能够感知每次熔断的异常原因(cause)，参考示例如下：\n\n```java\n@Slf4j\n@Service\npublic class HttpDegradeFallback implements HttpDegradeApi {\n\n   @Override\n   public Result\u003cInteger\u003e test() {\n      Result\u003cInteger\u003e fallback = new Result\u003c\u003e();\n      fallback.setCode(100)\n              .setMsg(\"fallback\")\n              .setBody(1000000);\n      return fallback;\n   }\n}\n```\n\n```java\n@Slf4j\n@Service\npublic class HttpDegradeFallbackFactory implements FallbackFactory\u003cHttpDegradeApi\u003e {\n\n   @Override\n   public HttpDegradeApi create(Throwable cause) {\n      log.error(\"触发熔断了! \", cause.getMessage(), cause);\n      return new HttpDegradeApi() {\n         @Override\n         public Result\u003cInteger\u003e test() {\n            Result\u003cInteger\u003e fallback = new Result\u003c\u003e();\n            fallback.setCode(100)\n                    .setMsg(\"fallback\")\n                    .setBody(1000000);\n            return fallback;\n         }\n      };\n   }\n}\n```\n\n### 错误解码器\n\n在`HTTP`发生请求错误(包括发生异常或者响应数据不符合预期)的时候，错误解码器可将`HTTP`相关信息解码到自定义异常中。你可以在`@RetrofitClient`注解的`errorDecoder()`\n指定当前接口的错误解码器，自定义错误解码器需要实现`ErrorDecoder`接口。 可以通过配置`retrofit.enable-error-decoder=false`配置关闭ErrorDecoder功能。\n\n### 微服务之间的HTTP调用\n\n#### 继承`ServiceInstanceChooser`\n\n用户可以自行实现`ServiceInstanceChooser`接口，完成服务实例的选取逻辑，并将其配置成`Spring Bean`。对于`Spring Cloud`\n应用，可以使用如下实现。\n\n```java\n@Service\npublic class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser {\n    \n   private LoadBalancerClient loadBalancerClient;\n\n   @Autowired\n   public SpringCloudServiceInstanceChooser(LoadBalancerClient loadBalancerClient) {\n      this.loadBalancerClient = loadBalancerClient;\n   }\n\n   /**\n    * Chooses a ServiceInstance URI from the LoadBalancer for the specified service.\n    *\n    * @param serviceId The service ID to look up the LoadBalancer.\n    * @return Return the uri of ServiceInstance\n    */\n   @Override\n   public URI choose(String serviceId) {\n      ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);\n      Assert.notNull(serviceInstance, \"can not found service instance! serviceId=\" + serviceId);\n      return serviceInstance.getUri();\n   }\n}\n```\n\n#### 指定`serviceId`和`path`\n\n```java\n@RetrofitClient(serviceId = \"user\", path = \"/api/user\")\npublic interface ChooserOkHttpUserService {\n\n   /**\n    * 根据id查询用户信息\n    */\n   @GET(\"getUser\")\n   User getUser(@Query(\"id\") Long id);\n}\n```\n\n### 自定义RetrofitClient注解\n\n有些时候，JAVA接口上的`@RetrofitClient`、`@Retry`、`@Logging`、`@Resilience4jDegrade`等注解上的默认值不符合业务需要。 此时一种方式是每个接口都修改对应注解属性，但是会导致很多接口都要做相同的逻辑，不够优雅。 另外一种方式就是自定义RetrofitClient注解，后续其他接口只需要使用自定义注解即可。\n\n比如下面代码定义了自定义注解`@MyRetrofitClient`：\n\n```java\n\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\n@Documented\n@Inherited\n@RetrofitClient(baseUrl = \"${test.baseUrl}\")\n@Logging(logLevel = LogLevel.WARN)\n@Retry(intervalMs = 200)\npublic @interface MyRetrofitClient {\n\n   @AliasFor(annotation = RetrofitClient.class, attribute = \"converterFactories\")\n   Class\u003c? extends Converter.Factory\u003e[] converterFactories() default {GsonConverterFactory.class};\n\n   @AliasFor(annotation = Logging.class, attribute = \"logStrategy\")\n   LogStrategy logStrategy() default LogStrategy.BODY;\n}\n```\n\n## 配置属性\n\n组件支持了多个可配置的属性，用来应对不同的业务场景。具体可支持的配置属性及默认值如下：\n\n```yaml\nretrofit:\n   # 全局转换器工厂\n   global-converter-factories:\n      - com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory\n      - retrofit2.converter.jackson.JacksonConverterFactory\n\n   # 全局日志打印配置\n   global-log:\n      # 启用日志打印\n      enable: true\n      # 全局日志打印级别\n      log-level: info\n      # 全局日志打印策略\n      log-strategy: basic\n      # 是否聚合打印请求日志\n      aggregate: true\n\n   # 全局重试配置\n   global-retry:\n      # 是否启用全局重试\n      enable: false\n      # 全局重试间隔时间\n      interval-ms: 100\n      # 全局最大重试次数\n      max-retries: 2\n      # 全局重试规则\n      retry-rules:\n         - response_status_not_2xx\n         - occur_io_exception\n\n   # 全局超时时间配置\n   global-timeout:\n      # 全局读取超时时间\n      read-timeout-ms: 10000\n      # 全局写入超时时间\n      write-timeout-ms: 10000\n      # 全局连接超时时间\n      connect-timeout-ms: 10000\n      # 全局完整调用超时时间\n      call-timeout-ms: 0\n\n  # 全局连接池配置\n   global-connection-pool:\n     # 最大空闲连接数\n     max-idle-connections: 5\n     keep-alive-duration-ms: 300_000\n   # 熔断降级配置\n   degrade:\n      # 熔断降级类型。默认none，表示不启用熔断降级\n      degrade-type: none\n      # 全局sentinel降级配置\n      global-sentinel-degrade:\n         # 是否开启\n         enable: false\n         # 各降级策略对应的阈值。平均响应时间(ms)，异常比例(0-1)，异常数量(1-N)\n         count: 1000\n         # 熔断时长，单位为 s\n         time-window: 5\n         # 降级策略（0：平均响应时间；1：异常比例；2：异常数量）\n         grade: 0\n\n      # 全局resilience4j降级配置\n      global-resilience4j-degrade:\n         # 是否开启\n         enable: false\n         # 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig，作为全局熔断配置\n         circuit-breaker-config-name: defaultCircuitBreakerConfig\n   # 自动设置PathMathInterceptor的scope为prototype\n   auto-set-prototype-scope-for-path-math-interceptor: true\n   # 是否开启ErrorDecoder功能\n   enable-error-decoder: true\n```\n绝大部分场景下，在Spring Boot配置文件（application.yml或者application.properties）中加上上述配置，即可自定义修改组件功能。\n\n**如果Spring Boot配置文件无法生效，可以手动配置RetrofitProperties Bean**，代码如下：\n```java\n@Bean\npublic RetrofitProperties retrofitProperties() {\n   RetrofitProperties retrofitProperties = new RetrofitProperties();\n   // 手动修改retrofitProperties各项配置值\n   return retrofitProperties;\n}\n```\n\n## 其他功能示例\n\n### form参数\n\n```java\n@FormUrlEncoded\n@POST(\"token/verify\")\nObject tokenVerify(@Field(\"source\") String source,@Field(\"signature\") String signature,@Field(\"token\") String token);\n\n\n@FormUrlEncoded\n@POST(\"message\")\nCompletableFuture\u003cObject\u003e sendMessage(@FieldMap Map\u003cString, Object\u003e param);\n```\n\n### 文件上传\n\n#### 创建MultipartBody.Part\n\n```java\n// 对文件名使用URLEncoder进行编码\npublic ResponseEntity importTerminology(MultipartFile file){\n     String fileName=URLEncoder.encode(Objects.requireNonNull(file.getOriginalFilename()),\"utf-8\");\n     okhttp3.RequestBody requestBody=okhttp3.RequestBody.create(MediaType.parse(\"multipart/form-data\"),file.getBytes());\n     MultipartBody.Part part=MultipartBody.Part.createFormData(\"file\",fileName,requestBody);\n     apiService.upload(part);\n     return ok().build();\n}\n```\n\n#### `HTTP`上传接口\n\n```java\n@POST(\"upload\")\n@Multipart\nVoid upload(@Part MultipartBody.Part file);\n```\n\n### 文件下载\n\n#### `HTTP`下载接口\n\n```java\n@RetrofitClient(baseUrl = \"https://img.ljcdn.com/hc-picture/\")\npublic interface DownloadApi {\n\n    @GET(\"{fileKey}\")\n    Response\u003cResponseBody\u003e download(@Path(\"fileKey\") String fileKey);\n}\n\n```\n\n#### `HTTP`下载使用\n\n```java\n@SpringBootTest(classes = {RetrofitBootApplication.class})\n@RunWith(SpringRunner.class)\npublic class DownloadTest {\n    @Autowired\n    DownloadApi downLoadApi;\n\n    @Test\n    public void download() throws Exception {\n        String fileKey = \"6302d742-ebc8-4649-95cf-62ccf57a1add\";\n        Response\u003cResponseBody\u003e response = downLoadApi.download(fileKey);\n        ResponseBody responseBody = response.body();\n        // 二进制流\n        InputStream is = responseBody.byteStream();\n\n        // 具体如何处理二进制流，由业务自行控制。这里以写入文件为例\n        File tempDirectory = new File(\"temp\");\n        if (!tempDirectory.exists()) {\n            tempDirectory.mkdir();\n        }\n        File file = new File(tempDirectory, UUID.randomUUID().toString());\n        if (!file.exists()) {\n            file.createNewFile();\n        }\n        FileOutputStream fos = new FileOutputStream(file);\n        byte[] b = new byte[1024];\n        int length;\n        while ((length = is.read(b)) \u003e 0) {\n            fos.write(b, 0, length);\n        }\n        is.close();\n        fos.close();\n    }\n}\n```\n\n### 动态URL\n\n使用`@url`注解可实现动态URL。此时，`baseUrl`配置任意合法url即可。例如： `http://github.com/` 。运行时只会根据`@Url`地址发起请求。\n\n\u003e 注意：`@url`必须放在方法参数的第一个位置，另外，`@GET`、`@POST`等注解上，不需要定义端点路径。\n\n```java\n @GET\n Map\u003cString, Object\u003e test3(@Url String url,@Query(\"name\") String name);\n```\n\n### `DELETE`请求添加请求体\n\n```java\n@HTTP(method = \"DELETE\", path = \"/user/delete\", hasBody = true)\n```\n\n### `GET`请求添加请求体\n\n`okhttp3`自身不支持`GET`请求添加请求体，源码如下：\n\n![image](https://user-images.githubusercontent.com/30620547/108949806-0a9f7780-76a0-11eb-9eb4-326d5d546e98.png)\n\n![image](https://user-images.githubusercontent.com/30620547/108949831-1ab75700-76a0-11eb-955c-95d324084580.png)\n\n作者给出了具体原因，可以参考: [issue](https://github.com/square/okhttp/issues/3154)\n\n但是，如果实在需要这么做，可以使用：`@HTTP(method = \"get\", path = \"/user/get\", hasBody = true)`，使用小写`get`绕过上述限制。\n\n\n## 反馈建议\n\n如有任何问题，欢迎提issue或者加QQ群反馈。\n\n群号：806714302\n\n![QQ群图片](https://github.com/LianjiaTech/retrofit-spring-boot-starter/blob/master/group.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flianjiatech%2Fretrofit-spring-boot-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flianjiatech%2Fretrofit-spring-boot-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flianjiatech%2Fretrofit-spring-boot-starter/lists"}