وثيقة باللغة الإنجليزية
Spring-boot-starter للتحديث، ودعم التكامل السريع وتحسين الميزات .
يستمر تحسين المشروع وتكراره، ونرحب بالجميع لتقديم المشكلات والعلاقات العامة! من فضلك أعطنا نجمة نجمك هو حافزنا للتحديثات المستمرة!
عنوان مشروع جيثب: https://github.com/LianjiaTech/retrofit-spring-boot-starter
عنوان مشروع gitee: https://gitee.com/lianjiatech/retrofit-spring-boot-starter
نموذج العرض التوضيحي: https://github.com/ismart-yuxi/retrofit-spring-boot-demo
شكرًا
@ismart-yuxi
على كتابة النموذج التجريبي لهذا المشروع
< dependency >
< groupId >com.github.lianjiatech</ groupId >
< artifactId >retrofit-spring-boot-starter</ artifactId >
< version >3.1.3</ version >
</ dependency >
في حالة فشل بدء التشغيل، هناك احتمال كبير بوجود تعارض في التبعية، يرجى تقديم التبعيات ذات الصلة أو استبعادها .
يجب أن يتم تمييز الواجهة بالتعليق التوضيحي @RetrofitClient
! للحصول على المعلومات المتعلقة بـ HTTP، يرجى الرجوع إلى الوثائق الرسمية: الوثائق الرسمية التحديثية.
@ RetrofitClient ( baseUrl = "${test.baseUrl}" )
public interface UserService {
/**
* 根据id查询用户姓名
*/
@ POST ( "getName" )
String getName ( @ Query ( "id" ) Long id );
}
ملاحظة: يجب أن تبدأ مسارات طلب الطريقة بـ
/
بحذر . بالنسبة إلىRetrofit
، إذا كانbaseUrl=http://localhost:8080/api/test/
وكان مسار طلب الطريقة هوperson
، فإن مسار الطلب الكامل للطريقة هو:http://localhost:8080/api/test/person
. إذا كان مسار طلب الطريقة هو/person
، فإن مسار الطلب الكامل للطريقة هو:http://localhost:8080/person
.
أدخل الواجهة في الخدمات الأخرى واستخدمها!
@ Service
public class BusinessService {
@ Autowired
private UserService userService ;
public void doBusiness () {
// call userService
}
}
افتراضيًا، يتم استخدام مسار فحص SpringBoot
تلقائيًا لتسجيل RetrofitClient
. يمكنك أيضًا إضافة @RetrofitScan
إلى فئة التكوين لتحديد مسار الفحص يدويًا.
تستخدم جميع التعليقات التوضيحية المتعلقة بطلبات HTTP
التعليقات التوضيحية الأصلية Retrofit
، وفيما يلي شرح بسيط:
تصنيف التعليق التوضيحي | التعليقات التوضيحية المدعومة |
---|---|
طريقة الطلب | @GET @HEAD @POST @PUT @DELETE @OPTIONS @HTTP |
رأس الطلب | @Header @HeaderMap @Headers |
معلمات الاستعلام | @Query @QueryMap @QueryName |
معلمة المسار | @Path |
المعلمات المشفرة بالنموذج | @Field @FieldMap @FormUrlEncoded |
هيئة الطلب | @Body |
تحميل الملف | @Multipart @Part @PartMap |
معلمات URL | @Url |
للحصول على معلومات مفصلة، يرجى الرجوع إلى الوثائق الرسمية: الوثائق الرسمية التحديثية
يدعم المكون سمات متعددة قابلة للتكوين للتعامل مع سيناريوهات الأعمال المختلفة. سمات التكوين المدعومة المحددة والقيم الافتراضية هي كما يلي:
ملاحظة: يحتاج التطبيق فقط إلى تكوين عناصر التكوين المراد تغييرها !
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
إذا كنت بحاجة فقط إلى تعديل مهلة OkHttpClient
، فيمكنك تعديلها من خلال الحقول ذات الصلة @RetrofitClient
أو تعديل تكوين المهلة العامة.
إذا كنت بحاجة إلى تعديل تكوينات أخرى OkHttpClient
، فيمكنك القيام بذلك عن طريق تخصيص OkHttpClient
، والخطوات هي كما يلي:
قم بتنفيذ واجهة SourceOkHttpClientRegistrar
واستدعاء أسلوب SourceOkHttpClientRegistry#register()
لتسجيل 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 ());
}
}
حدد OkHttpClient
الذي ستستخدمه الواجهة الحالية من خلال @RetrofitClient.sourceOkHttpClient
@ RetrofitClient ( baseUrl = "${test.baseUrl}" , sourceOkHttpClient = "customOkHttpClient" )
public interface CustomOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
ملاحظة: لن يستخدم المكون
OkHttpClient
المحدد مباشرة، ولكنه سينشئ مكونًا جديدًا بناءً علىOkHttpClient
.
يوفر المكون اعتراضًا للتعليقات التوضيحية التي تدعم الاعتراض بناءً على مطابقة مسار URL. الخطوات التي يجب استخدامها هي كما يلي:
BasePathMatchInterceptor
@Intercept
لتحديد المعترض الذي سيتم استخدامهإذا كنت بحاجة إلى استخدام اعتراضات متعددة، فما عليك سوى وضع علامة على تعليقات
@Intercept
المتعددة على الواجهة.
BasePathMatchInterceptor
لكتابة معالج الاعتراض @ 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 ();
}
}
افتراضيًا، يقوم المكون تلقائيًا بتعيين scope
BasePathMatchInterceptor
إلى prototype
. يمكن إيقاف تشغيل هذه الميزة عبر retrofit.auto-set-prototype-scope-for-path-math-interceptor=false
. بعد الإغلاق، تحتاج إلى ضبط scope
يدويًا على prototype
.
@ Component
@ Scope ( "prototype" )
public class PathMatchInterceptor extends BasePathMatchInterceptor {
}
@Intercept
للتعليق على الواجهة @ 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 );
}
يعني تكوين @Intercept
أعلاه: اعتراض الطلبات ضمن المسار /api/user/**
ضمن واجهة InterceptorUserService
(باستثناء /api/user/getUser
)، ويستخدم معالج الاعتراض PathMatchInterceptor
.
في بعض الأحيان، نحتاج إلى تمرير بعض المعلمات ديناميكيًا في "التعليق التوضيحي للاعتراض" ثم استخدام هذه المعلمات عند الاعتراض. في هذا الوقت، يمكننا استخدام "التعليقات التوضيحية للاعتراض المخصص" والخطوات هي كما يلي:
@InterceptMark
، ويجب أن يتضمن التعليق التوضيحي حقول include、exclude、handler
.BasePathMatchInterceptor
لكتابة معالج الاعتراض على سبيل المثال، نحتاج إلى "إضافة معلومات توقيع accessKeyId
و accessKeySecret
ديناميكيًا إلى رأس الطلب قبل بدء طلب HTTP." في هذه الحالة، يمكننا تخصيص التعليق التوضيحي @Sign
لتحقيق ذلك.
@Sign
مخصص @ 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 ;
}
المعترض المستخدم هو SignInterceptor
المحدد في التعليق التوضيحي @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 ();
}
}
ملاحظة: يجب أن يوفر الحقلان
accessKeyId
وaccessKeySecret
أساليبsetter
.
سيتم إدخال قيم حقل accessKeyId
و accessKeySecret
للمعترض تلقائيًا بناءً على قيم accessKeyId()
@Sign
accessKeySecret()
للتعليق @Sign
سيتم استخدام قيمة سمة التكوين للحقن.
@Sign
على الواجهة @ RetrofitClient ( baseUrl = "${test.baseUrl}" )
@ Sign ( accessKeyId = "${test.accessKeyId}" , accessKeySecret = "${test.accessKeySecret}" , include = "/api/user/getAll" )
public interface InterceptorUserService {
/**
* 查询所有用户信息
*/
@ GET ( "getAll" )
Response < List < User >> getAll ();
}
يدعم المكون طباعة السجل العمومي وطباعة السجل التعريفي.
افتراضيًا، يتم تمكين طباعة السجل العام، ويكون التكوين الافتراضي كما يلي:
retrofit :
# 全局日志打印配置
global-log :
# 启用日志打印
enable : true
# 全局日志打印级别
log-level : info
# 全局日志打印策略
log-strategy : basic
# 是否聚合打印请求日志
aggregate : true
# 日志名称,默认为{@link LoggingInterceptor} 的全类名
logName : com.github.lianjiatech.retrofit.spring.boot.log.LoggingInterceptor
معاني استراتيجيات طباعة السجل الأربعة هي كما يلي:
NONE
: لا توجد سجلات.BASIC
: سجلات الطلب وخطوط الاستجابة.HEADERS
: سجلات الطلب وأسطر الاستجابة ورؤوس كل منها.BODY
: سجلات الطلب وأسطر الاستجابة ورؤوسها ونصوصها (إن وجدت). إذا كنت تحتاج فقط إلى طباعة سجلات لبعض الطلبات، فيمكنك استخدام التعليق التوضيحي @Logging
على الواجهة أو الطريقة ذات الصلة.
إذا كنت بحاجة إلى تعديل سلوك طباعة السجل، فيمكنك وراثة LoggingInterceptor
وتكوينه Spring bean
.
يدعم دعم المكونات إعادة المحاولة العامة وإعادة المحاولة التعريفية.
يتم إيقاف إعادة المحاولة العامة بشكل افتراضي، وتكون عناصر التكوين الافتراضية كما يلي:
retrofit :
# 全局重试配置
global-retry :
# 是否启用全局重试
enable : false
# 全局重试间隔时间
interval-ms : 100
# 全局最大重试次数
max-retries : 2
# 全局重试规则
retry-rules :
- response_status_not_2xx
- occur_io_exception
تدعم قواعد إعادة المحاولة ثلاثة تكوينات:
RESPONSE_STATUS_NOT_2XX
: أعد المحاولة عندما لا يكون رمز حالة الاستجابة 2xx
OCCUR_IO_EXCEPTION
: أعد المحاولة عند حدوث استثناء IOOCCUR_EXCEPTION
: أعد المحاولة عند حدوث أي استثناء إذا كانت هناك حاجة إلى إعادة محاولة بعض الطلبات فقط، فيمكنك استخدام التعليق التوضيحي @Retry
على الواجهة أو الطريقة المقابلة.
إذا كنت بحاجة إلى تعديل سلوك إعادة محاولة الطلب، فيمكنك وراثة RetryInterceptor
وتكوينه Spring bean
.
يتم إيقاف تشغيل الإصدار السابق لقاطع الدائرة بشكل افتراضي، ويدعم حاليًا تطبيقات sentinel
و resilience4j
.
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
قم بتكوين degrade-type=sentinel
لتمكينه، ثم قم بإعلان التعليق التوضيحي @SentinelDegrade
على الواجهة أو الطريقة ذات الصلة.
تذكر أن تقوم بإدخال تبعيات Sentinel
يدويًا:
< dependency >
< groupId >com.alibaba.csp</ groupId >
< artifactId >sentinel-core</ artifactId >
< version >1.6.3</ version >
</ dependency >
بالإضافة إلى ذلك، يتم أيضًا دعم الرجوع إلى إصدار سابق لقواطع دوائر Sentinel
العالمية:
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : sentinel
# 全局sentinel降级配置
global-sentinel-degrade :
# 是否开启
enable : true
# ...其他sentinel全局配置
قم بتكوين degrade-type=resilience4j
لتمكينه. ثم أعلن @Resilience4jDegrade
على الواجهة أو الطريقة ذات الصلة.
تذكر أن تقوم بإدخال تبعية Resilience4j
يدويًا:
< dependency >
< groupId >io.github.resilience4j</ groupId >
< artifactId >resilience4j-circuitbreaker</ artifactId >
< version >1.7.1</ version >
</ dependency >
يمكن تمكين الرجوع إلى إصدار سابق لقاطع الدائرة المرنة 4j من خلال التكوين التالي:
retrofit :
# 熔断降级配置
degrade :
# 熔断降级类型。默认none,表示不启用熔断降级
degrade-type : resilience4j
# 全局resilience4j降级配置
global-resilience4j-degrade :
# 是否开启
enable : true
# 根据该名称从#{@link CircuitBreakerConfigRegistry}获取CircuitBreakerConfig,作为全局熔断配置
circuit-breaker-config-name : defaultCircuitBreakerConfig
إدارة تكوين قواطع الدائرة:
قم بتنفيذ واجهة CircuitBreakerConfigRegistrar
وقم بتسجيل 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
بواسطة circuitBreakerConfigName
. قم بتضمين retrofit.degrade.global-resilience4j-degrade.circuit-breaker-config-name
أو @Resilience4jDegrade.circuitBreakerConfigName
إذا كان المستخدم بحاجة إلى استخدام تطبيق آخر لتدهور قاطع الدائرة، فارث BaseRetrofitDegrade
وقم بتكوينه Spring Bean
.
إذا لم يقم @RetrofitClient
بتعيين fallback
أو fallbackFactory
، فسيتم طرح RetrofitBlockException
مباشرة عند تشغيل قاطع الدائرة. يمكن للمستخدمين تخصيص قيمة إرجاع الطريقة عند حدوث الدمج عن طريق تعيين fallback
أو fallbackFactory
.
ملاحظة: يجب أن تكون الفئة
fallback
هي فئة التنفيذ للواجهة الحالية، ويجب أن يكونfallbackFactory
هو فئة التنفيذFallbackFactory<T>
، ويجب أن يكون نوع المعلمة العامة هو نوع الواجهة الحالية. بالإضافة إلى ذلك، يجب تكوين المثيلاتfallback
وfallbackFactory
على أنهاSpring Bean
.
مقارنةً fallbackFactory
fallback
هو أنه يمكنه استشعار السبب (السبب) غير الطبيعي لكل قاطع دائرة، والمثال المرجعي هو كما يلي:
@ 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 ;
}
};
}
}
عند حدوث خطأ في طلب HTTP
(بما في ذلك استثناء أو عدم تلبية بيانات الاستجابة للتوقعات)، يمكن لوحدة فك ترميز الأخطاء فك تشفير المعلومات المتعلقة HTTP
وتحويلها إلى استثناء مخصص. يمكنك تحديد وحدة فك ترميز الأخطاء للواجهة الحالية في التعليق التوضيحي لـ errorDecoder errorDecoder()
الخاص بـ @RetrofitClient
. يحتاج برنامج فك ترميز الأخطاء المخصص إلى تنفيذ واجهة ErrorDecoder
:
ServiceInstanceChooser
يمكن للمستخدمين تنفيذ واجهة ServiceInstanceChooser
بأنفسهم، وإكمال منطق اختيار مثيل الخدمة، وتكوينه باعتباره Spring Bean
. بالنسبة لتطبيقات Spring Cloud
، يمكن استخدام التنفيذ التالي.
@ 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
path
@ RetrofitClient ( serviceId = "user" , path = "/api/user" )
public interface ChooserOkHttpUserService {
/**
* 根据id查询用户信息
*/
@ GET ( "getUser" )
User getUser ( @ Query ( "id" ) Long id );
}
إذا كنا بحاجة إلى إجراء معالجة اعتراض موحدة على طلبات HTTP
للنظام بأكمله، فيمكننا تنفيذ المعترض العالمي GlobalInterceptor
وتكوينه باعتباره 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 ();
}
}
قم بتنفيذ واجهة NetworkInterceptor
وقم بتكوينها spring Bean
.
يمكن Retrofit
تكييف كائن Call<T>
مع نوع قيمة الإرجاع لأسلوب الواجهة من خلال CallAdapterFactory
. يقوم المكون بتوسيع بعض تطبيقات CallAdapterFactory
:
BodyCallAdapterFactory
HTTP
بشكل متزامن وقم بتكييف محتوى نص الاستجابة مع نوع قيمة الإرجاع للطريقة.BodyCallAdapterFactory
، مع الأولوية الدنيا.ResponseCallAdapterFactory
HTTP
بشكل متزامن، وقم بتكييف محتوى نص الاستجابة مع Retrofit.Response<T>
وإعادته.ResponseCallAdapterFactory
فقط إذا كان نوع قيمة إرجاع الطريقة هو Retrofit.Response<T>
.CallAdapterFactory
سيحدد Retrofit
CallAdapterFactory
المقابل لإجراء معالجة التكيف بناءً على نوع قيمة إرجاع الطريقة . أنواع قيمة الإرجاع المدعومة حاليًا هي كما يلي:
String
: قم بتكييف Response Body
مع String
وإعادته.Long
/ Integer
/ Boolean
/ Float
/ Double
): قم بتكييف Response Body
مع الأنواع الأساسية المذكورة أعلاهJava
: قم بتكييف Response Body
مع كائن Java
المقابل وإعادتهCompletableFuture<T>
: قم بتكييف Response Body
في كائن CompletableFuture<T>
وإعادتهVoid
: يمكنك استخدام Void
إذا كنت لا تهتم بنوع الإرجاع.Response<T>
: قم بتكييف Response
مع كائن Response<T>
وإعادتهCall<T>
: لا يقوم بإجراء معالجة التكيف ويعيد كائن Call<T>
مباشرةMono<T>
: نوع الإرجاع التفاعلي Project Reactor
Single<T>
: نوع الإرجاع المستجيب Rxjava
(يدعم Rxjava2/Rxjava3
)Completable
: نوع الإرجاع المستجيب Rxjava
، لا يحتوي طلب HTTP
على نص استجابة (يدعم Rxjava2/Rxjava3
) يمكن تمديد CallAdapter
عن طريق وراثة CallAdapter.Factory
.
يدعم المكون مصانع محولات الاتصال العالمية من خلال تكوين retrofit.global-call-adapter-factories
:
retrofit :
# 全局转换器工厂(组件扩展的`CallAdaptorFactory`工厂已经内置,这里请勿重复配置)
global-call-adapter-factories :
# ...
لكل واجهة Java، يمكنك أيضًا تحديد CallAdapter.Factory
الذي تستخدمه الواجهة الحالية من خلال @RetrofitClient.callAdapterFactories
.
الاقتراح: قم بتكوين
CallAdapter.Factory
Spring Bean
يستخدم Retrofit
Converter
لتحويل كائن @Body
المشروح إلى Request Body
وتحويل Response Body
إلى كائن Java
. يمكنك الاختيار من بين Converter
التالية:
يدعم المكون تكوين Converter.Factory
العالمي من خلال retrofit2.converter.jackson.JacksonConverterFactory
retrofit.global-converter-factories
.
إذا كنت بحاجة إلى تعديل تكوين Jackson
، فما عليك سوى الكتابة فوق تكوين bean
الخاص بـ JacksonConverterFactory
بنفسك.
retrofit :
# 全局转换器工厂
global-converter-factories :
- com.github.lianjiatech.retrofit.spring.boot.core.BasicTypeConverterFactory
- retrofit2.converter.jackson.JacksonConverterFactory
لكل واجهة Java
، يمكنك أيضًا تحديد Converter.Factory
الذي تستخدمه الواجهة الحالية من خلال @RetrofitClient.converterFactories
.
الاقتراح: قم بتكوين
Converter.Factory
Spring Bean
.
التعليقات التوضيحية مثل @RetrofitClient
و @Retry
و @Logging
و @Resilience4jDegrade
تدعم التعليقات التوضيحية الوصفية والميراث و @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 الديناميكية باستخدام التعليق التوضيحي @url
. في الوقت الحالي، يمكن تكوين baseUrl
باستخدام أي عنوان URL قانوني. على سبيل المثال: http://github.com/
. في وقت التشغيل، لن يتم بدء الطلبات إلا بناءً على عنوان @Url
.
ملاحظة: يجب وضع
@url
في الموضع الأول لمعلمات الطريقة، بالإضافة إلى ذلك،@GET
و@POST
والتعليقات التوضيحية الأخرى لا تحتاج إلى تحديد مسار نقطة النهاية.
@ GET
Map < String , Object > test3 ( @ Url String url , @ Query ( "name" ) String name );
DELETE
نص الطلب @ HTTP ( method = "DELETE" , path = "/user/delete" , hasBody = true )
GET
okhttp3
نفسه لا يدعم إضافة نصوص الطلب GET
، وكود المصدر كما يلي:
وقد ذكر المؤلف أسبابا محددة، يمكنك الرجوع إلى: المسألة
ومع ذلك، إذا كنت تريد حقًا القيام بذلك، فيمكنك استخدام: @HTTP(method = "get", path = "/user/get", hasBody = true)
واستخدام الحروف الصغيرة get
لتجاوز القيود المذكورة أعلاه.
إذا كانت لديك أية أسئلة، برجاء طرح مشكلة أو الانضمام إلى مجموعة QQ للحصول على تعليقات.
رقم المجموعة: 806714302