求求你別再用OkHttp呼叫API介面了,快來試試這款HTTP客戶端庫吧

码农Academy發表於2024-02-29

引言

在日常業務開發中,我們時常需要使用一些其他公司的服務,呼叫第三方系統的介面,這時就會涉及到網路請求,通常我們可以使用HttpClientOkHttp等框架去完成網路請求。隨著RESTful API的普及,一個高效、簡潔且易於維護的HTTP客戶端庫顯得尤為關鍵。而本文主要介紹一款強大的網路客戶端庫:Retrofit2

Retrofit2簡介

Retrofit2是什麼?

Retrofit2是一個由Square公司精心打造並開源的JavaAndroid雙平臺適用的RESTful API客戶端庫,其核心構建在效能卓越的OkHttp庫之上。透過精巧的設計原理,Retrofit2將原本複雜的HTTP網路請求過程高度抽象為直觀且型別安全的介面呼叫模式,從而極大地簡化了應用程式與後端API之間的互動邏輯。

開發者利用Retrofit2能夠以註解驅動的方式來宣告和定義API介面,輕鬆指定HTTP方法、URL路徑以及請求引數等關鍵資訊,進而自動生成相應的請求實現程式碼。該框架不僅支援同步及非同步兩種呼叫方式,還內建了對JSON資料序列化和反序列化的自動化處理能力,這意味著無論是傳送請求還是解析響應,都能無縫轉換成或從對應的Java物件進行操作。

此外,Retrofit2具備強大的擴充套件性,允許開發人員根據專案需求定製各種高階功能,如自定義轉換器以適應不同資料格式,新增攔截器以實現全域性請求/響應處理,以及整合多種認證機制,充分滿足現代應用程式中面對複雜網路環境的各種需求。

Retrofit2能做什麼?

Retrofit2的主要功能包括:

  1. 型別安全API設計Retrofit2賦予開發者以宣告式介面定義的方式來確保網路請求的型別安全性。這意味著透過在介面方法上使用註解來精確指定HTTP請求引數和響應資料結構,框架會自動進行型別校驗並確保資料在傳輸過程中嚴格符合預期型別,從而消除型別不匹配引發的執行時錯誤。

  2. 網路請求流程精簡Retrofit2極大地簡化了發起網路請求的步驟。開發人員僅需專注於設計與後端服務互動的API介面及相應的HTTP動作,框架會自動生成底層邏輯程式碼,無需手動編寫建立請求、設定Header或解析響應內容等繁瑣環節,極大地提高了開發效率。

  3. 內建資料轉換機制:為便於資料處理,Retrofit2整合了多種資料轉換器(Converter),能夠輕鬆地將從伺服器接收到的HTTP原始資料流轉換成Java物件,支援常見的資料格式如JSONXML以及其他可透過擴充套件實現的格式,這使得資料模型與實際業務邏輯之間的對映變得直觀且易於管理。

  4. 非同步執行與回撥整合:針對移動應用中避免阻塞UI執行緒的需求,Retrofit2全面支援非同步網路請求。它允許開發者採用回撥函式或者結合RxJava等反應式程式設計庫來優雅地處理非同步任務,確保即便在網路請求執行期間也能保持流暢的使用者體驗和應用效能。

Retrofit2的優點

  1. 程式碼簡化與一致性:透過提供一種宣告式的方式來設計和實現網路請求介面,Retrofit2極大地減少了開發人員在處理網路通訊時所需編寫的重複性程式碼量。開發者僅需關注業務邏輯相關的API描述,無需手動構建和管理複雜的HTTP請求。

  2. 提升可讀性和維護性:框架強調清晰的結構和註解驅動的配置方式,使得網路請求邏輯更加直觀且易於理解,進而提高了程式碼的可讀性和維護性。開發者能夠快速識別並定位各個網路操作的意義和行為。

  3. 型別安全保證:透過整合型別安全的API設計,Retrofit2消除了因引數拼寫錯誤或型別不匹配所引發的執行時異常風險。它確保了資料交換過程中引數型別的正確性,增強了應用的整體健壯性。

  4. 高效穩定整合Retrofit2無縫整合了高效能的OkHttp庫,充分利用了其在網路連線複用、快取策略、失敗重試等方面的效能優勢,從而有效提升了網路請求的執行效率及服務穩定性,為應用程式提供了更強大的網路支援基礎架構。

