日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Boot项目整合Retrofit最佳实践,最优雅的HTTP客户端工具!

發布時間:2025/3/20 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Boot项目整合Retrofit最佳实践,最优雅的HTTP客户端工具! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達今日推薦:2020年7月程序員工資統計,平均14357元,又跌了,扎心個人原創100W+訪問量博客:點擊前往,查看更多

轉自:六點半起床,

鏈接:juejin.im/post/6854573211426750472

大家都知道 OKHttp 是一款由 Square?公司開源的 Java 版本 HTTP 客戶端工具。實際上,Square?公司還開源了基于 OKHttp?進一步封裝的 Retrofit?工具,用來支持通過接口的方式發起 HTTP?請求。如果你的項目中還在直接使用 RestTemplate 或者 OKHttp?,或者基于它們封裝的 HttpUtils,那么你可以嘗試使用 Retrofit。

retrofit-spring-boot-starter 實現了 Retrofit 與 spring-boot 框架快速整合,并且支持了部分功能增強,從而極大的簡化 spring-boot 項目下 HTTP?接口調用開發。接下來我們直接通過 retrofit-spring-boot-starter,來看看 spring-boot 項目發送 HTTP?請求有多簡單。

Retrofit 官方并沒有提供與 spring-boot 快速整合的 starter。retrofit-spring-boot-starter 是筆者封裝的,已在生產環境使用,非常穩定。造輪子不易,跪求各位大佬 star。

項目源碼:retrofit-spring-boot-starter

https://github.com/LianjiaTech/retrofit-spring-boot-starter

引入依賴

<dependency><groupId>com.github.lianjiatech</groupId><artifactId>retrofit-spring-boot-starter</artifactId><version>2.0.2</version> </dependency>

配置 @RetrofitScan 注解

你可以給帶有?@Configuration 的類配置 @RetrofitScan,或者直接配置到 spring-boot 的啟動類上。代碼如下:

@SpringBootApplication @RetrofitScan("com.github.lianjiatech.retrofit.spring.boot.test") public?class?RetrofitTestApplication?{public static void main(String[] args) {SpringApplication.run(RetrofitTestApplication.class, args);} }

定義http接口

接口必須使用 @RetrofitClient 注解標記!

@RetrofitClient(baseUrl = "${test.baseUrl}") public?interface?HttpApi?{@GET("person")Result<Person> getPerson(@Query("id") Long id); }

HTTP 相關注解可參考?Retrofit 官方文檔:https://square.github.io/retrofit/。

注入使用

將接口注入到其它 Service 中即可使用。

