Source: https://juejin.cn/post/6898485806587969544Recommended programming resource site for programmers:http://cxyroad.comSide hustle earning column:https://xbt100.topLatest activation method for IDEA in 2024Reply in the backend:activation codeCSDN no-loginCopy codePlugin download:CSDN copy pluginBelow is the main content.
Using <span>SpringBoot</span> to directly send <span>HTTP</span> requests with <span>okhttp</span>, <span>httpClient</span>, or <span>RestTemplate</span> is cumbersome and inconvenient for unified management. Therefore, I recommend a lightweight HTTP client framework suitable for <span>SpringBoot</span> projects: <span>retrofit-spring-boot-starter</span>, which is very simple and convenient to use while providing many functional enhancements. The project has currently been updated to version <span>2.2.2</span> and will continue to be iteratively optimized.
GitHub project address: github.com/LianjiaTech
Gitee project address: gitee.com/lianjiatech
Introduction
<span>Retrofit</span> is a type-safe HTTP client for <span>Android</span> and <span>Java</span>, with its biggest feature being its support for initiating HTTP requests via interfaces. However, <span>spring-boot</span> is the most widely used Java development framework, and the official <span>Retrofit</span> does not support quick integration with the <span>spring-boot</span> framework, which is why we developed <span>retrofit-spring-boot-starter</span>.
<span>retrofit-spring-boot-starter</span> achieves quick integration of <span>Retrofit</span> with the <span>spring-boot</span> framework and supports many functional enhancements, greatly simplifying development.
Features
- Custom injection of OkHttpClient
- Annotation-based interceptors
- Connection pool management
- Logging
- Request retries
- Error decoders
- Global interceptors
- Circuit breaker and degradation
- HTTP calls between microservices
- Call adapters
- Data converters
Quick Start
Include Dependency
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
Copy code
Define HTTP Interface
The interface must be marked with the <span>@RetrofitClient</span> annotation! For HTTP-related annotations, please refer to the official documentation: Retrofit official documentation.
@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
}
Copy code
Inject and Use
Simply inject the interface into other services to use it!
@Service
public class TestService {
@Autowired
private HttpApi httpApi;
public void test() {
// Initiate HTTP request through httpApi
}
}
Copy code
HTTP Request Related Annotations
<span>HTTP</span> request related annotations all use the <span>retrofit</span> native annotations. For detailed information, please refer to the official documentation: Retrofit official documentation, below is a brief explanation.
| Annotation Category | Supported Annotations |
|---|---|
| Request Methods | <span>@GET</span><span>@HEAD</span><span>@POST</span><span>@PUT</span><span>@DELETE</span><span>@OPTIONS</span> |
| Request Headers | <span>@Header</span><span>@HeaderMap</span><span>@Headers</span> |
| Query Parameters | <span>@Query</span><span>@QueryMap</span><span>@QueryName</span> |
| Path Parameters | <span>@Path</span> |
| Form-encoded Parameters | <span>@Field</span><span>@FieldMap</span><span>@FormUrlEncoded</span> |
| File Upload | <span>@Multipart</span><span>@Part</span><span>@PartMap</span> |
| URL Parameters | <span>@Url</span> |
Configuration Item Description
<span>retrofit-spring-boot-starter</span> supports multiple configurable properties to handle different business scenarios. You can modify them as needed, with specific descriptions as follows:
| Configuration | Default Value | Description |
|---|---|---|
| enable-log | true | Enable logging |
| logging-interceptor | DefaultLoggingInterceptor | Logging interceptor |
| pool | Connection pool configuration | |
| disable-void-return-type | false | Disable java.lang.Void return type |
| retry-interceptor | DefaultRetryInterceptor | Request retry interceptor |
| global-converter-factories | JacksonConverterFactory | Global converter factory |
| global-call-adapter-factories | BodyCallAdapterFactory, ResponseCallAdapterFactory | Global call adapter factory |
| enable-degrade | false | Whether to enable circuit breaker degradation |
| degrade-type | sentinel | Circuit breaker degradation implementation method (currently only supports Sentinel) |
| resource-name-parser | DefaultResourceNameParser | Circuit breaker resource name parser, used to parse resource names |
<span>yml</span> configuration method:
retrofit:
enable-response-call-adapter:true
# Enable logging
enable-log:true
# Connection pool configuration
pool:
test1:
max-idle-connections:3
keep-alive-second:100
test2:
max-idle-connections:5
keep-alive-second:50
# Disable void return type
disable-void-return-type:false
# Logging interceptor
logging-interceptor:com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
# Request retry interceptor
retry-interceptor:com.github.lianjiatech.retrofit.spring.boot.retry.DefaultRetryInterceptor
# Global converter factory
global-converter-factories:
- retrofit2.converter.jackson.JacksonConverterFactory
# Global call adapter factory
global-call-adapter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
- com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory
# Enable circuit breaker degradation
enable-degrade:true
# Circuit breaker degradation implementation method
degrade-type:sentinel
# Circuit breaker resource name parser
resource-name-parser:com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser
Copy code
Advanced Features
Custom Injection of OkHttpClient
In most cases, dynamically creating the <span>OkHttpClient</span> object through the properties of the <span>@RetrofitClient</span> annotation can meet most usage scenarios. However, in some cases, users may need to customize the <span>OkHttpClient</span>. In this case, you can define a static method that returns the type <span>OkHttpClient.Builder</span> on the interface to achieve this. The code example is as follows:
@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
Result<Person> getPerson(@Url String url, @Query("id") Long id);
}
Copy code
The method must be marked with the
<span>@OkHttpClientBuilder</span>annotation!
Annotation-based Interceptors
Many times, we want certain HTTP requests under a specific interface to execute unified interception logic. To support this functionality, <span>retrofit-spring-boot-starter</span> provides annotation-based interceptors, achieving URL path-based matching interception. The steps to use it are mainly divided into 2 steps:
- Inherit
<span>BasePathMatchInterceptor</span>to write the interceptor; - Use
<span>@Intercept</span>to annotate the interface. If you need to configure multiple interceptors, simply annotate multiple<span>@Intercept</span>annotations on the interface!
Below is an example of appending a timestamp to the end of a specified request URL to illustrate how to use annotation-based interceptors.
Inherit <span>BasePathMatchInterceptor</span> to write the interceptor
@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);
}
}
Copy code
Use <span>@Intercept</span> to annotate the interface
@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);
}
Copy code
The above <span>@Intercept</span> configuration indicates: intercept requests under the <span>HttpApi</span> interface at the <span>/api/**</span> path (excluding <span>/api/test/savePerson</span>) using the <span>TimeStampInterceptor</span>.
Extend Annotation-based Interceptors
Sometimes, we need to dynamically pass some parameters into the intercept annotation and then use these parameters during interception. In such cases, we can extend and implement a custom intercept annotation. The <span>custom intercept annotation</span> must be marked with <span>@InterceptMark</span>, and it must include the properties <span>include()</span>, <span>exclude()</span>, and <span>handler()</span>. The steps to use it are mainly divided into 3 steps:
- Custom intercept annotation
- Inherit
<span>BasePathMatchInterceptor</span>to write the interceptor - Use the custom intercept annotation on the interface;
For example, if we need to dynamically add accessKeyId and accessKeySecret signature information in the request header to initiate HTTP requests normally, we can define a signing interceptor annotation <span>@Sign</span> to achieve this. Below is an example of the custom <span>@Sign</span> intercept annotation.
Custom <span>@Sign</span> Annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
/**
* Secret key
* Supports placeholder configuration.
*
* @return
*/
String accessKeyId();
/**
* Secret
* Supports placeholder configuration.
*
* @return
*/
String accessKeySecret();
/**
* Interceptor matching path
*
* @return
*/
String[] include() default {"/**"};
/**
* Exclude matching for the interceptor, exclude specified paths from interception
*
* @return
*/
String[] exclude() default {};
/**
* Interceptor class that handles this annotation
* It first tries to get the corresponding Bean from the Spring container, if not found, it uses reflection to create one!
*
* @return
*/
Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}
Copy code
Extending the <span>custom intercept annotation</span><code> has the following 2 points to note:
<span>Custom intercept annotation</span>must be marked with<span>@InterceptMark</span>.- The annotation must include
<span>include()</span>,<span>exclude()</span>, and<span>handler()</span>property information.
Implement <span>SignInterceptor</span>
@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);
}
}
Copy code
The above <span>accessKeyId</span> and <span>accessKeySecret</span> field values will be automatically injected based on the <span>@Sign</span> annotation’s <span>accessKeyId()</span> and <span>accessKeySecret()</span> values. If the <span>@Sign</span> specifies a placeholder string, the configuration property value will be used for injection. Additionally, the <span>accessKeyId</span> and <span>accessKeySecret</span> fields must provide <span>setter</span> methods.
Use on the Interface <span>@Sign</span>
@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);
}
Copy code
This way, the signature information will be automatically added to the requests for the specified URL.
Connection Pool Management
By default, all HTTP requests sent through <span>Retrofit</span> will use the default connection pool with <span>max-idle-connections=5 keep-alive-second=300</span>. Of course, we can also configure multiple custom connection pools in the configuration file and specify which one to use through the <span>@RetrofitClient</span>’s <span>poolName</span> property. For example, if we want all requests under a certain interface to use the <span>poolName=test1</span> connection pool, the code implementation is as follows:
-
Configure the connection pool.
retrofit: # Connection pool configuration pool: test1: max-idle-connections:3 keep-alive-second:100 test2: max-idle-connections:5 keep-alive-second:50 Copy code -
Specify the connection pool to use through the
<span>@RetrofitClient</span>’s<span>poolName</span>property.@RetrofitClient(baseUrl = "${test.baseUrl}", poolName="test1") public interface HttpApi { @GET("person") Result<Person> getPerson(@Query("id") Long id); } Copy code
Logging
In many cases, we want to log HTTP request details. The logging can be globally controlled through the <span>retrofit.enableLog</span> configuration. For each interface, you can control whether logging is enabled through the <span>@RetrofitClient</span>’s <span>enableLog</span>. By using <span>logLevel</span> and <span>logStrategy</span>, you can specify the logging level and strategy for each interface. <span>retrofit-spring-boot-starter</span> supports 5 logging levels (<span>ERROR</span>, <span>WARN</span>, <span>INFO</span>, <span>DEBUG</span>, <span>TRACE</span>), with the default being <span>INFO</span>; it supports 4 logging strategies (<span>NONE</span>, <span>BASIC</span>, <span>HEADERS</span>, <span>BODY</span>), with the default being <span>BASIC</span>. The meanings of the 4 logging strategies are as follows:
<span>NONE</span>: No logs.<span>BASIC</span>: Logs request and response lines.<span>HEADERS</span>: Logs request and response lines and their respective headers.<span>BODY</span>: Logs request and response lines and their respective headers and bodies (if present).
<span>retrofit-spring-boot-starter</span> uses the <span>DefaultLoggingInterceptor</span> to perform the actual logging functionality, which is based on the native <span>HttpLoggingInterceptor</span> of <span>okhttp</span>. Of course, you can also implement your own logging interceptor by inheriting from <span>BaseLoggingInterceptor</span> (for specific implementation, refer to the <span>DefaultLoggingInterceptor</span> implementation), and then configure it in the configuration file.
retrofit:
# Logging interceptor
logging-interceptor:com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
Copy code
Request Retries
<span>retrofit-spring-boot-starter</span> supports request retry functionality, simply add the <span>@Retry</span> annotation to the interface or method.<span>@Retry</span> supports retry count <span>maxRetries</span>, retry interval <span>intervalMs</span>, and retry rules <span>retryRules</span> configuration. The retry rules support three configurations:
<span>RESPONSE_STATUS_NOT_2XX</span>: Retry when the response status code is not<span>2xx</span>.<span>OCCUR_IO_EXCEPTION</span>: Retry when an IO exception occurs.<span>OCCUR_EXCEPTION</span>: Retry when any exception occurs.
By default, it automatically retries when the response status code is not <span>2xx</span> or when an IO exception occurs. If needed, you can also inherit from <span>BaseRetryInterceptor</span> to implement your own request retry interceptor and configure it.
retrofit:
# Request retry interceptor
retry-interceptor:com.github.lianjiatech.retrofit.spring.boot.retry.DefaultRetryInterceptor
Copy code
Error Decoders
When an HTTP request error occurs (including exceptions or response data not meeting expectations), the error decoder can decode the HTTP-related information into a custom exception. You can specify the current interface’s error decoder in the <span>@RetrofitClient</span> annotation’s <span>errorDecoder()</span>. Custom error decoders need to implement the <span>ErrorDecoder</span> interface:
/**
* Error decoder. ErrorDecoder.
* When an exception occurs in the request or an invalid response result is received, the HTTP related information is decoded into the exception,
* and the invalid response is determined by the business itself.
*
* @author 陈添明
*/
public interface ErrorDecoder {
/**
* When the response is invalid, decode the HTTP information into the exception, invalid response is determined by business.
*
* @param request request
* @param response response
* @return If it returns null, the processing is ignored and the processing continues with the original response.
*/
default RuntimeException invalidRespDecode(Request request, Response response) {
if (!response.isSuccessful()) {
throw RetrofitException.errorStatus(request, response);
}
return null;
}
/**
* When an IO exception occurs in the request, the HTTP information is decoded into the exception.
*
* @param request request
* @param cause IOException
* @return RuntimeException
*/
default RuntimeException ioExceptionDecode(Request request, IOException cause) {
return RetrofitException.errorExecuting(request, cause);
}
/**
* When the request has an exception other than the IO exception, the HTTP information is decoded into the exception.
*
* @param request request
* @param cause Exception
* @return RuntimeException
*/
default RuntimeException exceptionDecode(Request request, Exception cause) {
return RetrofitException.errorUnknown(request, cause);
}
}
Copy code
Global Interceptors
Global Application Interceptors
If we need to perform unified interception processing for all HTTP requests in the system, we can customize and implement a global interceptor <span>BaseGlobalInterceptor</span>, and configure it as a <span>bean</span> in the <span>spring</span> container! For example, if we want all HTTP requests initiated in the system to carry source information.
@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);
}
}
Copy code
Global Network Interceptors
Simply implement the <span>NetworkInterceptor</span> interface and configure it as a <span>bean</span> in the <span>spring</span> container to support automatic weaving of global network interceptors.
Circuit Breaker and Degradation
In a distributed service architecture, performing circuit breaker degradation on unstable external services is one of the important measures to ensure high availability of services. Since the stability of external services cannot be guaranteed, when external services are unstable, response times will increase. Consequently, the response time for the caller will also increase, threads will pile up, and eventually, it may exhaust the caller’s thread pool, leading to the entire service becoming unavailable. Therefore, we need to perform circuit breaker degradation on unstable weak dependency service calls to temporarily cut off unstable calls, preventing local instability from causing an overall service avalanche.
<span>retrofit-spring-boot-starter</span> supports circuit breaker degradation functionality, based on Sentinel. Specifically, it supports circuit breaker resource self-discovery and annotation-based degradation rule configuration. To use circuit breaker degradation, simply perform the following operations:
1. Enable Circuit Breaker Degradation Functionality
By default, the circuit breaker degradation functionality is disabled, and you need to set the corresponding configuration items to enable it:
retrofit:
# Whether to enable circuit breaker degradation
enable-degrade:true
# Circuit breaker degradation implementation method (currently only supports Sentinel)
degrade-type:sentinel
# Resource name parser
resource-name-parser:com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser
Copy code
The resource name parser is used to implement user-defined resource names, with the default configuration being <span>DefaultResourceNameParser</span>, corresponding to the resource name format of <span>HTTP_OUT:GET:http://localhost:8080/api/degrade/test</span>. Users can inherit from the <span>BaseResourceNameParser</span> class to implement their own resource name parser.
Additionally, since the circuit breaker degradation functionality is optional, enabling it requires users to manually introduce the Sentinel dependency:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.6.3</version>
</dependency>
Copy code
2. Configure Degradation Rules (Optional)
<span>retrofit-spring-boot-starter</span> supports annotation-based configuration of degradation rules, configured through the <span>@Degrade</span> annotation. The <span>@Degrade</span> annotation can be configured on interfaces or methods, with the configuration on methods taking precedence.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface Degrade {
/**
* RT threshold or exception ratio threshold count.
*/
double count();
/**
* Degrade recover timeout (in seconds) when degradation occurs.
*/
int timeWindow() default 5;
/**
* Degrade strategy (0: average RT, 1: exception ratio).
*/
DegradeStrategy degradeStrategy() default DegradeStrategy.AVERAGE_RT;
}
Copy code
If the application project already supports configuring degradation rules through a configuration center, the annotation-based configuration method can be ignored.
3. Set fallback or fallbackFactory in <span>@RetrofitClient</span> (Optional)
If the <span>@RetrofitClient</span> does not set <span>fallback</span> or <span>fallbackFactory</span>, when a circuit breaker is triggered, it will directly throw a <span>RetrofitBlockException</span> exception. Users can customize the return value of the method when the circuit breaker is triggered by setting <span>fallback</span> or <span>fallbackFactory</span>. The <span>fallback</span> class must be an implementation of the current interface, and the <span>fallbackFactory</span> must be an implementation of <span>FallbackFactory<T></span>, with the generic parameter type being the current interface type. Additionally, the <span>fallback</span> and <span>fallbackFactory</span> instances must be configured as <span>Bean</span> in the <span>Spring</span> container.
<span>fallbackFactory</span> differs from <span>fallback</span> mainly in that it can perceive the cause of each circuit breaker trigger (cause). Below is a reference example:
@Slf4j
@Service
public class HttpDegradeFallback implements HttpDegradeApi {
@Override
public Result<Integer> test() {
Result<Integer> fallback = new Result<>();
fallback.setCode(100)
.setMsg("fallback")
.setBody(1000000);
return fallback;
}
}
Copy code
@Slf4j
@Service
public class HttpDegradeFallbackFactory implements FallbackFactory<HttpDegradeApi> {
/**
* Returns an instance of the fallback appropriate for the given cause
*
* @param cause fallback cause
* @return an instance that implements the retrofit interface.
*/
@Override
public HttpDegradeApi create(Throwable cause) {
log.error("Circuit breaker triggered! ", cause.getMessage(), cause);
return new HttpDegradeApi() {
@Override
public Result<Integer> test() {
Result<Integer> fallback = new Result<>();
fallback.setCode(100)
.setMsg("fallback")
.setBody(1000000);
return fallback;
}
};
}
}
Copy code
HTTP Calls Between Microservices
To enable microservice calls, the following configuration is required:
Configure <span>ServiceInstanceChooser</span> as a <span>Spring</span> container <span>Bean</span>
Users can implement the <span>ServiceInstanceChooser</span> interface to complete the service instance selection logic and configure it as a <span>Bean</span> in the <span>Spring</span> container. For <span>Spring Cloud</span> applications, <span>retrofit-spring-boot-starter</span> provides the <span>SpringCloudServiceInstanceChooser</span> implementation, and users only need to configure it as a <span>Bean</span> in the <span>Spring</span> container.
@Bean
@Autowired
public ServiceInstanceChooser serviceInstanceChooser(LoadBalancerClient loadBalancerClient) {
return new SpringCloudServiceInstanceChooser(loadBalancerClient);
}
Copy code
Use <span>@Retrofit</span>’s <span>serviceId</span> and <span>path</span> properties to achieve HTTP calls between microservices
@RetrofitClient(serviceId = "${jy-helicarrier-api.serviceId}", path = "/m/count", errorDecoder = HelicarrierErrorDecoder.class)
@Retry
public interface ApiCountService {
}
Copy code
Call Adapters and Data Converters
Call Adapters
<span>Retrofit</span> can adapt the <span>Call<T></span> object to the return type of the interface method through call adapters <span>CallAdapterFactory</span>. <span>retrofit-spring-boot-starter</span> extends 2 types of <span>CallAdapterFactory</span> implementations:
-
BodyCallAdapterFactory
- Enabled by default, can be disabled by configuring
<span>retrofit.enable-body-call-adapter=false</span>. - Synchronously executes HTTP requests, adapting the response body content to the return type instance of the interface method.
- Besides
<span>Retrofit.Call<T></span>,<span>Retrofit.Response<T></span>, and<span>java.util.concurrent.CompletableFuture<T></span>, other return types can use this adapter.
ResponseCallAdapterFactory
- Enabled by default, can be disabled by configuring
<span>retrofit.enable-response-call-adapter=false</span>. - Synchronously executes HTTP requests, adapting the response body content to return
<span>Retrofit.Response<T></span>. - If the method’s return type is
<span>Retrofit.Response<T></span>, this adapter can be used.
Retrofit automatically selects the corresponding <span>CallAdapterFactory</span> for adaptation based on the method return type! Along with Retrofit’s default <span>CallAdapterFactory</span>, it supports various forms of method return types:
<span>Call<T></span>: Does not perform adaptation, directly returns the <code><span>Call<T></span><span> object</span><span>CompletableFuture<T></span>: Adapts the response body content to return a <code><span>CompletableFuture<T></span><span> object</span><span>Void</span>: Can use Void if the return type is not a concern. If the HTTP status code is not 2xx, it throws an error!<span>Response<T></span>: Adapts the response content to return a <code><span>Response<T></span><span> object</span>- Any other Java type: Adapts the response body content to return a corresponding Java type object, if the HTTP status code is not 2xx, it throws an error!
/**
* Call<T>
* Does not perform adaptation, directly returns Call<T> object
* @param id
* @return
*/
@GET("person")
Call<Result<Person>> getPersonCall(@Query("id") Long id);
/**
* CompletableFuture<T>
* Adapts the response body content to return a CompletableFuture<T> object
* @param id
* @return
*/
@GET("person")
CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);
/**
* Void
* Does not focus on the return type can use Void. If the HTTP status code is not 2xx, it throws an error!
* @param id
* @return
*/
@GET("person")
Void getPersonVoid(@Query("id") Long id);
/**
* Response<T>
* Adapts the response content to return a Response<T> object
* @param id
* @return
*/
@GET("person")
Response<Result<Person>> getPersonResponse(@Query("id") Long id);
/**
* Any other Java type
* Adapts the response body content to return a corresponding Java type object, if the HTTP status code is not 2xx, it throws an error!
* @param id
* @return
*/
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
Copy code
We can also extend and implement our own <span>CallAdapter</span> by inheriting from <span>CallAdapter.Factory</span>!
<span>retrofit-spring-boot-starter</span> supports configuring global call adapter factories through <span>retrofit.global-call-adapter-factories</span>, with the factory instance prioritized to be obtained from the Spring container, and if not found, it is created via reflection. The default global call adapter factories are <span>[BodyCallAdapterFactory, ResponseCallAdapterFactory]</span>!
retrofit:
# Global call adapter factory
global-call-adapter-factories:
- com.github.lianjiatech.retrofit.spring.boot.core.BodyCallAdapterFactory
- com.github.lianjiatech.retrofit.spring.boot.core.ResponseCallAdapterFactory
Copy code
For each Java interface, you can also specify the <span>CallAdapter.Factory</span> used by the current interface through the <span>@RetrofitClient</span> annotation’s <span>callAdapterFactories()</span>, with the specified factory instance still prioritized to be obtained from the Spring container.
Note: If the <span>CallAdapter.Factory</span> does not have a public no-argument constructor, please manually configure it as a <span>Bean</span> object in the <span>Spring</span> container!
Data Converters
<span>Retrofit</span> uses <span>Converter</span> to convert objects annotated with <span>@Body</span> into request bodies and to convert response body data into a <span>Java</span> object. The following types of <span>Converter</span> can be selected:
- Gson: com.squareup.retrofit2:converter-gson
- Jackson: com.squareup.retrofit2:converter-jackson
- Moshi: com.squareup.retrofit2:converter-moshi
- Protobuf: com.squareup.retrofit2:converter-protobuf
- Wire: com.squareup.retrofit2:converter-wire
- Simple XML: com.squareup.retrofit2:converter-simplexml
- JAXB: com.squareup.retrofit2:converter-jaxb
<span>retrofit-spring-boot-starter</span> supports configuring global data converter factories through <span>retrofit.global-converter-factories</span>, with the converter factory instance prioritized to be obtained from the Spring container, and if not found, it is created via reflection. The default global data converter factory is <span>retrofit2.converter.jackson.JacksonConverterFactory</span>, and you can directly configure the <span>jackson</span> serialization rules through <span>spring.jackson.*</span>, with configuration details available in Customize the Jackson ObjectMapper!
retrofit:
# Global converter factory
global-converter-factories:
- retrofit2.converter.jackson.JacksonConverterFactory
Copy code
For each Java interface, you can also specify the <span>Converter.Factory</span> used by the current interface through the <span>@RetrofitClient</span> annotation’s <span>converterFactories()</span>, with the specified converter factory instance still prioritized to be obtained from the Spring container.
Note: If the <span>Converter.Factory</span> does not have a public no-argument constructor, please manually configure it as a <span>Bean</span> object in the <span>Spring</span> container!
Conclusion
<span>retrofit-spring-boot-starter</span> is a lightweight <span>HTTP</span> client framework suitable for <span>SpringBoot</span> projects, which has been stably running online for over a year and has been adopted by multiple external companies.
<END>Recommended Reading: Side hustle earning recommendations: Let your time start to monetize! Free experience of AI image generation, just at Image Generator Hub!
Programmer online tool site: cxytools.com
Recommend a tool site I wrote: https://cxytools.com, specially designed for programmers, including time and date,
JSON processing, SQL formatting, random string generation, UUID generation, text Hash... and other functions to improve development efficiency.
⬇ Click to read the original text directly! I have read it