1. Description:
Retrofit is an open source java version of http client,
retrofit-spring-boot-starter
It realizes rapid integration Retrofit
with SpringBoot
the framework and supports some function enhancements, thus greatly simplifying the development of http interface calls under the spring-boot project. Compared with okHttp and HttpClient, it has obvious advantages in project development.
1. Add dependencies:
<dependency>
<groupId>com.github.lianjiatech</groupId>
<artifactId>retrofit-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
2. Add annotations to the startup class
- @RetrofitScan(“com.dabby.service.client”) marks the scan package path
3. Define the interface
-
@RetrofitClient(baseUrl = "${test.baseUrl}") specifies the RetrofitClient client class, and baseUrl specifies the base address
-
Request method annotations include the following:
- @HTTP/@GET/@POST commonly used to submit data and get data
- @PUT/@DELETE
- @PATH/@HEAD/OPTIONS/@HTTP
-
Request parameter annotations include the following:
- @Header/@Headers Add request headers
-
@URL/@PATH URL default value setting
- @Filed/@FieldMap is used for form incoming key-value pair POST request
-
@Part/@PartMap User file upload form font
- @Query/@QueryMap is used for form form data request GET request
-
@Body is often used for POST request data
-
mark annotation
- @FormUrlEncoded indicates that this is a form format request, note that each parameter needs to be annotated with @Filed
- @Multipart indicates that this is a Form form for file upload: form-encoded, note that each parameter needs to be annotated with @Part
- @Streaming indicates that the returned data is put back in the form of a stream, which is suitable for scenarios with large data
@RetrofitClient(baseUrl = "${test.baseUrl}")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name,
@Field("age") int age);
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name,
@Part("age") RequestBody age,
@Part MultipartBody.Part file);
}
4. Injection use
@Service
public class TestService {
@Autowired
private HttpApi httpApi;
public void test() {
// 通过httpApi发起http请求
}
}
2. Extended use
1. Add a timestamp parameter to the request
(1), injection interceptor
For some requests, a timestamp needs to be added
@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();
//url添加时间戳参数
HttpUrl newUrl = url.newBuilder().addQueryParameter("timestamp", String.valueOf(timestamp)).build();
Request newRequest = request.newBuilder().url(newUrl).build();
return chain.proceed(newRequest);
}
}
(2), using labels on the interface
- @Intercept
- handler specifies the processor
- include contains certain interfaces
- exclude Exclude certain interfaces
@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);
}
2. Customize @Sign annotation
(1) Create a custom @Sign annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@InterceptMark
public @interface Sign {
/**
* 密钥key 支持占位符形式配置。
*/
String accessKeyId();
/**
* 密钥支持占位符形式配置。
*/
String accessKeySecret();
/**
* 拦截器匹配路径
*/
String[] include() default {
"/**"};
/**
* 拦截器排除匹配,排除指定路径拦截
*/
String[] exclude() default {
};
/**
* 处理该注解的拦截器类
* 优先从spring容器获取对应的Bean,如果获取不到,则使用反射创建一个!
*/
Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class;
}
(2), to achieve SignInterceptor
@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);
}
}
(3), using @Sign on the interface
@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);
}
3. Connection pool management:
(1) Add connection pool configuration to the configuration file
retrofit:
# 连接池配置
pool:
test1:
max-idle-connections: 3
keep-alive-second: 100
test2:
max-idle-connections: 5
keep-alive-second: 50
(2) Use the poolName attribute of @RetrofitClient to specify the connection pool used.
@RetrofitClient(baseUrl = "${test.baseUrl}", poolName="test1")
public interface HttpApi {
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
}
4. Log printing
retrofit:
# 日志打印拦截器
logging-interceptor: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
retrofit:
# Http异常信息格式化器
http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter
5. Exception formatter
(1) Use the default exception formatter
retrofit:
# Http异常信息格式化器
http-exception-message-formatter: com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter
(2) Used in the interface
/**
* Call<T>
* 不执行适配处理,直接返回Call<T>对象
*/
@GET("person")
Call<Result<Person>> getPersonCall(@Query("id") Long id);
/**
* CompletableFuture<T>
* 将响应体内容适配成CompletableFuture<T>对象返回
*/
@GET("person")
CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);
/**
* Void
* 不关注返回类型可以使用Void。如果http状态码不是2xx,直接抛错!
*/
@GET("person")
Void getPersonVoid(@Query("id") Long id);
/**
* Response<T>
* 将响应内容适配成Response<T>对象返回
*/
@GET("person")
Response<Result<Person>> getPersonResponse(@Query("id") Long id);
/**
* 其他任意Java类型
* 将响应体内容适配成一个对应的Java类型对象返回,如果http状态码不是2xx,直接抛错!
*/
@GET("person")
Result<Person> getPerson(@Query("id") Long id);
6. Global interceptor
@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);
}
}