เอกสารภาษาอังกฤษ
Spring-boot-starter สำหรับการปรับแต่งเพิ่มเติม รองรับการบูรณาการอย่างรวดเร็วและการปรับปรุงคุณสมบัติ
โครงการนี้ยังคงได้รับการปรับปรุงและทำซ้ำอย่างต่อเนื่อง และยินดีให้ทุกคนส่งปัญหาและประชาสัมพันธ์ได้ โปรดให้ดาวแก่เรา ดาวของคุณคือแรงจูงใจของเราในการอัปเดตอย่างต่อเนื่อง!
ที่อยู่โครงการ Github: 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 ;
}
Interceptor ที่ใช้คือ 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
ของ interceptor จะถูกแทรกโดยอัตโนมัติตามค่า accessKeyId()
และ accessKeySecret()
ของคำอธิบายประกอบ @Sign
หาก @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
: ลองอีกครั้งเมื่อมีข้อยกเว้น IO เกิดขึ้นOCCUR_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 >
Global resilience4j ดาวน์เกรดเซอร์กิตเบรกเกอร์สามารถเปิดใช้งานได้ผ่านการกำหนดค่าต่อไปนี้:
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
Interceptor แบบโกลบอลและกำหนดค่าให้เป็น 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
ส่วนประกอบสนับสนุนโรงงาน call adapter ทั่วโลกผ่านการกำหนดค่า 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
ส่วนกลางผ่าน retrofit.global-converter-factories
ค่าเริ่มต้นคือ retrofit2.converter.jackson.JacksonConverterFactory
หากคุณต้องการแก้ไขการกำหนดค่า 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
รองรับ meta-annotations, inheritance และ @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