切換語言為:簡體
基於OkHttp實現的一款開源優雅Http框架

基於OkHttp實現的一款開源優雅Http框架

  • 爱糖宝
  • 2024-10-09
  • 2037
  • 0
  • 0

導讀:本文從AI時代背景下的軟體架構變化談起,引出其中一個必要的Http客戶端技術,進而分析當前Java領域主要的Http客戶端和Http框架,並重點闡述了其中優雅度滿分的Retrofit框架,以及相關的使用技巧。透過閱讀本文,你可以快速瞭解Java領域的三大Http客戶端是什麼?三大封裝框架是什麼?以及熟練掌握Retrofit框架的各種使用技巧。

前沿

在AI技術日新月異的今天,軟體架構正經歷著前所未有的變革,以適應更加複雜、高效且智慧的資料互動需求。作為這一變革中的重要一環,HTTP客戶端技術成爲了連線前後端、大模型與Java、微服務之間不可或缺的橋樑。在Java這一廣泛應用的程式語言中,HTTP客戶端的選擇與使用不僅關乎到系統的效能與穩定性,還直接影響到開發效率與程式碼的可維護性。因此對於開發者掌握好Http客戶端和框架勢必重要!

三大框架是什麼?

在Java生態中,三大主流的HTTP客戶端分別是:

  • Apache HttpClient:作為Apache軟體基金會下的一個專案,HttpClient以其豐富的功能、高度的可配置性和廣泛的社羣支援而聞名。它支援HTTP/1.1和HTTP/2協議,提供了強大的請求執行、響應處理以及連線管理功能。

  • OkHttp:由Square公司開發,OkHttp以其高效、易用和強大的錯誤處理能力而受到青睞。它支援同步和非同步請求,內建了連線池、GZIP壓縮和HTTP/2等特性,非常適合在Android和Java後端服務中使用。

  • HttpUrlConnection:隨著Java 11的釋出,Java平臺內建了一個全新的HTTP客戶端API。這個API旨在提供簡單、現代的HTTP客戶端功能,同時保持與Java平臺的緊密整合。它支援HTTP/2和WebSocket,並提供了非同步和流式API,使得處理HTTP請求變得更加靈活和高效。

這三大客戶端封裝實現了HTTP協議,但是在封裝的API方法上千差萬別,且都不怎麼好用,因此開源社羣又陸續的出現了三大HTTP框架:

  • Spring RestTemplate(儘管Spring 5引入了WebClient作為更現代的替代品,但RestTemplate在舊專案中仍廣泛使用):RestTemplate是Spring框架提供的一個同步客戶端,用於簡化與HTTP服務的通訊。它提供了豐富的模板方法,用於處理HTTP請求,並自動將響應體繫結到Java物件上。

  • Retrofit(注意:雖然Retrofit在Android開發中非常流行,但嚴格來說它更多被用於Android而非純Java後端環境。不過,其設計理念和優雅度值得借鑑):Retrofit是一個型別安全的HTTP客戶端,用於Android和Java,它基於OkHttp構建,透過註解的方式極大地簡化了HTTP請求的編寫。Retrofit將HTTP請求抽象為Java介面,開發者只需定義介面方法並新增註解,即可實現複雜的HTTP請求。

  • Feign:Feign是一個宣告式的Web服務客戶端,它使得編寫Web服務客戶端變得更加簡單。Feign透過建立介面和註解的方式來定義服務繫結,它內部封裝了Ribbon和Hystrix,提供了負載均衡和斷路器功能,非常適合在微服務架構中使用。

企業開發者往往都使用更為簡單的框架,而這3大框架都為主流的,但是他們各自有很明顯的區別:

  • RestTemplate:Spring把HttpClient、OkHttp、HttpUrlConnection的使用統一成一套API,只做了統一,並API使用上並沒有簡化太多

  • Retrofit:採用宣告式方式定義http請求,使得呼叫http請求變成了對方法進行呼叫,非常優雅的方式供開發者使用

  • Feign:同Retrofit一樣,採用宣告式的方式定義http請求,但多用於微服務之間通訊

在實踐開發中,如果開發的是微服務專案則可首選Feign,因為它還支援更多微服務所需要的功能。而如果在單體專案中則首選Retrofit,其優雅的使用方式能大大簡化介面的開發、管理**。同時Retrofit底層透過OkHttp進行實現,效能相比其它框架最好。**

Retrofit框架是什麼?

官網:square.github.io/retrofit/

Retrofit基於OkHttp開發的、型別安全的Android或Java Http框架。再此我們選用Retrofit框架的重點理由是它基於OkHttp封裝,效能好,同時它融入了流行的宣告式(PS:只需要定義,不需要實現)開發思想,便於我們開發和學習。

基於OkHttp實現的一款開源優雅Http框架

Retrofit入門

在Retrofit中要實現一個Http請求總體來說共有以下2個步驟:

  • 1、匯入依賴

  • 2、宣告API

  • 3、生效API

匯入依賴

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


宣告API

我們可以先建立一個介面類:cn.itcast.star.graph.comfyui.client.api.ComfyuiApi,並按如下程式碼進行編寫:

package cn.itcast.star.graph.comfyui.client.api;

import retrofit2.Call;
import retrofit2.http.GET;

import java.util.HashMap;

public interface ComfyuiApi {

    /**
     * 獲取系統資訊
     * @return
     */
    @GET("/system_stats")
    Call<HashMap> getSystemStats();

}


