Dokumen Bahasa Inggris
Spring-boot-starter untuk retrofit, mendukung integrasi cepat dan peningkatan fitur .
Proyek ini terus dioptimalkan dan diulangi, dan semua orang dipersilakan untuk mengirimkan MASALAH dan PR! Tolong beri kami bintang. Bintang Anda adalah motivasi kami untuk pembaruan berkelanjutan!
Alamat proyek Github: https://github.com/LianjiaTech/retrofit-spring-boot-starter
alamat proyek gitee: https://gitee.com/lianjiatech/retrofit-spring-boot-starter
Contoh demo: https://github.com/ismart-yuxi/retrofit-spring-boot-demo
Terima kasih kepada
@ismart-yuxi
yang telah menulis contoh demo untuk proyek ini
< dependency >
< groupId >com.github.lianjiatech</ groupId >
< artifactId >retrofit-spring-boot-starter</ artifactId >
< version >3.1.3</ version >
</ dependency >
Jika startup gagal, kemungkinan besar terjadi konflik ketergantungan. Harap perkenalkan atau kecualikan ketergantungan terkait .
Antarmuka harus ditandai dengan anotasi @RetrofitClient
! Untuk informasi terkait HTTP, silakan merujuk ke dokumentasi resmi: dokumentasi resmi retrofit.
@ RetrofitClient ( baseUrl = "${test.baseUrl}" )
public interface UserService {
/**
* 根据id查询用户姓名
*/
@ POST ( "getName" )
String getName ( @ Query ( "id" ) Long id );
}
Catatan: Jalur permintaan metode harus dimulai dengan
/
dengan hati-hati . UntukRetrofit
, jikabaseUrl=http://localhost:8080/api/test/
dan jalur permintaan metode adalahperson
, jalur permintaan lengkap dari metode tersebut adalah:http://localhost:8080/api/test/person
. Jika jalur permintaan metode adalah/person
, jalur permintaan lengkap dari metode tersebut adalah:http://localhost:8080/person
.
Suntikkan antarmuka ke Layanan lain dan gunakan!
@ Service
public class BusinessService {
@ Autowired
private UserService userService ;
public void doBusiness () {
// call userService
}
}
Secara default, jalur pemindaian SpringBoot
secara otomatis digunakan untuk pendaftaran RetrofitClient
. Anda juga dapat menambahkan @RetrofitScan
ke kelas konfigurasi untuk menentukan jalur pemindaian secara manual.
Anotasi yang terkait dengan permintaan HTTP
semuanya menggunakan anotasi asli Retrofit
. Berikut penjelasan sederhananya:
Klasifikasi anotasi | Anotasi yang didukung |
---|---|
Metode permintaan | @GET @HEAD @POST @PUT @DELETE @OPTIONS @HTTP |
Judul permintaan | @Header @HeaderMap @Headers |
Parameter kueri | @Query @QueryMap @QueryName |
parameter jalur | @Path |
parameter yang dikodekan formulir | @Field @FieldMap @FormUrlEncoded |
Permintaan tubuh | @Body |
Unggah berkas | @Multipart @Part @PartMap |
parameter url | @Url |
Untuk informasi selengkapnya, silakan merujuk ke dokumentasi resmi: dokumentasi resmi retrofit
Komponen ini mendukung beberapa atribut yang dapat dikonfigurasi untuk mengatasi berbagai skenario bisnis. Atribut konfigurasi spesifik yang didukung dan nilai default adalah sebagai berikut:
Catatan: Aplikasi hanya perlu mengkonfigurasi item konfigurasi yang akan diubah !
retrofit :
# 全局转换器工厂
global-converter-factories :
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
# 全局调用适配器工厂(组件扩展的调用适配器工厂已经内置,这里请勿重复配置)
global-call-adapter-factories :
# 全局日志打印配置
global-log :
# 启用日志打印
enable : true
# 全局日志打印级别
log-level : info
# 全局日志打印策略
log-strategy : basic
# 是否聚合打印请求日志
aggregate : true
# 全局重试配置
global-retry :
# 是否启用全局重试
enable : false
# 全局重试间隔时间
interval-ms : 100
# 全局最大重试次数
max-retries : 2
# 全局重试规则
retry-rules :
- response_status_not_2xx
- occur_io_exception
# 全局超时时间配置
global-timeout :
# 全局读取超时时间
read-timeout-ms : 10000
# 全局写入超时时间
write-timeout-ms : 10000
# 全局连接超时时间
connect-timeout-ms : 10000
# 全局完整调用超时时间
call-timeout-ms : 0
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : none
# 全局sentinel降级配置
global-sentinel-degrade :
# 是否开启
enable : false
# 各降级策略对应的阈值。平均响应时间(ms),异常比例(0-1),异常数量(1-N)
count : 1000
# 熔断时长,单位为 s
time-window : 5
# 降级策略(0:平均响应时间;1:异常比例;2:异常数量)
grade : 0
# 全局resilience4j降级配置
global-resilience4j-degrade :
# 是否开启
enable : false
# 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置
circuit-breaker-config-name : defaultCircuitBreakerConfig
# 自动设置PathMathInterceptor的scope为prototype
auto-set-prototype-scope-for-path-math-interceptor : true
Jika Anda hanya perlu mengubah periode batas waktu OkHttpClient
, Anda dapat memodifikasinya melalui bidang terkait @RetrofitClient
atau mengubah konfigurasi batas waktu global.
Jika Anda perlu mengubah konfigurasi OkHttpClient
lainnya, Anda dapat melakukannya dengan menyesuaikan OkHttpClient
. Langkah-langkahnya adalah sebagai berikut:
Implementasikan antarmuka SourceOkHttpClientRegistrar
dan panggil metode SourceOkHttpClientRegistry#register()
untuk mendaftarkan OkHttpClient
@ Component
public class CustomOkHttpClientRegistrar implements SourceOkHttpClientRegistrar {
@ Override
public void register ( SourceOkHttpClientRegistry registry ) {
// 注册customOkHttpClient,超时时间设置为1s
registry . register ( "customOkHttpClient" , new OkHttpClient . Builder ()
. connectTimeout ( Duration . ofSeconds ( 1 ))
. writeTimeout ( Duration . ofSeconds ( 1 ))
. readTimeout ( Duration . ofSeconds ( 1 ))
. addInterceptor ( chain -> chain . proceed ( chain . request ()))
. build ());
}
}
Tentukan OkHttpClient
yang akan digunakan oleh antarmuka saat ini melalui @RetrofitClient.sourceOkHttpClient
@ RetrofitClient ( baseUrl = "${test.baseUrl}" , sourceOkHttpClient = "customOkHttpClient" )
public interface CustomOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
Catatan: Komponen tidak akan menggunakan
OkHttpClient
yang ditentukan secara langsung, namun akan membuat yang baru berdasarkanOkHttpClient
.
Komponen menyediakan interseptor anotasi yang mendukung intersepsi berdasarkan pencocokan jalur URL. Langkah-langkah penggunaannya adalah sebagai berikut:
BasePathMatchInterceptor
@Intercept
untuk menentukan interseptor yang akan digunakanJika Anda perlu menggunakan beberapa pencegat, cukup tandai beberapa anotasi
@Intercept
pada antarmuka.
BasePathMatchInterceptor
untuk menulis prosesor intersepsi @ Component
public class PathMatchInterceptor extends BasePathMatchInterceptor {
@ Override
protected Response doIntercept ( Chain chain ) throws IOException {
Response response = chain . proceed ( chain . request ());
// response的Header加上path.match
return response . newBuilder (). header ( "path.match" , "true" ). build ();
}
}
Secara default, komponen secara otomatis menetapkan scope
BasePathMatchInterceptor
ke prototype
. Fitur ini dapat dimatikan melalui retrofit.auto-set-prototype-scope-for-path-math-interceptor=false
. Setelah ditutup, Anda perlu mengatur scope
secara manual ke prototype
.
@ Component
@ Scope ( "prototype" )
public class PathMatchInterceptor extends BasePathMatchInterceptor {
}
@Intercept
untuk memberi anotasi pada antarmuka @ RetrofitClient ( baseUrl = "${test.baseUrl}" )
@ Intercept ( handler = PathMatchInterceptor . class , include = { "/api/user/**" }, exclude = "/api/user/getUser" )
// @Intercept() 如果需要使用多个路径匹配拦截器,继续添加@Intercept即可
public interface InterceptorUserService {
/**
* 根据id查询用户姓名
*/
@ POST ( "getName" )
Response < String > getName ( @ Query ( "id" ) Long id );
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
Response < User > getUser ( @ Query ( "id" ) Long id );
}
Konfigurasi @Intercept
di atas berarti: mencegat permintaan di bawah jalur /api/user/**
di bawah antarmuka InterceptorUserService
(tidak termasuk /api/user/getUser
), dan prosesor intersepsi menggunakan PathMatchInterceptor
.
Terkadang, kita perlu meneruskan beberapa parameter secara dinamis dalam "anotasi intersepsi" dan kemudian menggunakan parameter ini saat mencegat. Saat ini, kita dapat menggunakan "anotasi intersepsi khusus". Langkah-langkahnya adalah sebagai berikut:
@InterceptMark
harus digunakan, dan anotasi harus menyertakan bidang include、exclude、handler
.BasePathMatchInterceptor
untuk menulis prosesor intersepsi Misalnya, kita perlu "menambahkan informasi tanda tangan accessKeyId
dan accessKeySecret
secara dinamis ke header permintaan sebelum memulai permintaan HTTP." Dalam hal ini, kita dapat menyesuaikan anotasi @Sign
untuk mencapai hal ini.
@Sign
khusus @ 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 ;
}
Pencegat yang digunakan adalah SignInterceptor
yang ditentukan dalam anotasi @Sign
.
SignInterceptor
@ Component
@ Setter
public class SignInterceptor extends BasePathMatchInterceptor {
private String accessKeyId ;
private String accessKeySecret ;
@ Override
public Response doIntercept ( Chain chain ) throws IOException {
Request request = chain . request ();
Request newReq = request . newBuilder ()
. addHeader ( "accessKeyId" , accessKeyId )
. addHeader ( "accessKeySecret" , accessKeySecret )
. build ();
Response response = chain . proceed ( newReq );
return response . newBuilder (). addHeader ( "accessKeyId" , accessKeyId )
. addHeader ( "accessKeySecret" , accessKeySecret ). build ();
}
}
Catatan: Bidang
accessKeyId
danaccessKeySecret
harus menyediakan metodesetter
.
Nilai bidang accessKeyId
dan accessKeySecret
dari pencegat akan secara otomatis disuntikkan berdasarkan nilai accessKeyId()
dan accessKeySecret()
dari anotasi @Sign
. Jika @Sign
menentukan string dalam bentuk placeholder, maka nilai atribut konfigurasi akan digunakan untuk injeksi.
@Sign
pada antarmuka @ RetrofitClient ( baseUrl = "${test.baseUrl}" )
@ Sign ( accessKeyId = "${test.accessKeyId}" , accessKeySecret = "${test.accessKeySecret}" , include = "/api/user/getAll" )
public interface InterceptorUserService {
/**
* 查询所有用户信息
*/
@ GET ( "getAll" )
Response < List < User >> getAll ();
}
Komponen ini mendukung pencetakan log global dan pencetakan log deklaratif.
Secara default, pencetakan log global diaktifkan, dan konfigurasi defaultnya adalah sebagai berikut:
retrofit :
# 全局日志打印配置
global-log :
# 启用日志打印
enable : true
# 全局日志打印级别
log-level : info
# 全局日志打印策略
log-strategy : basic
# 是否聚合打印请求日志
aggregate : true
# 日志名称,默认为{@link LoggingInterceptor} 的全类名
logName : com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor
Arti dari keempat strategi pencetakan log adalah sebagai berikut:
NONE
: Tidak ada log.BASIC
: Mencatat jalur permintaan dan respons.HEADERS
: Mencatat baris permintaan dan respons serta headernya masing-masing.BODY
: Mencatat baris permintaan dan respons serta header dan isi masing-masing (jika ada). Jika Anda hanya perlu mencetak log untuk beberapa permintaan, Anda dapat menggunakan anotasi @Logging
pada antarmuka atau metode yang relevan.
Jika Anda perlu mengubah perilaku pencetakan log, Anda dapat mewarisi LoggingInterceptor
dan mengonfigurasinya sebagai Spring bean
.
Dukungan komponen mendukung percobaan ulang global dan percobaan ulang deklaratif.
Percobaan ulang global dinonaktifkan secara default, dan item konfigurasi default adalah sebagai berikut:
retrofit :
# 全局重试配置
global-retry :
# 是否启用全局重试
enable : false
# 全局重试间隔时间
interval-ms : 100
# 全局最大重试次数
max-retries : 2
# 全局重试规则
retry-rules :
- response_status_not_2xx
- occur_io_exception
Aturan percobaan ulang mendukung tiga konfigurasi:
RESPONSE_STATUS_NOT_2XX
: Coba lagi ketika kode status respons bukan 2xx
OCCUR_IO_EXCEPTION
: Lakukan percobaan ulang ketika pengecualian IO terjadiOCCUR_EXCEPTION
: Coba lagi ketika terjadi pengecualian Jika hanya beberapa permintaan yang perlu dicoba ulang, Anda dapat menggunakan anotasi @Retry
pada antarmuka atau metode yang sesuai.
Jika Anda perlu mengubah perilaku permintaan coba lagi, Anda dapat mewarisi RetryInterceptor
dan mengonfigurasinya sebagai Spring bean
.
Penurunan versi pemutus sirkuit dinonaktifkan secara default, dan saat ini mendukung implementasi sentinel
dan resilience4j
.
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
Konfigurasikan degrade-type=sentinel
untuk mengaktifkannya, lalu deklarasikan anotasi @SentinelDegrade
pada antarmuka atau metode yang relevan.
Ingatlah untuk memperkenalkan dependensi Sentinel
secara manual:
< dependency >
< groupId >com.alibaba.csp</ groupId >
< artifactId >sentinel-core</ artifactId >
< version >1.6.3</ version >
</ dependency >
Selain itu, downgrade pemutus sirkuit Sentinel
global juga didukung:
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
# 全局sentinel降级配置
global-sentinel-degrade :
# 是否开启
enable : true
# ...其他sentinel全局配置
Konfigurasikan degrade-type=resilience4j
untuk mengaktifkannya. Kemudian deklarasikan @Resilience4jDegrade
pada antarmuka atau metode yang relevan.
Ingatlah untuk memperkenalkan ketergantungan Resilience4j
secara manual:
< dependency >
< groupId >io.github.resilience4j</ groupId >
< artifactId >resilience4j-circuitbreaker</ artifactId >
< version >1.7.1</ version >
</ dependency >
Downgrade pemutus sirkuit ketahanan global4j dapat diaktifkan melalui konfigurasi berikut:
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : resilience4j
# 全局resilience4j降级配置
global-resilience4j-degrade :
# 是否开启
enable : true
# 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置
circuit-breaker-config-name : defaultCircuitBreakerConfig
Manajemen konfigurasi pemutus sirkuit:
Implementasikan antarmuka CircuitBreakerConfigRegistrar
dan daftarkan CircuitBreakerConfig
.
@ Component
public class CustomCircuitBreakerConfigRegistrar implements CircuitBreakerConfigRegistrar {
@ Override
public void register ( CircuitBreakerConfigRegistry registry ) {
// 替换默认的CircuitBreakerConfig
registry . register ( Constants . DEFAULT_CIRCUIT_BREAKER_CONFIG , CircuitBreakerConfig . ofDefaults ());
// 注册其它的CircuitBreakerConfig
registry . register ( "testCircuitBreakerConfig" , CircuitBreakerConfig . custom ()
. slidingWindowType ( CircuitBreakerConfig . SlidingWindowType . TIME_BASED )
. failureRateThreshold ( 20 )
. minimumNumberOfCalls ( 5 )
. permittedNumberOfCallsInHalfOpenState ( 5 )
. build ());
}
}
CircuitBreakerConfig
ditentukan oleh circuitBreakerConfigName
. Sertakan retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name
atau @Resilience4jDegrade.circuitBreakerConfigName
Jika pengguna perlu menggunakan implementasi degradasi pemutus sirkuit lainnya, warisi BaseRetrofitDegrade
dan konfigurasikan Spring Bean
.
Jika @RetrofitClient
tidak menyetel fallback
atau fallbackFactory
, saat pemutus sirkuit dipicu, RetrofitBlockException
akan langsung dilempar. Pengguna dapat menyesuaikan nilai pengembalian metode saat terjadi penggabungan dengan mengatur fallback
atau fallbackFactory
.
Catatan: Kelas
fallback
harus berupa kelas implementasi antarmuka saat ini,fallbackFactory
harus berupa kelas implementasiFallbackFactory<T>
, dan tipe parameter generik harus berupa tipe antarmuka saat ini. Selain itu, instansfallback
danfallbackFactory
harus dikonfigurasi sebagaiSpring Bean
.
Dibandingkan dengan fallbackFactory
fallback
adalah ia dapat merasakan penyebab (penyebab) abnormal dari setiap pemutus sirkuit. Contoh referensinya adalah sebagai berikut:
@ 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 ;
}
}
@ Slf4j
@ Service
public class HttpDegradeFallbackFactory implements FallbackFactory < HttpDegradeApi > {
@ Override
public HttpDegradeApi create ( Throwable cause ) {
log . error ( "触发熔断了! " , 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 ;
}
};
}
}
Ketika kesalahan permintaan HTTP
terjadi (termasuk pengecualian atau data respons tidak memenuhi harapan), dekoder kesalahan dapat mendekode informasi terkait HTTP
menjadi pengecualian khusus. Anda dapat menentukan dekoder kesalahan antarmuka saat ini dalam anotasi errorDecoder errorDecoder()
dari @RetrofitClient
. Dekoder kesalahan khusus perlu mengimplementasikan antarmuka ErrorDecoder
:
ServiceInstanceChooser
Pengguna dapat mengimplementasikan sendiri antarmuka ServiceInstanceChooser
, menyelesaikan logika pemilihan instans layanan, dan mengonfigurasinya sebagai Spring Bean
. Untuk aplikasi Spring Cloud
, implementasi berikut dapat digunakan.
@ Service
public class SpringCloudServiceInstanceChooser implements ServiceInstanceChooser {
private LoadBalancerClient loadBalancerClient ;
@ Autowired
public SpringCloudServiceInstanceChooser ( LoadBalancerClient loadBalancerClient ) {
this . loadBalancerClient = loadBalancerClient ;
}
/**
* Chooses a ServiceInstance URI from the LoadBalancer for the specified service.
*
* @param serviceId The service ID to look up the LoadBalancer.
* @return Return the uri of ServiceInstance
*/
@ Override
public URI choose ( String serviceId ) {
ServiceInstance serviceInstance = loadBalancerClient . choose ( serviceId );
Assert . notNull ( serviceInstance , "can not found service instance! serviceId=" + serviceId );
return serviceInstance . getUri ();
}
}
serviceId
dan path
@ RetrofitClient ( serviceId = "user" , path = "/api/user" )
public interface ChooserOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
Jika kita perlu melakukan pemrosesan intersepsi terpadu pada permintaan HTTP
seluruh sistem, kita dapat mengimplementasikan pencegat global GlobalInterceptor
dan mengonfigurasinya sebagai spring Bean
.
@ Component
public class MyGlobalInterceptor implements GlobalInterceptor {
@ Override
public Response intercept ( Chain chain ) throws IOException {
Response response = chain . proceed ( chain . request ());
// response的Header加上global
return response . newBuilder (). header ( "global" , "true" ). build ();
}
}
Implementasikan antarmuka NetworkInterceptor
dan konfigurasikan sebagai spring Bean
.
Retrofit
dapat mengadaptasi objek Call<T>
ke tipe nilai kembalian metode antarmuka melalui CallAdapterFactory
. Komponen ini memperluas beberapa implementasi CallAdapterFactory
:
BodyCallAdapterFactory
HTTP
secara sinkron dan sesuaikan konten isi respons dengan tipe nilai kembalian metode.BodyCallAdapterFactory
, dengan prioritas terendah.ResponseCallAdapterFactory
HTTP
secara sinkron, sesuaikan konten isi respons ke Retrofit.Response<T>
dan kembalikan.ResponseCallAdapterFactory
hanya dapat digunakan jika tipe nilai pengembalian metode adalah Retrofit.Response<T>
.CallAdapterFactory
Retrofit
akan memilih CallAdapterFactory
yang sesuai untuk melakukan pemrosesan adaptasi berdasarkan tipe nilai pengembalian metode . Tipe nilai pengembalian yang saat ini didukung adalah sebagai berikut:
String
: Sesuaikan Response Body
ke String
dan kembalikan.Long
/ Integer
/ Boolean
/ Float
/ Double
): Sesuaikan Response Body
dengan tipe dasar di atasJava
: Sesuaikan Response Body
ke objek Java
yang sesuai dan kembalikanCompletableFuture<T>
: Sesuaikan Response Body
menjadi objek CompletableFuture<T>
dan kembalikanVoid
: Anda dapat menggunakan Void
jika Anda tidak peduli dengan tipe pengembalian.Response<T>
: Sesuaikan Response
ke objek Response<T>
dan kembalikanCall<T>
: Tidak melakukan pemrosesan adaptasi dan langsung mengembalikan objek Call<T>
Mono<T>
: Tipe pengembalian reaktif Project Reactor
Single<T>
: Tipe pengembalian responsif Rxjava
(mendukung Rxjava2/Rxjava3
)Completable
: Jenis pengembalian responsif Rxjava
, permintaan HTTP
tidak memiliki isi respons (mendukung Rxjava2/Rxjava3
) CallAdapter
dapat diperluas dengan mewarisi CallAdapter.Factory
.
Komponen ini mendukung pabrik adaptor panggilan global melalui konfigurasi retrofit.global-call-adapter-factories
:
retrofit :
# 全局转换器工厂(组件扩展的`CallAdaptorFactory`工厂已经内置,这里请勿重复配置)
global-call-adapter-factories :
# ...
Untuk setiap antarmuka Java, Anda juga dapat menentukan CallAdapter.Factory
yang digunakan oleh antarmuka saat ini melalui @RetrofitClient.callAdapterFactories
.
Saran: Konfigurasikan
CallAdapter.Factory
sebagaiSpring Bean
Retrofit
menggunakan Converter
untuk mengubah objek beranotasi @Body
menjadi Request Body
dan mengubah Response Body
menjadi objek Java
. Anda dapat memilih dari Converter
berikut:
Komponen ini mendukung konfigurasi Converter.Factory
global melalui retrofit.global-converter-factories
. Defaultnya adalah retrofit2.converter.jackson.JacksonConverterFactory
.
Jika Anda perlu mengubah konfigurasi Jackson
, timpa sendiri konfigurasi bean
JacksonConverterFactory
.
retrofit :
# 全局转换器工厂
global-converter-factories :
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
Untuk setiap antarmuka Java
, Anda juga dapat menentukan Converter.Factory
yang digunakan oleh antarmuka saat ini melalui @RetrofitClient.converterFactories
.
Saran: Konfigurasikan
Converter.Factory
sebagaiSpring Bean
.
Anotasi seperti @RetrofitClient
, @Retry
, @Logging
, dan @Resilience4jDegrade
mendukung anotasi meta, pewarisan, dan @AliasFor
.
@ Retention ( RetentionPolicy . RUNTIME )
@ Target ( ElementType . TYPE )
@ Documented
@ Inherited
@ RetrofitClient ( baseUrl = "${test.baseUrl}" )
@ Logging ( logLevel = LogLevel . WARN )
@ Retry ( intervalMs = 200 )
public @interface MyRetrofitClient {
@ AliasFor ( annotation = RetrofitClient . class , attribute = "converterFactories" )
Class <? extends Converter . Factory >[] converterFactories () default { GsonConverterFactory . class };
@ AliasFor ( annotation = Logging . class , attribute = "logStrategy" )
LogStrategy logStrategy () default LogStrategy . BODY ;
}
@ FormUrlEncoded
@ POST ( "token/verify" )
Object tokenVerify ( @ Field ( "source" ) String source , @ Field ( "signature" ) String signature , @ Field ( "token" ) String token );
@ FormUrlEncoded
@ POST ( "message" )
CompletableFuture < Object > sendMessage ( @ FieldMap Map < String , Object > param );
// 对文件名使用URLEncoder进行编码
public ResponseEntity importTerminology ( MultipartFile file ){
String fileName = URLEncoder . encode ( Objects . requireNonNull ( file . getOriginalFilename ()), "utf-8" );
okhttp3 . RequestBody requestBody = okhttp3 . RequestBody . create ( MediaType . parse ( "multipart/form-data" ), file . getBytes ());
MultipartBody . Part part = MultipartBody . Part . createFormData ( "file" , fileName , requestBody );
apiService . upload ( part );
return ok (). build ();
}
HTTP
@ POST ( "upload" )
@ Multipart
Void upload ( @ Part MultipartBody . Part file );
HTTP
@ RetrofitClient ( baseUrl = "https://img.ljcdn.com/hc-picture/" )
public interface DownloadApi {
@ GET ( "{fileKey}" )
Response < ResponseBody > download ( @ Path ( "fileKey" ) String fileKey );
}
HTTP
@ SpringBootTest ( classes = { RetrofitBootApplication . class })
@ RunWith ( SpringRunner . class )
public class DownloadTest {
@ Autowired
DownloadApi downLoadApi ;
@ Test
public void download () throws Exception {
String fileKey = "6302d742-ebc8-4649-95cf-62ccf57a1add" ;
Response < ResponseBody > response = downLoadApi . download ( fileKey );
ResponseBody responseBody = response . body ();
// 二进制流
InputStream is = responseBody . byteStream ();
// 具体如何处理二进制流,由业务自行控制。这里以写入文件为例
File tempDirectory = new File ( "temp" );
if (! tempDirectory . exists ()) {
tempDirectory . mkdir ();
}
File file = new File ( tempDirectory , UUID . randomUUID (). toString ());
if (! file . exists ()) {
file . createNewFile ();
}
FileOutputStream fos = new FileOutputStream ( file );
byte [] b = new byte [ 1024 ];
int length ;
while (( length = is . read ( b )) > 0 ) {
fos . write ( b , 0 , length );
}
is . close ();
fos . close ();
}
}
URL dinamis dapat diimplementasikan menggunakan anotasi @url
. Saat ini, baseUrl
dapat dikonfigurasi dengan URL legal apa pun. Misalnya: http://github.com/
. Runtime hanya akan memulai permintaan berdasarkan alamat @Url
.
Catatan:
@url
harus ditempatkan di posisi pertama parameter metode. Selain itu,@GET
,@POST
dan anotasi lainnya tidak perlu menentukan jalur titik akhir.
@ GET
Map < String , Object > test3 ( @ Url String url , @ Query ( "name" ) String name );
DELETE
menambahkan isi permintaan @ HTTP ( method = "DELETE" , path = "/user/delete" , hasBody = true )
GET
okhttp3
sendiri tidak mendukung penambahan badan permintaan GET
. Kode sumbernya adalah sebagai berikut:
Penulis memberikan alasan khusus, Anda dapat merujuk ke: masalah
Namun, jika Anda benar-benar perlu melakukan ini, Anda dapat menggunakan: @HTTP(method = "get", path = "/user/get", hasBody = true)
dan menggunakan huruf kecil get
untuk melewati batasan di atas.
Jika Anda memiliki pertanyaan, silakan ajukan masalah atau bergabunglah dengan grup QQ untuk mendapatkan masukan.
Nomor grup: 806714302