Integrating Retrofit with Spring Boot Using retrofit‑spring‑boot‑starter
This article introduces the retrofit‑spring‑boot‑starter library, shows how to add the Maven dependency, configure @RetrofitScan, define HTTP interfaces, inject them into services, and demonstrates advanced features such as annotation‑based interceptors, custom interceptors, connection‑pool management, logging, exception formatting, call adapters, converters, and global interceptors for Spring Boot projects.
OkHttp is an open‑source Java HTTP client from Square, and Retrofit is a higher‑level wrapper built on top of OkHttp. The retrofit‑spring‑boot‑starter provides quick integration of Retrofit with Spring Boot, simplifying HTTP API calls.
Adding the Dependency
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>Configuring @RetrofitScan
Apply @RetrofitScan to a @Configuration class or directly on the Spring Boot main class:
@SpringBootApplication
@RetrofitScan("com.github.lianjiatech.retrofit.spring.boot.test")
public class RetrofitTestApplication {
public static void main(String[] args) {
SpringApplication.run(RetrofitTestApplication.class, args);
}
}Defining an HTTP Interface
Mark the interface with @RetrofitClient and use standard Retrofit annotations:
@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
@GET("person")
Result
getPerson(@Query("id") Long id);
}Injecting and Using the Interface
@Service
public class TestService {
@Autowired
private HttpApi httpApi;
public void test() {
// invoke HTTP request via httpApi
}
}Annotation‑Based Interceptor
Implement a custom interceptor by extending BasePathMatchInterceptor and annotate the target interface method with @Intercept :
@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
getPerson(@Query("id") Long id);
@POST("savePerson")
Result
savePerson(@Body Person person);
}Custom Annotation @Sign
Create a custom annotation marked with @InterceptMark to add signing headers dynamically:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
String accessKeyId();
String accessKeySecret();
String[] include() default {"/**"};
String[] exclude() default {};
Class
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
getPerson(@Query("id") Long id);
@POST("savePerson")
Result
savePerson(@Body Person person);
}Connection‑Pool Management
Default pool: max-idle-connections=5 keep-alive-second=300 . Custom pools can be defined in application.yml and selected via 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
Five log levels (ERROR, WARN, INFO, DEBUG, TRACE) and four strategies (NONE, BASIC, HEADERS, BODY). The default interceptor is DefaultLoggingInterceptor , which delegates to OkHttp's HttpLoggingInterceptor . Custom log interceptors can be provided by extending BaseLoggingInterceptor :
retrofit:
logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptorHTTP Exception Message Formatter
Customize exception messages by implementing BaseHttpExceptionMessageFormatter and configuring it:
retrofit:
http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatterCallAdapter Factories
Retrofit can adapt Call<T> to various return types via CallAdapter factories. The starter provides BodyCallAdapterFactory (default) and ResponseCallAdapterFactory . Examples:
@GET("person")
Call
> getPersonCall(@Query("id") Long id);
@GET("person")
CompletableFuture
> getPersonCompletableFuture(@Query("id") Long id);
@GET("person")
Void getPersonVoid(@Query("id") Long id);
@GET("person")
Response
> getPersonResponse(@Query("id") Long id);
@GET("person")
Result
getPerson(@Query("id") Long id);Converters
Retrofit uses Converter factories to serialize request bodies and deserialize responses. Supported converters include Gson, Jackson (default), Moshi, Protobuf, Wire, Simple XML, etc. Custom converters can be added by providing a bean of type Converter.Factory .
Global Interceptor (BaseGlobalInterceptor)
Implement a global interceptor to apply logic to every HTTP request, e.g., 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);
}
}Conclusion
The retrofit‑spring‑boot‑starter offers an elegant way to use Retrofit in Spring Boot applications, covering dependency setup, interface definition, injection, annotation‑based interceptors, connection‑pool configuration, logging, exception formatting, call adapters, converters, and global interceptors. For more details, refer to the official documentation and GitHub repository.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.