1. 程式人生 > >一款直擊痛點的優秀http框架,讓我超高效率完成了和第三方介面的對接

一款直擊痛點的優秀http框架,讓我超高效率完成了和第三方介面的對接

## 1.背景 因為業務關係,要和許多不同第三方公司進行對接。這些服務商都提供基於http的api。但是每家公司提供api具體細節差別很大。有的基於`RESTFUL`規範,有的基於傳統的http規範;有的需要在`header`裡放置簽名,有的需要`SSL`的雙向認證,有的只需要`SSL`的單向認證;有的以`JSON` 方式進行序列化,有的以`XML`方式進行序列化。類似於這樣細節的差別太多了。 不同的公司API規範不一樣,這很正常。但是對於我來說,我如果想要程式碼變得優雅。我就必須解決一個痛點: **不同服務商API那麼多的差異點,如何才能維護一套不涉及業務的公共http呼叫套件。最好通過配置或者簡單的引數就能區分開來。進行方便的呼叫?** 我當然知道有很多優秀的大名鼎鼎的http開源框架可以實現任何形式的http呼叫,在多年的開發經驗中我都有使用過。比如`apache`的`httpClient`包,非常優秀的`Okhttp`,`jersey client`。 這些`http`開源框架的介面使用相對來說,都不太一樣。不管選哪個,在我這個場景裡來說,我都不希望在呼叫每個第三方的http api時寫上一堆http呼叫程式碼。 所以,在這個場景裡,我得對每種不同的http api進行封裝。這樣的程式碼才能更加優雅,業務程式碼和http呼叫邏輯耦合度更低。 可惜,我比較懶。一來覺得封裝起來比較費時間,二來覺對封裝這種底層http呼叫來說,應該有更好的選擇。不想自己再去造輪子。 **於是,我發現了一款優秀的開源http框架,能遮蔽不同細節http api所帶來的所有差異。能通過簡單的配置像呼叫rpc框架一樣的去完成極為複雜的http呼叫。** **Forest** > [https://gitee.com/dt_flys/forest](https://gitee.com/dt_flys/forest) > ![file](https://img2020.cnblogs.com/other/268224/202007/268224-20200722105235613-112882572.jpg) ## 2.上手 `Forest`支援了`Springboot`的自動裝配,所以只需要引入一個依賴就行 ```xml ``` 定義自己的介面類 ```java public interface MyClient { @Request(url = "http://baidu.com") String simpleRequest(); @Request( url = "http://ditu.amap.com/service/regeo", dataType = "json" ) Map getLocation(@DataParam("longitude") String longitude, @DataParam("latitude") String latitude); } ``` 在啟動類裡配置代理介面類的掃描包 ```java @SpringBootApplication @ForestScan(basePackages = "com.example.demo.forest") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 這時候,你就可以從spring容器中注入你的代理介面,像呼叫本地方法一樣去呼叫http的api了 ```java @Autowired private MyClient myClient; @Override public void yourMethod throws Exception { Map result = myClient.getLocation("124.730329","31.463683"); System.out.println(JSON.toJSONString(result,true)); } ``` 日誌列印,`Forest`列印了內部所用的http框架,和實際請求url和返回。當然日誌可以通過配置去控制開關。 ![file](https://img2020.cnblogs.com/other/268224/202007/268224-20200722105235862-1680361472.jpg) ## 3.特點 我覺得對於尤其是做對接第三方api的開發同學來說,這款開源框架能幫你提高很多效率。 `Forest` 底層封裝了2種不同的http框架:`Apache httpClient`和`OKhttp`。所以這個開源框架並沒有對底層實現進行重複造輪子,而是在易用性上面下足了功夫。 我用`Forest`最終完成了和多個服務商api對接的專案,這些風格迥異的API,我僅用了1個小時時間就把他們轉化為了本地方法。然後專案順利上線。 `Forest`作為一款更加高層的http框架,其實你並不需要寫很多程式碼,大多數時候,你僅通過一些配置就能完成http的本地化呼叫。而這個框架所能覆蓋的面,卻非常之廣,滿足你絕大多數的http呼叫請求。 `Forest`有以下特點: - 以`Httpclient`和`OkHttp`為後端框架 - 通過呼叫本地方法的方式去傳送Http請求, 實現了業務邏輯與Http協議之間的解耦 - 相比Feign更輕量,不依賴`Spring Cloud`和任何註冊中心 - 支援所有請求方法:`GET`, `HEAD`, `OPTIONS`, `TRACE`, `POST`, `DELETE`, `PUT`, `PATCH` - 支援靈活的模板表示式 - 支援過濾器來過濾傳入的資料 - 基於註解、配置化的方式定義`Http`請求 - 支援`Spring`和`Springboot`整合 - 實現`JSON`和`XML`的序列化和反序列化 - 支援JSON轉換框架: `Fastjson`,` Jackson`, `Gson` - 支援`JAXB`形式的`XML`轉換 - 支援`SSL`的單向和雙向加密 - 支援http連線池的設定 - 可以通過`OnSuccess`和`OnError`介面引數實現請求結果的回撥 - 配置簡單,一般只需要`@Request`一個註解就能完成絕大多數請求的定義 - 支援非同步請求呼叫 ## 4.兩個很棒的功能 這裡不對使用方式和配置方式一一描述,有興趣的可以去閱讀詳細文件: > https://dt_flys.gitee.io/forest 這裡只想分析這個框架2個我認為比較好的功能 ### 4.1 **模板表示式和引數的對映繫結功能** --- 模板表示式在使用的時候特別方便,舉個栗子 ```java @Request( url = "${0}/send?un=${1}&pw=${2}&ph=${3}&ct=${4}", type = "get", dataType = "json" ) public Map send( String base, String userName, String password, String phone, String content ); ``` 上述是用序號下標進行取值,也可以通過名字進行取值: ```java @Request( url = "${base}/send?un=${un}&pw=${pw}&ph=${3}&ct=${ct}", type = "get", dataType = "json" ) public Map send( @DataVariable("base") String base, @DataVariable("un") String userName, @DataVariable("pw") String password, @DataVariable("ph") String phone, @DataVariable("ct") String content ); ``` 甚至於可以這樣簡化寫: ```java @Request( url = "${base}/send", type = "get", dataType = "json" ) public Map send( @DataVariable("base") String base, @DataParam("un") String userName, @DataParam("pw") String password, @DataParam("ph") String phone, @DataParam("ct") String content ); ``` **以上三種寫法是等價的** 當然你也可以把引數繫結到header和body裡去,你甚至於可以用一些表示式簡單的把物件序列化成json或者xml: ```java @Request( url = "${base}/pay", contentType = "application/json", type = "post", dataType = "json", headers = {"Authorization: ${1}"}, data = "${json($0)}" ) public PayResponse pay(PayRequest request, String auth); ``` 當然資料繫結這塊詳情請參閱文件 ### 4.2 對`HTTPS`的支援 以前用其他http框架處理https的時候,總覺得特別麻煩,尤其是雙向證書。每次碰到問題也只能去baidu。然後根據別人的經驗來修改自己的程式碼。 `Forest`對於這方面也想的很周到,底層完美封裝了對https單雙向證書的支援。也是隻要通過簡單的配置就能迅速完成。舉個雙向證書栗子: ```java @Request( url = "${base}/pay", contentType = "application/json", type = "post", dataType = "json", keyStore = "pay-keystore", data = "${json($0)}" ) public PayResponse pay(PayRequest request); ``` 其中`pay-keystore`對應著`application.yml`裡的`ssl-key-stores` ```yml forest: ... ssl-key-stores: - id: pay-keystore file: test.keystore keystore-pass: 123456 cert-pass: 123456 protocols: SSLv3 ``` 這樣設定,就ok了,剩下的,就是原生代碼形式的呼叫了。 ## 5.最後 `Forest`有很多其他的功能設定,如果感興趣的同學還請仔細去閱讀文件和示例。 但是我想說的是,相信看到這裡,很多人一定會說,這不就是`Feign`嗎? 我在開發`Spring Cloud`專案的時候,也用過一段時間`Feign`,個人感覺`Forest`的確在配置和用法上和`Feign`的設計很像,但`Feign`的角色更多是作為`Spring Cloud`生態裡的一個成員。充當RPC通訊的角色,其承擔的不僅是http通訊,還要對註冊中心下發的呼叫地址進行負載均衡。 而`Forest`這個開源專案其定位則是一個高階的http工具,主打友好和易用性。從使用角度出發,個人感覺`Forest`配置性更加簡單直接。提供的很多功能也能解決很多人的痛點。 開源精神難能可貴,好的開源需要大家的添磚加瓦和支援。希望這篇文章能給大家在選擇http客戶端框架時帶來一個新的選擇:`Forest` ## 聯絡作者 微信關注 「**元人部落**」: **關注後回覆 "資料" 免費獲取50G的技術資料,包含一整套企業級微服務課程以及一套秒殺課程** ![file](https://img2020.cnblogs.com/other/268224/202007/268224-20200722105236169-586705