Unlock Simple HTTP Calls in Spring Boot with retrofit-spring-boot-starter

This guide introduces retrofit-spring-boot-starter, a lightweight HTTP client for Spring Boot that simplifies request management, offers rich features such as custom OkHttp injection, annotation‑based interceptors, logging, retry, circuit‑breaker, and detailed configuration, with full code examples and usage patterns.

Programmer DD
Programmer DD
Programmer DD
Unlock Simple HTTP Calls in Spring Boot with retrofit-spring-boot-starter

Introduction

Retrofit is a type‑safe HTTP client for Android and Java. Spring Boot does not provide native integration, so retrofit-spring-boot-starter was created to bridge the gap, offering a lightweight and feature‑rich HTTP client for Spring Boot projects.

Features

Custom OkHttpClient injection

Annotation‑based interceptors

Connection pool management

Logging with configurable levels and strategies

Request retry with customizable rules

Error decoder support

Global and network interceptors

Circuit‑breaker (Sentinel) with annotation‑based rules

Microservice HTTP calls via service discovery

Flexible call adapters and data converters

Quick Start

Add the starter as a Maven dependency:

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

Define a Retrofit interface and annotate it with @RetrofitClient:

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

Inject the interface into a Spring service:

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

HTTP Annotations

The starter uses the native Retrofit annotations such as @GET, @POST, @PUT, @DELETE, @Header, @Query, @Path, @Body, etc. Refer to the official Retrofit documentation for details.

Annotation‑Based Interceptors

Implement a class extending BasePathMatchInterceptor and annotate the Retrofit interface with @Intercept to apply the interceptor to specific URL patterns.

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

Define a custom annotation marked with @InterceptMark (e.g., @Sign) and implement a corresponding interceptor to add dynamic headers such as access keys.

@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 connection pools in application.yml and select a pool per interface using the 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 { ... }

Logging

Global logging can be toggled with retrofit.enableLog. Per‑interface logging is controlled by enableLog, logLevel (ERROR, WARN, INFO, DEBUG, TRACE) and logStrategy (NONE, BASIC, HEADERS, BODY). The default interceptor is DefaultLoggingInterceptor based on OkHttp’s HttpLoggingInterceptor.

retrofit:
  logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor

Retry

Apply @Retry on an interface or method to enable automatic retries. Configurable parameters include maxRetries, intervalMs, and retryRules (e.g., RESPONSE_STATUS_NOT_2XX, OCCUR_IO_EXCEPTION, OCCUR_EXCEPTION).

retrofit:
  retry-interceptor: com.github.lianjiatech.retrofit.spring.boot.retry.DefaultRetryInterceptor

Error Decoder

Implement ErrorDecoder and reference it via the errorDecoder() attribute of @RetrofitClient to translate HTTP errors into custom exceptions.

public interface ErrorDecoder {
    default RuntimeException invalidRespDecode(Request request, Response response) { ... }
    default RuntimeException ioExceptionDecode(Request request, IOException cause) { ... }
    default RuntimeException exceptionDecode(Request request, Exception cause) { ... }
}

Global Interceptors

Define beans extending BaseGlobalInterceptor or implementing NetworkInterceptor to apply logic to every HTTP request, such as adding a source header.

@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

Enable circuit breaking with Sentinel by setting:

retrofit:
  enable-degrade: true
  degrade-type: sentinel
  resource-name-parser: com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser

Configure rules with @Degrade (count, timeWindow, strategy) on interfaces or methods, and optionally provide fallback or fallbackFactory beans for graceful degradation.

Microservice Calls

Integrate with service discovery by providing a ServiceInstanceChooser bean (e.g., Spring Cloud’s SpringCloudServiceInstanceChooser) and using @RetrofitClient(serviceId = "${service.id}", path = "/api") to call other services.

@Bean
public ServiceInstanceChooser serviceInstanceChooser(LoadBalancerClient loadBalancerClient) {
    return new SpringCloudServiceInstanceChooser(loadBalancerClient);
}

Call Adapters and Converters

The starter registers two call‑adapter factories by default: BodyCallAdapterFactory (maps response bodies to method return types) and ResponseCallAdapterFactory (returns Response<T>). These can be disabled via retrofit.enable-body-call-adapter or retrofit.enable-response-call-adapter. Global factories are configurable:

retrofit:
  global-call-adapter-factories:
    - com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
    - com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory

Data conversion uses Converter.Factory implementations (Jackson, Gson, Moshi, etc.). The default is Jackson, configurable globally:

retrofit:
  global-converter-factories:
    - retrofit2.converter.jackson.JacksonConverterFactory

Interface‑level converters can be set with the converterFactories() attribute.

Conclusion

retrofit-spring-boot-starter

provides a production‑ready, lightweight HTTP client for Spring Boot, covering request management, extensible interceptors, logging, retry, circuit breaking, and seamless microservice integration. It has been stable in production for over a year and is ready for adoption in new projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaMicroservicesSpring BootInterceptorcircuit breakerRetrofitHTTP client
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.