Retrofit2 VS HttpClient

  1. 現代化的 API 設計
    Retrofit2 使用現代程式設計風格,透過註解定義HTTP請求介面,程式碼簡潔易讀。相比之下,HttpClient需要手動構建Request和處理響應,程式碼結構更為繁瑣。

  2. 自動轉換資料
    Retrofit2 提供了內建或自定義的資料轉換器,如 GsonConverterFactory,可以自動將JSON或其他格式的資料轉換為 Java物件,簡化了資料的序列化和反序列化過程。HttpClient則需要手動處理資料轉換,操作相對繁瑣。

  3. 非同步與同步支援
    Retrofit2 支援同步和非同步兩種網路請求方式,提供了基於CallObservable等型別的非同步呼叫方式,方便結合 RxJava等響應式程式設計框架使用,極大地提升了使用者體驗和應用程式效能。HttpClient在非同步支援方面較為侷限。

  4. 面向介面程式設計
    Retrofit2 透過定義服務介面來描述API端點,使得網路層與其他業務邏輯解耦,提高了程式碼組織性和可測試性。相比之下,HttpClient直接操作 HttpRequestHttpResponse例項,耦合度較高。

  5. 相容性與效能
    官方不再推薦使用Apache HttpClient,而OkHttpRetrofit2 底層依賴庫)經過持續最佳化,在效能、連線複用、快取策略以及對HTTP/2協議的支援等方面表現更優。

  6. 易於擴充套件
    Retrofit2可以很容易地新增攔截器(Interceptor)進行諸如身份驗證、日誌記錄和重試機制等功能的擴充套件。雖然]HttpClient的擴充套件性也很強,但需要更多手工編碼。

  7. 社群活躍與更新頻繁
    Retrofit2OkHttp 社群活躍,更新迭代較快,能快速跟進新的技術和最佳實踐,確保開發者能夠利用最新的技術改進和安全更新。

Retrofit2 在簡化RESTful API客戶端開發、提高效率、易用性、可維護性以及對現代網路特性的支援上均優於舊版的 HttpClient

Retrofit2 VS OkHttp

  1. API 介面定義簡潔明瞭
    Retrofit2 使用註解(Annotations)來描述 HTTP 請求方法、URL、引數等,開發者只需透過定義 Java 介面就能清晰地表達出網路呼叫的意圖。相比之下,OkHttp 需要開發者直接處理複雜的 HTTP 請求構建邏輯。

  2. 自動序列化與反序列化
    Retrofit2 提供了轉換器(Converter)支援,如 GsonConverterFactory、JacksonConverterFactory 等,能夠自動將 JSON 或其他格式的資料轉換為 Java 物件以及相反的操作,極大地簡化了資料處理過程。而 OkHttp 需要開發者手動處理資料轉換。

  3. 同步/非同步模式統一處理
    Retrofit2 不僅支援同步請求,還對非同步請求提供了統一的 Call 或 Observable 返回型別,方便在 Android 中進行非阻塞式程式設計,並且易於結合 RxJava 等響應式庫使用。相比之下,OkHttp 的非同步請求處理需要開發者自行管理。

  4. 豐富的註解體系
    Retrofit2 提供了多種註解以支援不同的請求型別(GET、POST、PUT、DELETE 等)、路徑引數、查詢引數、表單提交、檔案上傳、多部分請求等,可以靈活配置請求內容。而 OkHttp 的使用需要開發者手動構建請求引數和處理響應。

  5. 強大的擴充套件性
    Retrofit2 支援自定義攔截器(Interceptor),可以在請求前後新增額外的業務邏輯,如認證、日誌記錄、快取策略等。同時,可以自由配置 OkHttpClient 例項,充分利用 OkHttp 的所有特性,如連線池、重試機制、HTTP/2 支援等。相比之下,OkHttp 更專注於網路通訊的核心功能。

  6. 程式碼可讀性強
    Retrofit2 將網路請求抽象成一個服務介面的形式,使得程式碼更易於閱讀和維護,提高了整體專案的組織性和整潔度。相比之下,OkHttp 的使用需要開發者更多地關注底層的網路通訊細節。

  7. 降低耦合度
    使用 Retrofit2 可以將網路訪問層與應用的其他元件更好地解耦,使得業務邏輯程式碼更加關注於處理業務本身,而不是如何發起網路請求。相比之下,OkHttp 的使用需要開發者更多地處理網路請求的細節,耦合度較高。

