Document anglais
Spring-boot-starter pour la mise à niveau, prenant en charge une intégration rapide et l'amélioration des fonctionnalités .
Le projet continue d'être optimisé et itéré, et tout le monde est invité à soumettre des PROBLÈMES et des PR ! S'il vous plaît, donnez-nous une étoile. Votre étoile est notre motivation pour des mises à jour continues !
Adresse du projet Github : https://github.com/LianjiaTech/retrofit-spring-boot-starter
Adresse du projet gîte : https://gitee.com/lianjiatech/retrofit-spring-boot-starter
Exemple de démo : https://github.com/ismart-yuxi/retrofit-spring-boot-demo
Merci à
@ismart-yuxi
d'avoir écrit l'exemple de démo pour ce projet
< dependency >
< groupId >com.github.lianjiatech</ groupId >
< artifactId >retrofit-spring-boot-starter</ artifactId >
< version >3.1.3</ version >
</ dependency >
Si le démarrage échoue, il existe une forte probabilité qu'il y ait un conflit de dépendances. Veuillez introduire ou exclure les dépendances associées .
L'interface doit être marquée avec @RetrofitClient
! Pour les informations relatives à HTTP, veuillez vous référer à la documentation officielle : documentation officielle de mise à niveau.
@ RetrofitClient ( baseUrl = "${test.baseUrl}" )
public interface UserService {
/**
* 根据id查询用户姓名
*/
@ POST ( "getName" )
String getName ( @ Query ( "id" ) Long id );
}
Remarque : les chemins de requête de méthode doivent commencer par
/
avec prudence . PourRetrofit
, sibaseUrl=http://localhost:8080/api/test/
et que le chemin de requête de la méthode estperson
, le chemin de requête complet de la méthode est :http://localhost:8080/api/test/person
. Si le chemin de requête de la méthode est/person
, le chemin de requête complet de la méthode est :http://localhost:8080/person
.
Injectez l'interface dans d'autres Services et utilisez-la !
@ Service
public class BusinessService {
@ Autowired
private UserService userService ;
public void doBusiness () {
// call userService
}
}
Par défaut, le chemin d'analyse SpringBoot
est automatiquement utilisé pour l'enregistrement RetrofitClient
. Vous pouvez également ajouter @RetrofitScan
à la classe de configuration pour spécifier manuellement le chemin d'analyse.
Les annotations liées aux requêtes HTTP
utilisent toutes les annotations natives Retrofit
. Voici une explication simple :
Classement des annotations | Annotations prises en charge |
---|---|
Méthode de demande | @GET @HEAD @POST @PUT @DELETE @OPTIONS @HTTP |
En-tête de requête | @Header @HeaderMap @Headers |
Paramètres de requête | @Query @QueryMap @QueryName |
paramètre de chemin | @Path |
paramètres codés sous forme | @Field @FieldMap @FormUrlEncoded |
Corps de la demande | @Body |
Téléchargement de fichiers | @Multipart @Part @PartMap |
paramètres d'URL | @Url |
Pour des informations détaillées, veuillez vous référer à la documentation officielle : documentation officielle de mise à niveau
Le composant prend en charge plusieurs attributs configurables pour faire face à différents scénarios commerciaux. Les attributs de configuration spécifiques pris en charge et les valeurs par défaut sont les suivants :
Remarque : L'application n'a besoin que de configurer les éléments de configuration à modifier !
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
Si vous avez uniquement besoin de modifier le délai d'expiration de OkHttpClient
, vous pouvez le modifier via les champs liés à @RetrofitClient
ou modifier la configuration globale du délai d'expiration.
Si vous devez modifier d'autres configurations OkHttpClient
, vous pouvez le faire en personnalisant OkHttpClient
. Les étapes sont les suivantes :
Implémentez l'interface SourceOkHttpClientRegistrar
et appelez SourceOkHttpClientRegistry#register()
pour enregistrer 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 ());
}
}
Spécifiez OkHttpClient
à utiliser par l'interface actuelle via @RetrofitClient.sourceOkHttpClient
@ RetrofitClient ( baseUrl = "${test.baseUrl}" , sourceOkHttpClient = "customOkHttpClient" )
public interface CustomOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
Remarque : Le composant n'utilisera pas directement le
OkHttpClient
spécifié, mais en créera un nouveau basé sur leOkHttpClient
.
Le composant fournit un intercepteur d'annotations qui prend en charge l'interception basée sur la correspondance du chemin d'URL. Les étapes à suivre sont les suivantes :
BasePathMatchInterceptor
@Intercept
pour spécifier l'intercepteur à utiliserSi vous devez utiliser plusieurs intercepteurs, marquez simplement plusieurs annotations
@Intercept
sur l'interface.
BasePathMatchInterceptor
pour écrire le processeur d'interception @ 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 ();
}
}
Par défaut, le composant définit automatiquement scope
de BasePathMatchInterceptor
sur prototype
. Cette fonctionnalité peut être désactivée via retrofit.auto-set-prototype-scope-for-path-math-interceptor=false
. Après la fermeture, vous devez définir manuellement scope
sur prototype
.
@ Component
@ Scope ( "prototype" )
public class PathMatchInterceptor extends BasePathMatchInterceptor {
}
@Intercept
pour annoter l'interface @ 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 );
}
La configuration @Intercept
ci-dessus signifie : intercepter les requêtes sous le chemin /api/user/**
sous l'interface InterceptorUserService
(à l'exclusion de /api/user/getUser
), et le processeur d'interception utilise PathMatchInterceptor
.
Parfois, nous devons transmettre dynamiquement certains paramètres dans "l'annotation d'interception", puis utiliser ces paramètres lors de l'interception. À l'heure actuelle, nous pouvons utiliser des « annotations d'interception personnalisées ». Les étapes sont les suivantes :
@InterceptMark
doit être utilisée et l'annotation doit inclure les champs include、exclude、handler
.BasePathMatchInterceptor
pour écrire le processeur d'interception Par exemple, nous devons « ajouter dynamiquement les informations de signature accessKeyId
et accessKeySecret
à l'en-tête de la requête avant de lancer une requête HTTP ». Dans ce cas, nous pouvons personnaliser @Sign
pour y parvenir.
@Sign
personnalisée @ 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 ;
}
L'intercepteur utilisé est SignInterceptor
spécifié dans l'annotation @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 ();
}
}
Remarque : Les champs
accessKeyId
etaccessKeySecret
doivent fournir des méthodessetter
.
accessKeyId
et accessKeySecret
de l'intercepteur seront automatiquement injectées en fonction accessKeyId()
et accessKeySecret()
de l'annotation @Sign
. Si @Sign
spécifie une chaîne sous la forme d'un espace réservé, le La valeur de l'attribut de configuration sera utilisée pour l'injection.
@Sign
sur l'interface @ RetrofitClient ( baseUrl = "${test.baseUrl}" )
@ Sign ( accessKeyId = "${test.accessKeyId}" , accessKeySecret = "${test.accessKeySecret}" , include = "/api/user/getAll" )
public interface InterceptorUserService {
/**
* 查询所有用户信息
*/
@ GET ( "getAll" )
Response < List < User >> getAll ();
}
Le composant prend en charge l'impression globale des journaux et l'impression déclarative des journaux.
Par défaut, l'impression globale des journaux est activée et la configuration par défaut est la suivante :
retrofit :
# 全局日志打印配置
global-log :
# 启用日志打印
enable : true
# 全局日志打印级别
log-level : info
# 全局日志打印策略
log-strategy : basic
# 是否聚合打印请求日志
aggregate : true
# 日志名称,默认为{@link LoggingInterceptor} 的全类名
logName : com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor
Les significations des quatre stratégies d'impression de journaux sont les suivantes :
NONE
: Aucun journal.BASIC
: enregistre les lignes de demande et de réponse.HEADERS
: enregistre les lignes de demande et de réponse ainsi que leurs en-têtes respectifs.BODY
: enregistre les lignes de demande et de réponse ainsi que leurs en-têtes et corps respectifs (le cas échéant). Si vous n'avez besoin d'imprimer des journaux que pour certaines requêtes, vous pouvez utiliser l'annotation @Logging
sur l'interface ou la méthode appropriée.
Si vous devez modifier le comportement d'impression du journal, vous pouvez hériter de LoggingInterceptor
et le configurer en tant que Spring bean
.
La prise en charge des composants prend en charge les nouvelles tentatives globales et les nouvelles tentatives déclaratives.
La nouvelle tentative globale est désactivée par défaut et les éléments de configuration par défaut sont les suivants :
retrofit :
# 全局重试配置
global-retry :
# 是否启用全局重试
enable : false
# 全局重试间隔时间
interval-ms : 100
# 全局最大重试次数
max-retries : 2
# 全局重试规则
retry-rules :
- response_status_not_2xx
- occur_io_exception
Les règles de nouvelle tentative prennent en charge trois configurations :
RESPONSE_STATUS_NOT_2XX
: Réessayez lorsque le code d'état de la réponse n'est pas 2xx
OCCUR_IO_EXCEPTION
: Réessayez lorsqu'une exception IO se produitOCCUR_EXCEPTION
: réessayez lorsqu'une exception se produit Si seules certaines requêtes doivent être réessayées, vous pouvez utiliser l'annotation @Retry
sur l'interface ou la méthode correspondante.
Si vous devez modifier le comportement des nouvelles tentatives de demande, vous pouvez hériter RetryInterceptor
et le configurer en tant que Spring bean
.
La rétrogradation du disjoncteur est désactivée par défaut et prend actuellement en charge les implémentations sentinel
et resilience4j
.
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
Configurez degrade-type=sentinel
pour l'activer, puis déclarez l'annotation @SentinelDegrade
sur l'interface ou la méthode appropriée.
N'oubliez pas d'introduire manuellement les dépendances Sentinel
:
< dependency >
< groupId >com.alibaba.csp</ groupId >
< artifactId >sentinel-core</ artifactId >
< version >1.6.3</ version >
</ dependency >
De plus, la rétrogradation globale des disjoncteurs Sentinel
est également prise en charge :
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
# 全局sentinel降级配置
global-sentinel-degrade :
# 是否开启
enable : true
# ...其他sentinel全局配置
Configurez degrade-type=resilience4j
pour l'activer. Déclarez ensuite @Resilience4jDegrade
sur l'interface ou la méthode appropriée.
Pensez à introduire manuellement Resilience4j
:
< dependency >
< groupId >io.github.resilience4j</ groupId >
< artifactId >resilience4j-circuitbreaker</ artifactId >
< version >1.7.1</ version >
</ dependency >
La dégradation globale du disjoncteur Resilience4j peut être activée via la configuration suivante :
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : resilience4j
# 全局resilience4j降级配置
global-resilience4j-degrade :
# 是否开启
enable : true
# 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置
circuit-breaker-config-name : defaultCircuitBreakerConfig
Gestion de la configuration des disjoncteurs :
Implémentez l'interface CircuitBreakerConfigRegistrar
et enregistrez 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
est spécifié par circuitBreakerConfigName
. Incluez retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name
ou @Resilience4jDegrade.circuitBreakerConfigName
Si l'utilisateur doit utiliser une autre implémentation de dégradation du disjoncteur, héritez de BaseRetrofitDegrade
et configurez-le Spring Bean
.
Si @RetrofitClient
ne définit pas fallback
ou fallbackFactory
, lorsque le disjoncteur est déclenché, RetrofitBlockException
sera levée directement. Les utilisateurs peuvent personnaliser la valeur de retour de la méthode lors de la fusion en définissant fallback
ou fallbackFactory
.
Remarque : La classe
fallback
doit être la classe d'implémentation de l'interface actuelle,fallbackFactory
doit êtreFallbackFactory<T>
et le type de paramètre générique doit être le type d'interface actuel. De plus, les instancesfallback
etfallbackFactory
doivent être configurées en tant queSpring Bean
.
Par rapport au fallbackFactory
fallback
est qu'il peut détecter la cause anormale (cause) de chaque disjoncteur. L'exemple de référence est le suivant :
@ 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 ;
}
};
}
}
Lorsqu'une erreur de requête HTTP
se produit (y compris une exception ou si les données de réponse ne répondent pas aux attentes), le décodeur d'erreur peut décoder les informations liées à HTTP
en une exception personnalisée. Vous pouvez spécifier le décodeur d'erreur de l'interface actuelle dans l'annotation errorDecoder errorDecoder()
de @RetrofitClient
. Un décodeur d'erreur personnalisé doit implémenter l'interface ErrorDecoder
:
ServiceInstanceChooser
Les utilisateurs peuvent implémenter eux-mêmes l'interface ServiceInstanceChooser
, compléter la logique de sélection de l'instance de service et la configurer en tant que Spring Bean
. Pour les applications Spring Cloud
, l'implémentation suivante peut être utilisée.
@ 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
et path
@ RetrofitClient ( serviceId = "user" , path = "/api/user" )
public interface ChooserOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
Si nous devons effectuer un traitement d'interception unifié sur les requêtes HTTP
de l'ensemble du système, nous pouvons implémenter l'intercepteur global GlobalInterceptor
et le configurer comme 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 ();
}
}
Implémentez l'interface NetworkInterceptor
et configurez-la en tant que spring Bean
.
Retrofit
peut adapter l'objet Call<T>
au type de valeur de retour de la méthode d'interface via CallAdapterFactory
. Le composant étend certaines implémentations CallAdapterFactory
:
BodyCallAdapterFactory
HTTP
de manière synchrone et adaptez le contenu du corps de la réponse au type de valeur de retour de la méthode.BodyCallAdapterFactory
, avec la priorité la plus basse.ResponseCallAdapterFactory
HTTP
de manière synchrone, adaptez le contenu du corps de la réponse à Retrofit.Response<T>
et renvoyez-le.ResponseCallAdapterFactory
ne peut être utilisé que si le type de valeur de retour de la méthode est Retrofit.Response<T>
.CallAdapterFactory
lié à la programmation réactive Retrofit
sélectionnera le CallAdapterFactory
correspondant pour effectuer le traitement d'adaptation en fonction du type de valeur de retour de la méthode . Les types de valeur de retour actuellement pris en charge sont les suivants :
String
: adaptez Response Body
en String
et renvoyez-le.Long
/ Integer
/ Boolean
/ Float
/ Double
) : adaptez Response Body
aux types de base ci-dessusJava
: adaptez Response Body
à l'objet Java
correspondant et renvoyez-leCompletableFuture<T>
: Adaptez Response Body
en CompletableFuture<T>
et renvoyez-leVoid
: Vous pouvez utiliser Void
si vous ne vous souciez pas du type de retour.Response<T>
: Adaptez Response
dans l'objet Response<T>
et renvoyez-laCall<T>
: N'effectue pas de traitement d'adaptation et renvoie directement l'objet Call<T>
Mono<T>
: Type de retour réactif Project Reactor
Single<T>
: type de retour réactif Rxjava
(prend en charge Rxjava2/Rxjava3
)Completable
: type de retour réactif Rxjava
, la requête HTTP
n'a pas de corps de réponse (prend en charge Rxjava2/Rxjava3
) CallAdapter
peut être étendu en héritant de CallAdapter.Factory
.
Le composant prend en charge les usines d'adaptateurs d'appel globales via la configuration retrofit.global-call-adapter-factories
:
retrofit :
# 全局转换器工厂(组件扩展的`CallAdaptorFactory`工厂已经内置,这里请勿重复配置)
global-call-adapter-factories :
# ...
Pour chaque interface Java, vous pouvez également spécifier CallAdapter.Factory
utilisé par l'interface actuelle via @RetrofitClient.callAdapterFactories
.
Suggestion : configurer
CallAdapter.Factory
en tant queSpring Bean
Retrofit
utilise Converter
pour convertir l'objet annoté @Body
en Request Body
et convertir Response Body
en objet Java
. Vous pouvez choisir parmi les Converter
suivants :
Le composant prend en charge la configuration du Converter.Factory
global via retrofit.global-converter-factories
. La valeur par défaut est retrofit2.converter.jackson.JacksonConverterFactory
.
Si vous devez modifier la configuration Jackson
, écrasez simplement vous-même la configuration bean
de JacksonConverterFactory
.
retrofit :
# 全局转换器工厂
global-converter-factories :
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
Pour chaque interface Java
, vous pouvez également spécifier Converter.Factory
utilisé par l'interface actuelle via @RetrofitClient.converterFactories
.
Suggestion : configurez
Converter.Factory
en tant queSpring Bean
.
Les annotations telles que @RetrofitClient
, @Retry
, @Logging
et @Resilience4jDegrade
prennent en charge les méta-annotations, l'héritage et @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 ();
}
}
Les URL dynamiques peuvent être implémentées à l'aide de l'annotation @url
. À l’heure actuelle, baseUrl
peut être configuré avec n’importe quelle URL légale. Par exemple : http://github.com/
. Au moment de l'exécution, les requêtes ne seront lancées qu'en fonction de l'adresse @Url
.
Remarque :
@url
doit être placé en première position des paramètres de méthode. De plus,@GET
,@POST
et les autres annotations n'ont pas besoin de définir le chemin du point de terminaison.
@ GET
Map < String , Object > test3 ( @ Url String url , @ Query ( "name" ) String name );
DELETE
ajoute le corps de la requête @ HTTP ( method = "DELETE" , path = "/user/delete" , hasBody = true )
GET
okhttp3
lui-même ne prend pas en charge l'ajout de corps de requête GET
. Le code source est le suivant :
L'auteur a donné des raisons précises, vous pouvez vous référer à : problème
Cependant, si vous avez vraiment besoin de le faire, vous pouvez utiliser : @HTTP(method = "get", path = "/user/get", hasBody = true)
et utiliser les minuscules get
pour contourner les restrictions ci-dessus.
Si vous avez des questions, veuillez soulever un problème ou rejoindre le groupe QQ pour obtenir des commentaires.
Numéro de groupe : 806714302