由於業務關係,要和許多不一樣第三方公司進行對接。這些服務商都提供基於http的api。可是每家公司提供api具體細節差異很大。有的基於RESTFUL
規範,有的基於傳統的http規範;有的須要在header
裏放置簽名,有的須要SSL
的雙向認證,有的只須要SSL
的單向認證;有的以JSON
方式進行序列化,有的以XML
方式進行序列化。相似於這樣細節的差異太多了。java
不一樣的公司API規範不同,這很正常。可是對於我來講,我若是想要代碼變得優雅。我就必須解決一個痛點:git
不一樣服務商API那麼多的差別點,如何才能維護一套不涉及業務的公共http調用套件。最好經過配置或者簡單的參數就能區分開來。進行方便的調用?spring
我固然知道有不少優秀的大名鼎鼎的http開源框架能夠實現任何形式的http調用,在多年的開發經驗中我都有使用過。好比apache
的httpClient
包,很是優秀的Okhttp
,jersey client
。apache
這些http
開源框架的接口使用相對來講,都不太同樣。無論選哪一個,在我這個場景裏來講,我都不但願在調用每一個第三方的http api時寫上一堆http調用代碼。json
因此,在這個場景裏,我得對每種不一樣的http api進行封裝。這樣的代碼才能更加優雅,業務代碼和http調用邏輯耦合度更低。後端
惋惜,我比較懶。一來以爲封裝起來比較費時間,二來覺對封裝這種底層http調用來講,應該有更好的選擇。不想本身再去造輪子。api
因而,我發現了一款優秀的開源http框架,能屏蔽不一樣細節http api所帶來的全部差別。能經過簡單的配置像調用rpc框架同樣的去完成極爲複雜的http調用。微信
Forestapp
https://gitee.com/dt_flys/forest
Forest
支持了Springboot
的自動裝配,因此只須要引入一個依賴就行負載均衡
<dependency> <groupId>com.dtflys.forest</groupId> <artifactId>spring-boot-starter-forest</artifactId> <version>1.3.0</version> </dependency>
定義本身的接口類
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); }
在啓動類裏配置代理接口類的掃描包
@SpringBootApplication @ForestScan(basePackages = "com.example.demo.forest") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
這時候,你就能夠從spring容器中注入你的代理接口,像調用本地方法同樣去調用http的api了
@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和返回。固然日誌能夠經過配置去控制開關。
我以爲對於尤爲是作對接第三方api的開發同窗來講,這款開源框架能幫你提升不少效率。
Forest
底層封裝了2種不一樣的http框架:Apache httpClient
和OKhttp
。因此這個開源框架並無對底層實現進行重複造輪子,而是在易用性上面下足了功夫。
我用Forest
最終完成了和多個服務商api對接的項目,這些風格迥異的API,我僅用了1個小時時間就把他們轉化爲了本地方法。而後項目順利上線。
Forest
做爲一款更加高層的http框架,其實你並不須要寫不少代碼,大多數時候,你僅經過一些配置就能完成http的本地化調用。而這個框架所能覆蓋的面,卻很是之廣,知足你絕大多數的http調用請求。
Forest
有如下特色:
Httpclient
和OkHttp
爲後端框架Spring Cloud
和任何註冊中心GET
, HEAD
, OPTIONS
, TRACE
, POST
, DELETE
, PUT
, PATCH
Http
請求Spring
和Springboot
集成JSON
和XML
的序列化和反序列化Fastjson
, Jackson
, Gson
JAXB
形式的XML
轉換SSL
的單向和雙向加密OnSuccess
和OnError
接口參數實現請求結果的回調@Request
一個註解就能完成絕大多數請求的定義這裏不對使用方式和配置方式一一描述,有興趣的能夠去閱讀詳細文檔:
https://dt_flys.gitee.io/forest
這裏只想分析這個框架2個我認爲比較好的功能
模板表達式在使用的時候特別方便,舉個栗子
@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 );
上述是用序號下標進行取值,也能夠經過名字進行取值:
@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 );
甚至於能夠這樣簡化寫:
@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:
@Request( url = "${base}/pay", contentType = "application/json", type = "post", dataType = "json", headers = {"Authorization: ${1}"}, data = "${json($0)}" ) public PayResponse pay(PayRequest request, String auth);
固然數據綁定這塊詳情請參閱文檔
HTTPS
的支持之前用其餘http框架處理https的時候,總以爲特別麻煩,尤爲是雙向證書。每次碰到問題也只能去baidu。而後根據別人的經驗來修改本身的代碼。
Forest
對於這方面也想的很周到,底層完美封裝了對https單雙向證書的支持。也是隻要經過簡單的配置就能迅速完成。舉個雙向證書栗子:
@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
forest: ... ssl-key-stores: - id: pay-keystore file: test.keystore keystore-pass: 123456 cert-pass: 123456 protocols: SSLv3
這樣設置,就ok了,剩下的,就是本地代碼形式的調用了。
Forest
有不少其餘的功能設定,若是感興趣的同窗還請仔細去閱讀文檔和示例。
可是我想說的是,相信看到這裏,不少人必定會說,這不就是Feign
嗎?
我在開發Spring Cloud
項目的時候,也用過一段時間Feign
,我的感受Forest
的確在配置和用法上和Feign
的設計很像,但Feign
的角色更可能是做爲Spring Cloud
生態裏的一個成員。充當RPC通訊的角色,其承擔的不只是http通信,還要對註冊中心下發的調用地址進行負載均衡。
而Forest
這個開源項目其定位則是一個高階的http工具,主打友好和易用性。從使用角度出發,我的感受Forest
配置性更加簡單直接。提供的不少功能也能解決不少人的痛點。
開源精神難能難得,好的開源須要你們的添磚加瓦和支持。但願這篇文章能給你們在選擇http客戶端框架時帶來一個新的選擇:Forest
微信關注獲取更多技術乾貨