雖然 OkHttp 是一個高效能的 HTTP 客戶端,專注於網路通訊的核心功能,但 Retrofit2 在此基礎上封裝了一層高階抽象,讓開發者能以宣告式的方式編寫網路請求程式碼,降低了複雜度並提升了開發效率。

Retrofit2使用

引入依賴

<dependency>
	<groupId>com.squareup.retrofit2</groupId>
	<artifactId>retrofit</artifactId>
	<version>2.9.0</version>
</dependency>

<!-- 示例使用jackson的converter -->
<dependency>
	<groupId>com.squareup.retrofit2</groupId>
	<artifactId>converter-jackson</artifactId>
	<version>2.9.0</version>
</dependency>

定義API介面

Retrofit框架中,構建與伺服器的通訊介面是透過定義清晰、結構化的API介面來實現的。這個過程涵蓋了詳細指定請求方式、路徑以及相關引數等關鍵資訊。具體來說,每個介面方法代表了一種特定的HTTP互動模式,明確指示了請求型別(如GETPOSTPUTDELETE)和目標URL路徑。

請求方法

在介面方法上應用諸如 @GET@POST@PUT@DELETE等註解是為了精確對映到相應的HTTP動作。

@POST("user/add")

@GET("user/info/{id}")

// 也可以指定查詢引數
@GET("user/list?pageSize=50")
URL操作

利用@Path@Query@Body註解能夠進一步細化介面描述,分別用於設定路徑中的動態變數、查詢字串引數以及HTTP請求體內容。介面方法可以接受不同型別的引數,這些引數會根據註解型別被正確地插入到請求的不同部分。
使用@Path 註解的引數會在實際呼叫時將傳入值插入到URL路徑中相應的位置

@GET("group/{id}/users")  
Call<List<UserInfoResponse>> groupList(@Path("id") int groupId);

還可以透過@Query引數新增查詢引數。

@GET("group/{id}/users")  
Call<List<UserInfoResponse>> groupList(@Path("id") int groupId, @Query("pageSize") Integer pageSize);

對於複雜的查詢引數組合,可以使用Map

@GET("group/{id}/users")  
Call<List<UserInfoResponse>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
請求體

對於請求物件,可以使用@Body註解指定物件作為HTTP請求體。@Body註解通常用於指定將物件作為JSON格式的資料傳輸到伺服器。當您在 Retrofit 介面方法中使用 @Body註解時,Retrofit將會使用內部的轉換器(如GsonConverter 或者 JacksonConverter)將物件轉換為JSON 格式的字串,並將其作為請求的請求體傳送到伺服器。
通常情況下,@Body註解用於POST 或者PUT請求,其中請求的主體包含了要傳輸的物件的JSON表示形式。

@POST("users/new")  
Call<UserInfoResponse> createUser(@Body UserInfoRequest user);

通常情況下 @Body註解用於指定JSON格式的資料傳輸,但Retrofit並不會強制要求請求體的格式必須是JSON。您也可以使用其他格式的資料,例如XML或者純文字,只要在請求體中提供了正確的資料格式,並且伺服器能夠正確地解析這種格式的資料。

