# retrofit-spring-boot-starter
**Repository Path**: lianjiatech/retrofit-spring-boot-starter
## Basic Information
- **Project Name**: retrofit-spring-boot-starter
- **Description**: A spring-boot starter for retrofit, supports rapid integration and feature enhancements.(适用于retrofit的spring-boot启动器,支持快速集成和功能增强)
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 456
- **Forks**: 125
- **Created**: 2020-11-25
- **Last Updated**: 2025-09-23
## Categories & Tags
**Categories**: spring-boot-ext
**Tags**: None
## README
# retrofit-spring-boot-starter
[](https://www.apache.org/licenses/LICENSE-2.0.html)

[](https://docs.oracle.com/javase/8/docs/index.html)
[](https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/htmlsingle/)
[](https://deepwiki.com/LianjiaTech/retrofit-spring-boot-starter)
[中文文档](https://github.com/LianjiaTech/retrofit-spring-boot-starter/)
[retrofit](https://square.github.io/retrofit/) enables the conversion of HTTP APIs into Java interfaces. This component deeply integrates Retrofit with Spring Boot and supports various practical feature enhancements.
- **For Spring Boot 3.x projects, use retrofit-spring-boot-starter 3.x**
- **For Spring Boot 1.x/2.x projects, use [retrofit-spring-boot-starter 2.x](https://github.com/LianjiaTech/retrofit-spring-boot-starter/tree/2.x)**, which supports Spring Boot 1.4.2 and above.
> 🚀 The project is continuously optimized and iterated. Contributions via ISSUES and PRs are welcome! Please consider giving a star⭐️—your support motivates our ongoing updates!
GitHub project link: [https://github.com/LianjiaTech/retrofit-spring-boot-starter](https://github.com/LianjiaTech/retrofit-spring-boot-starter)
Gitee project link: [https://gitee.com/lianjiatech/retrofit-spring-boot-starter](https://gitee.com/lianjiatech/retrofit-spring-boot-starter)
## Quick Start
### Add Dependency
```xml
com.github.lianjiatechretrofit-spring-boot-starter3.2.0
```
For most Spring Boot projects, adding the dependency is sufficient. If the component fails to work after dependency injection, try the following solutions:
#### Manual Auto-configuration Import
In some cases, `RetrofitAutoConfiguration` may not load properly. Attempt manual configuration import with the following code:
```java
@Configuration
@ImportAutoConfiguration({RetrofitAutoConfiguration.class})
public class SpringBootAutoConfigBridge {
}
```
If the project still uses Spring XML configuration files, add the Spring Boot auto-configuration class to the XML file:
```xml
```
### Define HTTP Java Interface
**Interfaces must be annotated with `@RetrofitClient`!**
```java
@RetrofitClient(baseUrl = "http://localhost:8080/api/user/")
public interface UserService {
/**
* Query username by ID
*/
@POST("getName")
String getName(@Query("id") Long id);
}
```
> Note: **Avoid using leading slashes (`/`) in method request paths**. For Retrofit, if `baseUrl = http://localhost:8080/api/test/`:
> - A method path `person` results in the full URL: `http://localhost:8080/api/test/person`.
> - A method path `/person` results in the full URL: `http://localhost:8080/person`.
### Injection and Usage
**Inject the interface into other Services for use!**
```java
@Service
public class BusinessService {
@Autowired
private UserService userService;
public void doBusiness() {
// Call userService methods
}
}
```
**By default, `RetrofitClient` interfaces are automatically registered via Spring Boot's component scanning path**. Alternatively, specify a custom scan path using `@RetrofitScan` on a configuration class.
## HTTP Request Annotations
HTTP request-related annotations use Retrofit's native annotations. A brief overview is provided below:
| Annotation Category | Supported Annotations |
|---------------------|-----------------------|
| Request Methods | `@GET`, `@HEAD`, `@POST`, `@PUT`, `@DELETE`, `@OPTIONS`, `@HTTP` |
| Request Headers | `@Header`, `@HeaderMap`, `@Headers` |
| Query Parameters | `@Query`, `@QueryMap`, `@QueryName` |
| Path Parameters | `@Path` |
| Form-Encoded Params | `@Field`, `@FieldMap`, `@FormUrlEncoded` |
| Request Body | `@Body` |
| File Upload | `@Multipart`, `@Part`, `@PartMap` |
| URL Parameters | `@Url` |
> For details, refer to the official documentation: [Retrofit Official Documentation](https://square.github.io/retrofit/)
## Feature Highlights
- [x] [Automatic Adaptation of HTTP Responses to Java Return Types](#Automatic-Adaptation-of-HTTP-Responses-to-Java-Return-Types)
- [x] [Custom Data Converters](#Custom-Data-Converters)
- [x] [Custom OkHttpClient](#Custom-OkHttpClient)
- [x] [Logging](#Logging)
- [x] [Request Retries](#Request-Retries)
- [x] [Global Application Interceptors](#Global-Application-Interceptors)
- [x] [Global Network Interceptors](#Global-Network-Interceptors)
- [x] [URL Path Matching Interceptors](#URL-Path-Matching-Interceptors)
- [x] [Custom Interceptor Annotations](#Custom-Interceptor-Annotations)
- [x] [Circuit Breaking](#Circuit-Breaking)
- [x] [Error Decoding](#Error-Decoding)
- [x] [HTTP Calls Between Microservices](#HTTP-Calls-Between-Microservices)
- [x] [Custom RetrofitClient Annotations](#Custom-RetrofitClient-Annotations)
- [x] [Configuration Properties](#Configuration-Properties)
### Automatic Adaptation of HTTP Responses to Java Return Types
This component automatically adapts HTTP responses to the return types defined in Java interfaces. The following return types are supported:
- `Call`: Returns the `Call` object directly without adaptation.
- `String`: Adapts the `Response Body` to a `String`.
- Primitive Types (`Long`/`Integer`/`Boolean`/`Float`/`Double`): Adapts the `Response Body` to the specified primitive type.
- `CompletableFuture`: Adapts the `Response Body` to a `CompletableFuture`.
- `Void`: Use for requests where the return type is irrelevant.
- `Response`: Adapts the response to a `Response` object.
- `Mono`: Reactive return type for Project Reactor.
- `Single`: Reactive return type for RxJava (supports RxJava2/RxJava3).
- `Completable`: RxJava reactive return type for HTTP requests with no response body (supports RxJava2/RxJava3).
- Custom POJOs: Adapts the `Response Body` to the specified POJO.
#### Adaptation Implementation
Retrofit uses `CallAdapterFactory` to adapt `Call` objects to method return types. This component extends `CallAdapterFactory` with the following implementations:
- `BodyCallAdapterFactory`:
- Executes HTTP requests synchronously and adapts the response body to the method's return type.
- Supports all return types with the lowest priority.
- `ResponseCallAdapterFactory`:
- Executes HTTP requests synchronously and adapts the response to `Retrofit.Response`.
- Only applicable when the return type is `Retrofit.Response`.
- Reactive Programming `CallAdapterFactory`:
- Supports reactive types like `Mono`, `Single`, and `Completable`.
Custom adaptations can be implemented by extending `CallAdapter.Factory`. Configure global call adapter factories via `retrofit.global-call-adapter-factories`:
```yaml
retrofit:
# Global adapter factories (component-extended CallAdapterFactories are pre-included; do not reconfigure here)
global-call-adapter-factories:
# ...
```
For individual interfaces, specify `CallAdapter.Factory` using `@RetrofitClient.callAdapterFactories`.
### Custom Data Converters
Retrofit uses `Converter` to convert `@Body`-annotated objects to HTTP request bodies and response bodies to Java objects. Supported converters include:
- [Gson](https://github.com/google/gson): `com.squareup.Retrofit:converter-gson`
- [Jackson](https://github.com/FasterXML/jackson): `com.squareup.Retrofit:converter-jackson`
- [Moshi](https://github.com/square/moshi/): `com.squareup.Retrofit:converter-moshi`
- [Protobuf](https://developers.google.com/protocol-buffers/): `com.squareup.Retrofit:converter-protobuf`
- [Wire](https://github.com/square/wire): `com.squareup.Retrofit:converter-wire`
- [Simple XML](http://simple.sourceforge.net/): `com.squareup.Retrofit:converter-simplexml`
- [JAXB](https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html): `com.squareup.retrofit2:converter-jaxb`
- FastJson: `com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory`
Configure global `Converter.Factory` via `retrofit.global-converter-factories` (default: `retrofit2.converter.jackson.JacksonConverterFactory`).
To customize Jackson configuration, override the `JacksonConverterFactory` bean:
```yaml
retrofit:
# Global converter factories
global-converter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
```
For individual interfaces, specify `Converter.Factory` using `@RetrofitClient.converterFactories`.
### Custom OkHttpClient
Timeout configurations for `OkHttpClient` can be set via the configuration file or `@RetrofitClient`. For advanced configurations, customize `OkHttpClient` as follows:
#### Implement `SourceOkHttpClientRegistrar`
```java
@Component
public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar {
@Override
public void register(SourceOkHttpClientRegistry registry) {
// Register customOkHttpClient with 1-second timeouts
registry.register("customOkHttpClient", new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(1))
.writeTimeout(Duration.ofSeconds(1))
.readTimeout(Duration.ofSeconds(1))
.addInterceptor(chain -> chain.proceed(chain.request()))
.build());
}
}
```
#### Specify `OkHttpClient` in `@RetrofitClient`
```java
@RetrofitClient(baseUrl = "${test.baseUrl}", sourceOkHttpClient = "customOkHttpClient")
public interface CustomOkHttpUserService {
/**
* Query user info by ID
*/
@GET("getUser")
User getUser(@Query("id") Long id);
}
```
### Logging
The component supports global and declarative logging.
#### Global Logging
Global logging is enabled by default with the following configuration:
```yaml
retrofit:
# Global logging configuration
global-log:
# Enable logging
enable: true
# Global log level
log-level: info
# Global log strategy
log-strategy: basic
# Aggregate request logs
aggregate: true
# Logger name (default: fully qualified class name of LoggingInterceptor)
logName: com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor
redact-headers:
```
Logging strategies:
1. `NONE`: No logs.
2. `BASIC`: Logs request and response lines.
3. `HEADERS`: Logs request/response lines and headers.
4. `BODY`: Logs request/response lines, headers, and bodies (if present).
#### Declarative Logging
Use the `@Logging` annotation on interfaces or methods to enable logging for specific requests.
#### Custom Logging Extensions
Extend `LoggingInterceptor` and register it as a Spring bean to customize logging behavior.
### Request Retries
The component supports global and declarative retries.
#### Global Retries
Global retries are disabled by default:
```yaml
retrofit:
# Global retry configuration
global-retry:
# Enable global retries
enable: false
# Retry interval (ms)
interval-ms: 100
# Max retries
max-retries: 2
# Retry rules
retry-rules:
- response_status_not_2xx
- occur_io_exception
```
Retry rules:
1. `RESPONSE_STATUS_NOT_2XX`: Retry on non-2xx status codes.
2. `OCCUR_IO_EXCEPTION`: Retry on IO exceptions.
3. `OCCUR_EXCEPTION`: Retry on any exception.
#### Declarative Retries
Use the `@Retry` annotation on interfaces or methods for selective retries.
#### Custom Retry Extensions
Extend `RetryInterceptor` and register it as a Spring bean to customize retry behavior.
### Global Application Interceptors
Implement `GlobalInterceptor` and register it as a Spring bean to apply unified request processing:
```java
@Component
public class MyGlobalInterceptor implements GlobalInterceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// Add "global" header to responses
return response.newBuilder().header("global", "true").build();
}
}
```
### Global Network Interceptors
Implement `NetworkInterceptor` and register it as a Spring bean.
### URL Path Matching Interceptors
Use path-matching interceptors to apply special logic to specific HTTP endpoints:
#### Extend `BasePathMatchInterceptor`
```java
@Component
public class PathMatchInterceptor extends BasePathMatchInterceptor {
@Override
protected Response doIntercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// Add "path.match" header to responses
return response.newBuilder().header("path.match", "true").build();
}
}
```
#### Annotate Interfaces with `@Intercept`
```java
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Intercept(handler = PathMatchInterceptor.class, include = {"/api/user/**"}, exclude = "/api/user/getUser")
// Add multiple @Intercept annotations for multiple interceptors
public interface InterceptorUserService {
/**
* Query username by ID
*/
@POST("getName")
Response getName(@Query("id") Long id);
/**
* Query user info by ID
*/
@GET("getUser")
Response getUser(@Query("id") Long id);
}
```
The `@Intercept` annotation above applies `PathMatchInterceptor` to requests under `/api/user/**` (excluding `/api/user/getUser`).
### Custom Interceptor Annotations
Define custom annotations to inject dynamic parameters into interceptors:
1. Create an annotation marked with `@InterceptMark`, including `include`, `exclude`, and `handler` fields.
2. Extend `BasePathMatchInterceptor` to implement the interceptor.
3. Apply the custom annotation to interfaces.
**Example: Add dynamic `accessKeyId` and `accessKeySecret` headers**
#### Define `@Sign` Annotation
```java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
String accessKeyId();
String accessKeySecret();
String[] include() default {"/**"};
String[] exclude() default {};
Class extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}
```
#### Implement `SignInterceptor`
```java
@Component
@Setter
public class SignInterceptor extends BasePathMatchInterceptor {
private String accessKeyId;
private String accessKeySecret;
@Override
public Response doIntercept(Chain chain) throws IOException {
Request request = chain.request();
Request newReq = request.newBuilder()
.addHeader("accessKeyId", accessKeyId)
.addHeader("accessKeySecret", accessKeySecret)
.build();
Response response = chain.proceed(newReq);
return response.newBuilder()
.addHeader("accessKeyId", accessKeyId)
.addHeader("accessKeySecret", accessKeySecret)
.build();
}
}
```
> Note: Provide setter methods for `accessKeyId` and `accessKeySecret`.
#### Apply `@Sign` to Interfaces
```java
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", include = "/api/user/getAll")
public interface InterceptorUserService {
/**
* Query all users
*/
@GET("getAll")
Response> getAll();
}
```
### Circuit Breaking
Circuit breaking is disabled by default, with support for `sentinel` and `resilience4j`:
```yaml
retrofit:
# Circuit breaking configuration
degrade:
# Circuit breaker type (default: none)
degrade-type: sentinel
```
#### Sentinel
Set `degrade-type: sentinel` and use `@SentinelDegrade` on interfaces/methods. Add the Sentinel dependency:
```xml
com.alibaba.cspsentinel-core1.6.3
```
Enable global Sentinel circuit breaking:
```yaml
retrofit:
degrade:
degrade-type: sentinel
global-sentinel-degrade:
enable: true
# ... other Sentinel configurations
```
#### Resilience4j
Set `degrade-type: resilience4j` and use `@Resilience4jDegrade` on interfaces/methods. Add the Resilience4j dependency:
```xml
io.github.resilience4jresilience4j-circuitbreaker1.7.1
```
Enable global Resilience4j circuit breaking:
```yaml
retrofit:
degrade:
degrade-type: resilience4j
global-resilience4j-degrade:
enable: true
circuit-breaker-config-name: defaultCircuitBreakerConfig
```
**Circuit Breaker Configuration Management**:
Implement `CircuitBreakerConfigRegistrar` to register `CircuitBreakerConfig`:
```java
@Component
public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar {
@Override
public void register(CircuitBreakerConfigRegistry registry) {
// Override default CircuitBreakerConfig
registry.register(Constants.DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreakerConfig.ofDefaults());
// Register custom configurations
registry.register("testCircuitBreakerConfig", CircuitBreakerConfig.custom()
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.TIME_BASED)
.failureRateThreshold(20)
.minimumNumberOfCalls(5)
.permittedNumberOfCallsInHalfOpenState(5)
.build());
}
}
```
Specify `CircuitBreakerConfig` via `circuitBreakerConfigName` in global settings or `@Resilience4jDegrade`.
### Error Decoding
Customize error handling by implementing `ErrorDecoder` and specifying it via `@RetrofitClient.errorDecoder()`. Disable with `retrofit.enable-error-decoder=false`.
### HTTP Calls Between Microservices
#### Extend `ServiceInstanceChooser`
Implement `ServiceInstanceChooser` to resolve service instances (example for Spring Cloud):
```java
@Service
public class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser {
private final LoadBalancerClient loadBalancerClient;
@Autowired
public SpringCloudServiceInstanceChooser(LoadBalancerClient loadBalancerClient) {
this.loadBalancerClient = loadBalancerClient;
}
@Override
public URI choose(String serviceId) {
ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);
Assert.notNull(serviceInstance, "Service instance not found! serviceId=" + serviceId);
return serviceInstance.getUri();
}
}
```
#### Specify `serviceId` and `path`
```java
@RetrofitClient(serviceId = "user", path = "/api/user")
public interface ChooserOkHttpUserService {
/**
* Query user info by ID
*/
@GET("getUser")
User getUser(@Query("id") Long id);
}
```
### Custom RetrofitClient Annotations
Combine multiple annotations into a custom annotation for reusability:
```java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Logging(logLevel = LogLevel.WARN)
@Retry(intervalMs = 200)
public @interface MyRetrofitClient {
@AliasFor(annotation = RetrofitClient.class, attribute = "converterFactories")
Class extends Converter.Factory>[] converterFactories() default {GsonConverterFactory.class};
@AliasFor(annotation = Logging.class, attribute = "logStrategy")
LogStrategy logStrategy() default LogStrategy.BODY;
}
```
## Configuration Properties
Customize component behavior via `application.yml` or `application.properties`:
```yaml
retrofit:
# Global converter factories
global-converter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
# Global logging
global-log:
enable: true
log-level: info
log-strategy: basic
aggregate: true
# Global retries
global-retry:
enable: false
interval-ms: 100
max-retries: 2
retry-rules:
- response_status_not_2xx
- occur_io_exception
# Global timeouts (ms)
global-timeout:
read-timeout-ms: 10000
write-timeout-ms: 10000
connect-timeout-ms: 10000
call-timeout-ms: 0
# Circuit breaking
degrade:
degrade-type: none
global-sentinel-degrade:
enable: false
count: 1000
time-window: 5
grade: 0
global-resilience4j-degrade:
enable: false
circuit-breaker-config-name: defaultCircuitBreakerConfig
auto-set-prototype-scope-for-path-math-interceptor: true
enable-error-decoder: true
```
**Manual `RetrofitProperties` Configuration** (if YAML properties fail):
```java
@Bean
public RetrofitProperties retrofitProperties() {
RetrofitProperties properties = new RetrofitProperties();
// Customize properties
return properties;
}
```
## Additional Examples
### Form Parameters
```java
@FormUrlEncoded
@POST("token/verify")
Object tokenVerify(@Field("source") String source, @Field("signature") String signature, @Field("token") String token);
@FormUrlEncoded
@POST("message")
CompletableFuture