@Service public?class?TestService?{@Autowiredprivate?HttpApi?httpApi;public void test() {// 通過 httpApi 發起 HTTP 請求} }

只要通過上述幾個步驟,就能實現通過接口發送 HTTP 請求了,真的很簡單。如果你在 spring-boot 項目里面使用過 MyBatis,相信你對這種使用方式會更加熟悉。接下來我們繼續介紹一下 retrofit-spring-boot-starter 更高級一點的功能。

注解式攔截器

很多時候,我們希望某個接口下的某些 HTTP?請求執行統一的攔截處理邏輯。這個時候可以使用注解式攔截器。使用的步驟主要分為2步:

  • 繼承 BasePathMatchInterceptor 編寫攔截處理器;

  • 接口上使用 @Intercept 進行標注。

  • 下面以給指定請求的 URL 后面拼接 timestamp 時間戳為例,介紹下如何使用注解式攔截器。

    繼承 BasePathMatchInterceptor 編寫攔截處理器

    @Component public?class?TimeStampInterceptor?extends?BasePathMatchInterceptor?{@Overridepublic Response doIntercept(Chain chain) throws IOException {Request request = chain.request();HttpUrl url = request.url();long timestamp = System.currentTimeMillis();HttpUrl newUrl = url.newBuilder().addQueryParameter("timestamp", String.valueOf(timestamp)).build();Request newRequest = request.newBuilder().url(newUrl).build();return chain.proceed(newRequest);} }

    接口上使用 @Intercept 進行標注

    @RetrofitClient(baseUrl = "${test.baseUrl}") @Intercept(handler = TimeStampInterceptor.class, include = {"/api/**"}, exclude = "/api/test/savePerson") public?interface?HttpApi?{@GET("person")Result<Person>?getPerson(@Query("id")?Long?id);@POST("savePerson")Result<Person> savePerson(@Body Person person); }

    上面的 @Intercept 配置表示:攔截 HttpApi 接口下 /api/** 路徑下(排除 /api/test/savePerson)的請求,攔截處理器使用 TimeStampInterceptor。

    擴展注解式攔截器

    有的時候,我們需要在攔截注解動態傳入一些參數,然后再執行攔截的時候需要使用這個參數。這種時候,我們可以擴展實現自定義攔截注解。自定義攔截注解必須使用 @InterceptMark 標記,并且注解中必須包括 include()、exclude()、handler() 屬性信息。使用的步驟主要分為3步:

  • 自定義攔截注解;

  • 繼承 BasePathMatchInterceptor 編寫攔截處理器;

  • 接口上使用自定義攔截注解。

  • 例如我們需要在請求頭里面動態加入 accessKeyId、accessKeySecret 簽名信息才能正常發起 http 請求,這個時候可以自定義一個加簽攔截器注解 @Sign 來實現。下面以自定義 @Sign 攔截注解為例進行說明。

    自定義@Sign注解

    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @InterceptMark public @interface Sign {/*** 密鑰 key* 支持占位符形式配置。** @return*/String accessKeyId();/*** 密鑰* 支持占位符形式配置。** @return*/String accessKeySecret();/*** 攔截器匹配路徑** @return*/String[] include() default {"/**"};/*** 攔截器排除匹配,排除指定路徑攔截** @return*/String[] exclude() default {};/*** 處理該注解的攔截器類*?優先從 Spring 容器獲取對應的 Bean,如果獲取不到,則使用反射創建一個!** @return*/Class<? extends BasePathMatchInterceptor> handler() default SignInterceptor.class; }

    擴展自定義攔截注解有以下2點需要注意:

  • 自定義攔截注解必須使用 @InterceptMark 標記;

  • 注解中必須包括 include()、exclude()、handler() 屬性信息。


  • 實現 SignInterceptor

    @Component public?class?SignInterceptor?extends?BasePathMatchInterceptor?{private?String?accessKeyId;private String accessKeySecret;public void setAccessKeyId(String accessKeyId) {this.accessKeyId = accessKeyId;}public void setAccessKeySecret(String accessKeySecret) {this.accessKeySecret = accessKeySecret;}@Overridepublic Response doIntercept(Chain chain) throws IOException {Request request = chain.request();Request newReq = request.newBuilder().addHeader("accessKeyId", accessKeyId).addHeader("accessKeySecret", accessKeySecret).build();return chain.proceed(newReq);} }

    上述 accessKeyId?和?accessKeySecret?字段值會依據?@Sign?注解的?accessKeyId()?和?accessKeySecret()?值自動注入。如果?@Sign?指定的是占位符形式的字符串,則會取配置屬性值進行注入。另外,accessKeyId?和?accessKeySecret?字段必須提供?setter?方法。

    接口上使用 @Sign

    @RetrofitClient(baseUrl = "${test.baseUrl}") @Sign(accessKeyId = "${test.accessKeyId}", accessKeySecret = "${test.accessKeySecret}", exclude = {"/api/test/person"}) public?interface?HttpApi?{@GET("person")Result<Person>?getPerson(@Query("id")?Long?id);@POST("savePerson")Result<Person> savePerson(@Body Person person); }

    連接池管理

    默認情況下,所有通過 Retrofit 發送的 HTTP 請求都會使用 max-idle-connections=5 keep-alive-second=300 的默認連接池。當然,我們也可以在配置文件中配置多個自定義的連接池,然后通過 @RetrofitClient 的 poolName 屬性來指定使用。比如我們要讓某個接口下的請求全部使用 poolName=test1 的連接池,代碼實現如下:

    1. 配置連接池。

    retrofit:# 連接池配置pool:test1:max-idle-connections: 3keep-alive-second: 100test2:max-idle-connections: 5keep-alive-second:?50

    2. 通過 @RetrofitClient 的 poolName 屬性來指定使用的連接池。

    @RetrofitClient(baseUrl = "${test.baseUrl}", poolName="test1") public?interface?HttpApi?{@GET("person")Result<Person> getPerson(@Query("id") Long id); }

    日志打印

    很多情況下,我們希望將 HTTP 請求日志記錄下來。通過 @RetrofitClient 的 logLevel 和 logStrategy 屬性,您可以指定每個接口的日志打印級別以及日志打印策略。

    retrofit-spring-boot-starter 支持了5種日志打印級別(ERROR、WARN、INFO、DEBUG、TRACE),默認 INFO。支持了4種日志打印策略(NONE、BASIC、HEADERS、BODY),默認 BASIC。4種日志打印策略含義如下:

  • NONE:無日志;

  • BASIC:Request 與 Response 日志;

  • HEADERS:Request 與 Response 日志,帶 HEADER;

  • BODY:Request 與 Response 日志,帶 HEADER 與 BODY(可選)。

  • retrofit-spring-boot-starter 默認使用了 DefaultLoggingInterceptor 執行真正的日志打印功能,其底層就是 OKHttp 原生的 HttpLoggingInterceptor。當然,你也可以自定義實現自己的日志打印攔截器,只需要繼承 BaseLoggingInterceptor(具體可以參考 DefaultLoggingInterceptor 的實現),然后在配置文件中進行相關配置即可。

    retrofit:# 日志打印攔截器logging-interceptor:?com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor

    HTTP 異常信息格式化器

    當出現 HTTP 請求異常時,原始的異常信息可能閱讀起來并不友好,因此 retrofit-spring-boot-starter 提供了 HTTP?異常信息格式化器,用來美化輸出 HTTP?請求參數,默認使用 DefaultHttpExceptionMessageFormatter 進行請求數據格式化。你也可以進行自定義,只需要繼承 BaseHttpExceptionMessageFormatter,再進行相關配置即可。

    retrofit:# Http異常信息格式化器http-exception-message-formatter:?com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultHttpExceptionMessageFormatter

    調用適配器 CallAdapter

    Retrofit 可以通過調用適配器 CallAdapterFactory 將 Call<T> 對象適配成接口方法的返回值類型。retrofit-spring-boot-starter 擴展兩種 CallAdapterFactory 實現:

  • BodyCallAdapterFactory

    • 默認啟用,可通過配置 retrofit.enable-body-call-adapter=false 關閉;

    • 同步執行 HTTP?請求,將響應體內容適配成接口方法的返回值類型實例;

    • 除了 Retrofit.Call<T>、Retrofit.Response<T>、java.util.concurrent.CompletableFuture<T> 之外,其它返回類型都可以使用該適配器。

    • ResponseCallAdapterFactory

      • 默認啟用,可通過配置 retrofit.enable-response-call-adapter=false 關閉;

      • 同步執行 HTTP?請求,將響應體內容適配成 Retrofit.Response<T> 返回;

      • 如果方法的返回值類型為 Retrofit.Response<T>,則可以使用該適配器。

      Retrofit 自動根據方法返回值類型選用對應的?CallAdapterFactory?執行適配處理!加上?Retrofit 默認的?CallAdapterFactory,可支持多種形式的方法返回值類型:

      • Call<T>: 不執行適配處理,直接返回 Call<T> 對象;

      • CompletableFuture<T>: 將響應體內容適配成 CompletableFuture<T> 對象返回

      • Void: 不關注返回類型可以使用 Void。如果 HTTP?狀態碼不是2xx,直接報錯;

      • Response<T>: 將響應內容適配成 Response<T> 對象返回;

      • 其他任意 Java 類型:將響應體內容適配成一個對應的 Java 類型對象返回,如果 HTTP?狀態碼不是 2xx,直接報錯。

      /*** Call<T>* 不執行適配處理,直接返回 Call<T> 對象* @param id* @return*/ @GET("person") Call<Result<Person>> getPersonCall(@Query("id") Long id);/*** CompletableFuture<T>* 將響應體內容適配成 CompletableFuture<T> 對象返回* @param id* @return*/ @GET("person") CompletableFuture<Result<Person>> getPersonCompletableFuture(@Query("id") Long id);/*** Void* 不關注返回類型可以使用 Void。如果http狀態碼不是2xx,直接拋錯!* @param id* @return*/ @GET("person") Void getPersonVoid(@Query("id") Long id);/*** Response<T>* 將響應內容適配成Response<T>對象返回* @param id* @return*/ @GET("person") Response<Result<Person>> getPersonResponse(@Query("id") Long id);/*** 其他任意Java類型* 將響應體內容適配成一個對應的Java類型對象返回,如果http狀態碼不是2xx,直接拋錯!* @param id* @return*/ @GET("person")Result<Person>?getPerson(@Query("id")?Long?id);

      我們也可以通過繼承 CallAdapter.Factory 擴展實現自己的 CallAdapter;然后將自定義的 CallAdapterFactory 配置成 Spring 的 Bean!

      自定義配置的 CallAdapter.Factory 優先級更高!


      數據轉碼器 Converter

      Retrofit 使用 Converter 將 @Body 注解標注的對象轉換成請求體,將響應體數據轉換成一個 Java 對象,可以選用以下幾種 Converter:

      • Gson:com.squareup.Retrofit:converter-gson

      • Jackson:com.squareup.Retrofit:converter-jackson

      • Moshi:com.squareup.Retrofit:converter-moshi

      • Protobuf:com.squareup.Retrofit:converter-protobuf

      • Wire:com.squareup.Retrofit:converter-wire

      • Simple XML:com.squareup.Retrofit:converter-simplexml

      retrofit-spring-boot-starter 默認使用的是 Jackson 進行序列化轉換!如果需要使用其它序列化方式,在項目中引入對應的依賴,再把對應的 ConverterFactory 配置成 Spring 的 Bean 即可。

      我們也可以通過繼承 Converter.Factory 擴展實現自己的 Converter;然后將自定義的 Converter.Factory 配置成 Spring 的 Bean!

      自定義配置的 Converter.Factory 優先級更高!


      全局攔截器 BaseGlobalInterceptor

      如果我們需要對整個系統的的 HTTP?請求執行統一的攔截處理,可以自定義實現全局攔截器 BaseGlobalInterceptor, 并配置成 Spring 中的 Bean!例如我們需要在整個系統發起的 HTTP?請求,都帶上來源信息。

      @Component public class SourceInterceptor extends BaseGlobalInterceptor {@Overridepublic Response doIntercept(Chain chain) throws IOException {Request request = chain.request();Request newReq = request.newBuilder().addHeader("source", "test").build();return chain.proceed(newReq);} }

      結語

      至此,spring-boot 項目下最優雅的 HTTP?客戶端工具介紹就結束了,更多詳細信息可以參考官方文檔:Retrofit?以及?retrofit-spring-boot-starter。實現原理解讀可查看基于 Retrofit 實現自己的輕量級 HTTP?調用工具。

      最后,再附上我歷時三個月總結的?Java 面試 + Java 后端技術學習指南,筆者這幾年及春招的總結,github 1.4k star,拿去不謝!

      下載方式1.?首先掃描下方二維碼 2.?后臺回復「Java面試」即可獲取

    總結

    以上是生活随笔為你收集整理的Spring Boot项目整合Retrofit最佳实践,最优雅的HTTP客户端工具!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。