表單資料和Multipart請求

方法還可以宣告傳送表單資料和多部分請求資料
使用@FormUrlEncoded@Field或者@FieldMap將傳送表單資料。

  @FormUrlEncoded
  @POST("users/new")
  Call<UserInfoResponse> createUser1(@Field("name") String name, @Field("passowrd") String password);

  @FormUrlEncoded
  @POST("users/new")
  Call<UserInfoResponse> createUser2(@FieldMap Map<String, Object> paramMap);

同時他還支援傳送多部分請求,例如檔案上傳。在方法上使用@Multipart註解用於傳送多部分請求,而引數要使用@Part註解。在Retrofit介面方法中使用@Multipart註解時,Retrofit將會使用multipart/form-data格式來傳送請求,這種格式允許同時上傳文字資料和二進位制檔案資料。

@Multipart  
@POST("user/image")  
Call<UserInfoResponse> updateUser(@Part("image") RequestBody userImage, @Part("imageDesc") RequestBody imageDesc);

@Part註解用於宣告每個部分的內容,其中可以是RequestBody型別的文字或者二進位制資料,也可以是MultipartBody.Part型別的檔案或者其他二進位制資料。這樣的話,就可以透過多個@Part註解來宣告不同型別的部分,以滿足不同的上傳需求

Header資訊

使用@Headers註解為方法設定靜態頭部。

@Headers({  
"Accept: application/json, text/plain, */*",  
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",  
"Cookie:xxxxxx"  
})  
@POST("users/new")  
Call<UserInfoResponse> createUser(@Body UserInfoRequest user);

使用用@Header或者HeaderMap註解動態更新請求頭。必須提供相應的引數給@Header。如果值為 null,則頭部將被省略。否則,將對值呼叫toString,並使用結果。

@POST("users/new")  
Call<UserInfoResponse> createUser(@Header("Cookie") String cookie, @Body UserInfoRequest user);  
  
@POST("users/new")  
Call<UserInfoResponse> createUser2(@HeaderMap Map<String, String> headerMap, @Body UserInfoRequest user);

關於Header引數,我們還可以透過OkHttp的攔截器進行操作。

方法返回值

API介面方法通常返回 Call<T> 型別的物件,這裡的T代表期望從伺服器接收的資料型別。這種方式使得開發者能方便地利用 Retrofit 提供的回撥機制或其他響應式程式設計庫(如RxJava)來處理網路請求的結果,從而確保了對非同步操作的良好控制和管理。

public interface MyClientService {
    @POST("test/add")
    Call<TestResponse> addTest(@Body TestRequest testRequest);

	@GET("group/{id}/users")
	Call<List<User>> groupList(@Path("id") int groupId);
}

建立Retrofit例項

Retrofit框架的核心元件是Retrofit例項。Retrofit例項作為整個框架的心臟,不僅負責搭建網路請求所需的基礎設施,還承擔起發起請求、轉換資料和管理響應生命週期的任務。

Retrofit retrofit = new Retrofit.Builder()
				// 設定 API 的基礎 URL
                .baseUrl("http://localhost:8080/coderacademy/") 
                .addConverterFactory(JacksonConverterFactory.create())
                .build();
baseUrl設定

其中baseUrl用於指定請求伺服器的根地址或者API的基礎路徑。Retrofit會自動將baseUrl和方法註解中的相對路徑結合起來生成實際請求的完整URL。例如對上述示例中:

public interface MyClientService {
    @POST("test/add")
    Call<TestResponse> addTest(@Body TestRequest testRequest);
}

最終的請求url為:localhost:8080/coderacademy/test/add