使用Retrofit來宣告API,其實就是宣告介面方法,比如上述類中定義了一個方法getSystemStats:

  • 方法名可以任意取,但建議與http介面名稱一致

  • 方法透過@GET註解宣告當前請求方式是GET並且請求的地址為/system_stats,即獲取Comfyui的系統資訊介面

  • 方法返回結果為Call<HashMap>物件

    • Call是固定的返回物件

    • HashMap則是介面返回的資料自動轉成Map集合儲存

生效API

上面宣告類要生效,我們還需要配置生效,可建立一個配置類:cn.itcast.star.graph.comfyui.client.config.ComfyuiConfig

package cn.itcast.star.graph.comfyui.client.config;

import cn.itcast.star.graph.comfyui.client.api.ComfyuiApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;

import java.io.IOException;

@Configuration
public class ComfyuiConfig {

    @Bean
    public ComfyuiApi comfyuiApi() throws IOException {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.100.129:8188")
                .addConverterFactory(JacksonConverterFactory.create())
                .build();
        ComfyuiApi comfyuiApi = retrofit.create(ComfyuiApi.class);
        return comfyuiApi;
    }

}


在類中:

  • 首先透過Retrofit.Builder構建一個Retrofit客戶端

    • 透過baseUrl指定請求的伺服器地址

    • 透過addConverterFactory指定請求資料的轉換器

  • 最後呼叫 retrofit.create方法建立ComfyuiApi介面的實現

透過上述程式碼,在Spring IOC中就是宣告好了一個可以遠端呼叫獲取Comfyui伺服器狀態的Bean.

測試API

在測試包下建立類:cn.itcast.star.graph.ComfyuiApiTest

package cn.itcast.star.graph;

import cn.itcast.star.graph.comfyui.client.api.ComfyuiApi;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ComfyuiApiTest {

   @Autowired
   ComfyuiApi comfyuiApi;

   @Test
   public void test() throws Exception {
       System.out.println(comfyuiApi.getSystemStats().execute().body());
   }

}


在類中,直接注入ComfyuiApi,並呼叫getSystemStats(),即可發起請求並列印出結果:

基於OkHttp實現的一款開源優雅Http框架

Retrofit 註解大全

Retrofit爲了應對更復雜的Http請求,提供了豐富的註解來支援:

  • @Query:用來宣告http查詢部分的引數,與@RequestParam類似

  • @Path:用於說明請求路徑引數,與@PathVariable類似

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


  • @Body:用於宣告請求體物件,與@RequestBody類似

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


  • @Multipart:用於說明當前請求以表單形式發起,常常用於帶有檔案的介面

    • 如果是檔案欄位需要使用 MultipartBody.Part

    • 如果是非檔案欄位需要使用 RequestBody

  • @Part:用於說明一個表單欄位

    @Multipart
    @PUT("user/photo")
    Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);


  • @Headers:設定請求頭資訊

    @Headers({
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
    })
    @GET("users/{username}")
    Call<User> getUser(@Path("username") String username);


  • @Header:設定一個頭欄位

    @GET("user")
    Call<User> getUser(@Header("Authorization") String authorization)


  • @HeaderMap :把一個Map內容設定到請求頭中

    @GET("user")
    Call<User> getUser(@HeaderMap Map<String, String> headers)


Retrofit 高階配置

日誌開啟

Retrofit還提供了列印日誌的功能,方便我們進行BUG的排錯。Retrofit日誌功能預設是關閉的,可以透過以下程式碼進行開啟:

@Bean
public ComfyuiApi comfyuiApi() throws IOException {
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .retryOnConnectionFailure(true)
        .connectTimeout(30, TimeUnit.SECONDS)
        .build();

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://192.168.100.129:8188")
        .client(okHttpClient)
        .addConverterFactory(JacksonConverterFactory.create())
        .build();
    ComfyuiApi comfyuiApi = retrofit.create(ComfyuiApi.class);
    return comfyuiApi;
}


我們之前提供過Retrofit框架底層是透過OkHttp實現,Retrofit的日誌功能也是交由底層OkHttp實現:

  • 由於要重新設定OkHttp,因此程式碼中自行構建了OkHttpClient

  • 給OkHttpClient增加了日誌攔截器HttpLoggingInterceptor,並設定攔截器的日誌級別為BODY

    • NONE:不輸出

    • BASIC:輸出基本摘要

    • HEADERS:輸出頭資訊

    • BODY:輸出body資料

  • 最後第14行透過client方法,重新設定Retrofit底層使用的OkHttp客戶端

按上述程式碼進行修改後,重新執行ComfyuiApiTest類,即可在控制檯看見相關的日誌輸出:

基於OkHttp實現的一款開源優雅Http框架

修改資料轉換器

Retrofit支援把Http的資料直接轉換成各種物件、各種資料格式,要使用那種格式,可透過配置資料轉換器自行選擇,目前Retrofit支援8種:

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

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

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

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

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

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

  • JAXB: com.squareup.retrofit2:converter-jaxb

  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

在專案中如果要使用GSON,則先需要匯入對應的依賴:

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-gson</artifactId>
    <version>2.11.0</version>
</dependency>


然後在程式碼中透過addConverterFactory方法進行,設定轉換工廠類:

工廠類命令為XXXConverterFactory,如果是Jackson則為JacksonConverterFactory,以此類推。

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

GitHubService service = retrofit.create(GitHubService.class);

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.