retrofit-spring-boot-starter: A Lightweight HTTP Client Framework for Spring Boot

The retrofit-spring-boot-starter library provides a Spring Boot‑compatible, type‑safe HTTP client built on Retrofit, offering easy integration, customizable OkHttpClient injection, annotation‑based interceptors, connection‑pool management, logging, retry, error decoding, circuit‑breaker support, and flexible call adapters and converters for modern Java backend development.

Top Architect
Top Architect
Top Architect
retrofit-spring-boot-starter: A Lightweight HTTP Client Framework for Spring Boot

In Spring Boot projects, using okhttp, httpClient or RestTemplate for HTTP calls can be cumbersome and hard to manage centrally. The retrofit-spring-boot-starter offers a lightweight, type‑safe HTTP client based on Retrofit that integrates seamlessly with Spring Boot, simplifying request handling and providing many enhancements. The current version is 2.2.2.

Retrofit is a type‑safe HTTP client for Android and Java that supports interface‑based request definitions. Since Retrofit does not natively support Spring Boot, this starter bridges the gap, enabling rapid integration and adding features such as custom OkHttpClient injection, annotation‑driven interceptors, connection‑pool management, logging, retry, error decoding, global interceptors, circuit‑breaker (Sentinel) support, and micro‑service HTTP calls.

Key Features

Custom OkHttpClient injection

Annotation‑based interceptors

Connection‑pool management

Logging

Request retry

Error decoder

Global interceptor

Circuit‑breaker degradation

HTTP calls between micro‑services

Call adapters and data converters

Quick Start

Dependency

<dependency>
    <groupId>com.github.lianjiatech</groupId>
    <artifactId>retrofit-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>

Define HTTP Interface

The interface must be annotated with @RetrofitClient. HTTP method annotations follow the official Retrofit documentation.

@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);
}

Inject and Use

@Service
public class TestService {
    @Autowired
    private HttpApi httpApi;
    public void test() {
        // call httpApi methods here
    }
}

HTTP Annotation Reference

All HTTP request annotations are the native Retrofit annotations; refer to the Retrofit documentation for details.

Configuration

Various properties can be set in application.yml to control logging, connection pools, retry, error decoding, and circuit‑breaker behavior.

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
  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

Advanced Features

Custom OkHttpClient Injection

Define a static method returning OkHttpClient.Builder and annotate it with @OkHttpClientBuilder inside the Retrofit interface.

@RetrofitClient(baseUrl = "http://ke.com")
public interface HttpApi3 {
    @OkHttpClientBuilder
    static OkHttpClient.Builder okhttpClientBuilder() {
        return new OkHttpClient.Builder()
            .connectTimeout(1, TimeUnit.SECONDS)
            .readTimeout(1, TimeUnit.SECONDS)
            .writeTimeout(1, TimeUnit.SECONDS);
    }
    @GET("person")
    Result<Person> getPerson(@Url String url, @Query("id") Long id);
}

Annotation‑Based Interceptor

Implement BasePathMatchInterceptor and annotate the interface with @Intercept to apply URL‑based interception.

@Component
public class TimeStampInterceptor extends BasePathMatchInterceptor {
    @Override
    public Response doIntercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl url = request.url();
        long timestamp = System.currentTimeMillis();
        HttpUrl newUrl = url.newBuilder()
            .addQueryParameter("timestamp", String.valueOf(timestamp))
            .build();
        Request newRequest = request.newBuilder().url(newUrl).build();
        return chain.proceed(newRequest);
    }
}
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Intercept(handler = TimeStampInterceptor.class, include = {"/api/**"}, exclude = "/api/test/savePerson")
public interface HttpApi {
    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);
    @POST("savePerson")
    Result<Person> savePerson(@Body Person person);
}

Custom Intercept Annotation (@Sign)

Define a custom annotation marked with @InterceptMark that includes include(), exclude(), and handler(). Implement the handler to add signature headers.

@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;
}
@Component
public class SignInterceptor extends BasePathMatchInterceptor {
    private String accessKeyId;
    private String accessKeySecret;
    public void setAccessKeyId(String accessKeyId) { this.accessKeyId = accessKeyId; }
    public void setAccessKeySecret(String accessKeySecret) { this.accessKeySecret = accessKeySecret; }
    @Override
    public Response doIntercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request newReq = request.newBuilder()
            .addHeader("accessKeyId", accessKeyId)
            .addHeader("accessKeySecret", accessKeySecret)
            .build();
        return chain.proceed(newReq);
    }
}
@RetrofitClient(baseUrl = "${test.baseUrl}")
@Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {"/api/test/person"})
public interface HttpApi {
    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);
    @POST("savePerson")
    Result<Person> savePerson(@Body Person person);
}

Connection Pool Management

Define multiple pools in configuration and select a pool per interface via poolName attribute.

retrofit:
  pool:
    test1:
      max-idle-connections: 3
      keep-alive-second: 100
    test2:
      max-idle-connections: 5
      keep-alive-second: 50
@RetrofitClient(baseUrl = "${test.baseUrl}", poolName = "test1")
public interface HttpApi {
    @GET("person")
    Result<Person> getPerson(@Query("id") Long id);
}

Logging

Enable global or per‑interface logging via retrofit.enableLog and configure level (ERROR, WARN, INFO, DEBUG, TRACE) and strategy (NONE, BASIC, HEADERS, BODY).

Retry

Apply @Retry to enable automatic retry with configurable max retries, interval, and rules (status not 2xx, IO exception, any exception).

Error Decoder

Implement ErrorDecoder to translate HTTP errors or exceptions into custom runtime exceptions.

Global Interceptor

Implement BaseGlobalInterceptor and register as a Spring bean to apply headers or other logic to all outgoing requests.

@Component
public class SourceInterceptor extends BaseGlobalInterceptor {
    @Override
    public Response doIntercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request newReq = request.newBuilder()
            .addHeader("source", "test")
            .build();
        return chain.proceed(newReq);
    }
}

Circuit‑Breaker (Sentinel)

Enable degradation with enable-degrade: true, set degrade-type: sentinel, and optionally configure @Degrade on interfaces or methods, or provide fallback / fallbackFactory implementations.

Micro‑service Calls

Implement ServiceInstanceChooser (e.g., SpringCloudServiceInstanceChooser) and use

@RetrofitClient(serviceId = "${service.id}", path = "/m/count")

to call other services.

Call Adapters and Converters

The starter registers BodyCallAdapterFactory and ResponseCallAdapterFactory globally, allowing return types such as Call<T>, CompletableFuture<T>, Void, Response<T>, or any POJO. Global converter factories can be set (default Jackson) and overridden per interface.

Overall, retrofit-spring-boot-starter provides a comprehensive, configurable, and Spring‑friendly HTTP client solution for modern Java backend development.

microservicesRetrofithttp-clientspring-bootcircuit-breaker
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.