關於baseUrl的設定有一些注意事項:

  • baseUrl設定必須以/結尾,否則彙報錯。
    image.png

  • 請求方法中的相對路徑(不以"/"開頭),將會正確附加在以斜槓結尾的 baseUrl 的路徑後面。這確保了正確的 URL 結果。如baseUrlhttp://localhost:8080/coderacademy/, 方法url為test/add,則最終的路徑為:localhost:8080/coderacademy/test/add

  • 請求方法中的絕對路徑(以"/"開頭),忽略baseUrl中的路徑元件,只保留host部分,最終的URL將只包含baseUrl的主機部分和方法的路徑。如baseUrlhttp://localhost:8080/coderacademy/, 方法url為/test/add,則最終的路徑為:localhost:8080/test/add

  • 請求方法中的路徑可以是完整的URL,如果方法路徑是完整的URL,則會替換baseUrl。如baseUrl為http://localhost:8080/coderacademy/,而方法url為http://localhost:8081/coderacademy/test/add,則最終的url為:http://localhost:8081/coderacademy/test/add

Converter設定

Retrofit預設只能將HTTP響應主體反序列化為OkHttpResponseBody型別,並且只能接受其RequestBody型別用於@Body註解。為了支援其他型別,可以新增轉換器。

官方提供了8種轉換器:

轉換器 功能 使用依賴
Gson 將 JSON 資料轉換為 Java 物件,以及將 Java 物件轉換為 JSON 資料。 com.squareup.retrofit2:converter-gson
Jackson 將JSON資料轉換為 Java 物件,以及將 Java 物件轉換為 JSON 資料。 com.squareup.retrofit2:converter-jackson
Moshi 將 JSON 資料轉換為 Java 物件,以及將 Java 物件轉換為 JSON 資料。 com.squareup.retrofit2:converter-moshi
Protobuf 將 Protocol Buffers 資料轉換為 Java 物件,以及將 Java 物件轉換為 Protocol Buffers 資料。 com.squareup.retrofit2:converter-protobuf
Wire 將 Wire 資料轉換為 Java 物件,以及將 Java 物件轉換為 Wire 資料。 com.squareup.retrofit2:converter-wire
Simple XML 將 XML 資料轉換為 Java 物件,以及將 Java 物件轉換為 XML 資料。 com.squareup.retrofit2:converter-simplexml
JAXB 將 XML 資料轉換為 Java 物件,以及將 Java 物件轉換為 XML 資料。 com.squareup.retrofit2:converter-jaxb
Scalars 將原始型別、包裝型別和字串轉換為 RequestBody,以及將 ResponseBody 轉換為原始型別、包裝型別和字串。 com.squareup.retrofit2:converter-scalars
除了官方提供的這幾種轉換器以外,如果使用了Retrofit預設不支援的內容格式的API 進行通訊(例如YAMLTXT、自定義格式),或者使用不同的庫來實現現有格式(請求與響應是不同的格式),我們也可以實現自定義轉換器。

除此之外Retrofit還可以跟OkHttpClient搭配使用,實現其高階功能,透過 OkHttpClient,您可以實現諸如網路連線池、超時設定、重試機制、攔截器等高階功能。而Retrofit則提供了簡化的API,使得使用這些高階功能變得更加方便。

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS) // 設定連線超時時間
    .readTimeout(30, TimeUnit.SECONDS)    // 設定讀取超時時間
    .writeTimeout(30, TimeUnit.SECONDS)   // 設定寫入超時時間
    .addInterceptor(new LoggingInterceptor()) // 新增日誌攔截器
    .build();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://localhost:8080/coderacademy/")
    .client(okHttpClient) // 設定自定義的 OkHttpClient
    .addConverterFactory(GsonConverterFactory.create())
    .build();

建立請求介面例項,發起請求

在建立完Retrofit例項之後,接下來就需要透過呼叫Retrofit例項的create() 方法來建立API介面的例項。然後就可以使用該例項呼叫定義在介面中的方法來發起網路請求。

MyClientService myClientService = retrofit.create(MyClientService.class);

TestRequest testRequest = new TestRequest();
testRequest.setName("碼農Academy");
testRequest.setPassword("12131");
// 發起請求
Call<TestResponse> call = myClientService.addTest(testRequest);
try {
	Response<TestResponse> response = call.execute();
	System.out.println("是否請求成功:"+response.isSuccessful());
	System.out.println("響應:"+ response.toString());
	TestResponse testResponse = response.body();
	System.out.println("請求結果:"+ testResponse.toString());
}catch (Exception e){
	e.printStackTrace();
}

Retrofit中,Call物件代表了一個待執行的網路請求。它是一個表示單個非同步或同步執行的請求的物件。Call介面定義了執行網路請求和處理響應的方法。Call介面的泛型型別參數列示了該網路請求的響應型別。例如,Call<TestResponse> 表示該網路請求的響應是一個TestResponse物件響應。

execute()方法用於同步執行網路請求,並返回一個Response物件。當呼叫execute()方法時,請求將立即發出,當前執行緒將被阻塞直到請求完成並返回響應。Response物件包含了網路請求的響應資料,可以透過呼叫body()方法來獲取響應主體。

另外,還可以使用Call物件來發起非同步網路請求。非同步請求允許您在發出請求後繼續執行其他程式碼,而不必等待網路請求完成。當請求完成後,Retrofit將在後臺執行緒上呼叫您提供的回撥方法,以處理響應資料。

Call<TestResponse> call = myClientService.addTest(testRequest);

try {
	call.enqueue(new Callback<TestResponse>() {
		@Override
		public void onResponse(Call<TestResponse> call, Response<TestResponse> response) {
			System.out.println("是否請求成功:"+response.isSuccessful());
			System.out.println("響應:"+ response.toString());
			TestResponse testResponse = response.body();
			System.out.println("請求結果:"+ testResponse.toString());
		}

		@Override
		public void onFailure(Call<TestResponse> call, Throwable t) {
			// 請求失敗結果
		}
	});
   
}catch (Exception e){
	e.printStackTrace();
}

非同步請求時,需要實現Callback介面,該介面定義了處理成功和失敗響應的方法。在 onResponse方法中處理成功響應,在onFailure方法中處理失敗響應。

然後使用Call物件的enqueue()方法來執行非同步網路請求,並傳入CallbackRetrofit將在後臺執行緒上執行網路請求,並在請求完成後呼叫相應的回撥方法。

到此一個使用Retrofit2發起請求的功能就完成了。接下來我們看一下Retrofit2的一些高階功能。

Retrofit2的高階功能

攔截器

Retrofit的高階功能通常需要與OkHttpClient結合使用才能實現。OkHttpClient是一個強大的HTTP客戶端庫,Retrofit是基於它構建的,並且Retrofit預設使用 OkHttpClient作為其底層的網路請求庫。

透過OkHttpClient,您可以實現諸如網路連線池、超時設定、重試機制、攔截器等高階功能。而Retrofit則提供了簡化的API,使得使用這些高階功能變得更加方便。

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS) // 設定連線超時時間
    .readTimeout(30, TimeUnit.SECONDS)    // 設定讀取超時時間
    .writeTimeout(30, TimeUnit.SECONDS)   // 設定寫入超時時間
    .addInterceptor(new LoggingInterceptor()) // 新增日誌攔截器
    .build();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://localhost:8080/coderacademy/")
    .client(okHttpClient) // 設定自定義的 OkHttpClient
    .addConverterFactory(GsonConverterFactory.create())
    .build();

對於攔截器,在實際開發中有較多需要使用的場景,比如第三方服務需要使用一些簽名驗證手段,請求資料進行加密等,我們都可以統一在攔截器中進行處理。自定義攔截器,我們需要實現Interceptor介面,實現intercept()方法。

@Slf4j
public class MyAuthInterceptor implements Interceptor {
    
    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {

        String appKey = "MyKey";
        String appToken = "MyToken";

        Request request = chain.request();
        Request.Builder builder = request.newBuilder();
        builder.addHeader("Api-Key", appKey).addHeader("Api-Secret", appToken);
        request = builder.build();
        return chain.proceed(request);
    }
}

傳入攔截器:

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS) // 設定連線超時時間
    .readTimeout(30, TimeUnit.SECONDS)    // 設定讀取超時時間
    .writeTimeout(30, TimeUnit.SECONDS)   // 設定寫入超時時間
    .addInterceptor(new LoggingInterceptor()) // 新增日誌攔截器
    .addInterceptor(new MyAuthInterceptor()) 
    .build();

轉換器

前面內容已經提到對於轉換器,出了Retrofit2提供的8種轉換器以外,有些特別的請求體這幾種轉換器不能滿足,此時,我們可以自定義轉換器。需要繼承Converter.Factory類,重寫requestBodyConverterreponseBodyConverter方法即可。

public class CustomBodyConverterFactory extends Converter.Factory {

    @Nullable
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new CustomResponseBodyConverter(type);
    }

    @Nullable
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new CustomRequestBodyConverter(type);
    }
}

然後我們在分別實現CustomResponseBodyConverter以及CustomRequestBodyConverter,實現請求與響應不同的轉換器。

@Slf4j
public class CustomRequestBodyConverter implements Converter<CustomRequest, RequestBody> {

    private final ObjectMapper objectMapper;

    public CustomRequestBodyConverter() {
    
      this.objectMapper = new ObjectMapper(new JsonFactoryBuilder().build());
      this.objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        this.objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    @Nullable
    @Override
    public RequestBody convert(CustomRequest CustomRequest) throws IOException {
	    // 具體轉換邏輯
    }
}    

/**
*響應轉換器
*/
public class CustomResponseBodyConverter implements Converter<ResponseBody, Object> {

    private final Type type;
    /**
     * 物件對映器
     */
    private final Gson gson;

    public CustomResponseBodyConverter(Type type) {
        this.type = type;
        GsonBuilder gsonBuilder = new GsonBuilder();
        this.gson = gsonBuilder.create();
    }

    @Override
    public Object convert(ResponseBody value) throws IOException {
	    // 具體處理邏輯
    }
}    

使用自定義轉換器

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://localhost:8080/coderacademy/")
    .client(okHttpClient) // 設定自定義的 OkHttpClient
    .addConverterFactory(new CustomBodyConverterFactory())
    .build();

總結

本文深入介紹了Retrofit2,這是由Square公司開源的一款面向JavaAndroid平臺的RESTful API客戶端庫。基於強大的OkHttp網路庫構建,Retrofit2透過優雅的設計理念,將複雜的HTTP請求抽象為型別安全且易於理解的介面呼叫。

在使用Retrofit2時,開發者可以利用註解來定義API介面以及配置請求方法、URL路徑、引數等資訊,大大簡化了網路通訊實現過程,提高了程式碼可讀性和維護性。同時,Retrofit2內建了多種資料轉換器(如GsonConverterFactory),支援JSON以及其他格式的資料自動序列化與反序列化,極大地降低了開發成本。

Retrofit2不僅支援同步和非同步兩種請求模式,還提供了豐富的擴充套件機制,包括自定義轉換器以適應不同資料格式,新增攔截器處理全域性請求/響應邏輯,以及整合各種認證方式,滿足複雜網路環境下的各類需求。

此外,本文還闡述瞭如何建立和配置Retrofit例項,給出了具體的使用示例,並深入探討了如何利用高階功能如自定義轉換器、攔截器以及進行身份驗證等,進一步展示了 Retrofit2 在實際專案中的強大靈活性和實用性。透過本文的學習,讀者將能夠更加熟練地使用Retrofit2開發出高效、可靠的網路請求功能。

本文已收錄於我的個人部落格:碼農Academy的部落格,專注分享Java技術乾貨,包括Java基礎、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中介軟體、架構設計、面試題、程式設計師攻略等

相關文章