一款直擊痛點(diǎn)的優(yōu)秀http框架,讓我超高效率完成了和第三方接口的對(duì)接

1.背景

因?yàn)闃I(yè)務(wù)關(guān)系仁热,要和許多不同第三方公司進(jìn)行對(duì)接勾哩。這些服務(wù)商都提供基于http的api思劳。但是每家公司提供api具體細(xì)節(jié)差別很大。有的基于RESTFUL規(guī)范潜叛,有的基于傳統(tǒng)的http規(guī)范秽褒;有的需要在header里放置簽名,有的需要SSL的雙向認(rèn)證钠导,有的只需要SSL的單向認(rèn)證震嫉;有的以JSON 方式進(jìn)行序列化,有的以XML方式進(jìn)行序列化牡属。類似于這樣細(xì)節(jié)的差別太多了票堵。

不同的公司API規(guī)范不一樣,這很正常逮栅。但是對(duì)于我來說悴势,我如果想要代碼變得優(yōu)雅。我就必須解決一個(gè)痛點(diǎn):

不同服務(wù)商API那么多的差異點(diǎn)措伐,如何才能維護(hù)一套不涉及業(yè)務(wù)的公共http調(diào)用套件。最好通過配置或者簡單的參數(shù)就能區(qū)分開來。進(jìn)行方便的調(diào)用镰官?

我當(dāng)然知道有很多優(yōu)秀的大名鼎鼎的http開源框架可以實(shí)現(xiàn)任何形式的http調(diào)用宙搬,在多年的開發(fā)經(jīng)驗(yàn)中我都有使用過。比如apachehttpClient包础淤,非常優(yōu)秀的Okhttp币砂,jersey client凑兰。

這些http開源框架的接口使用相對(duì)來說,都不太一樣。不管選哪個(gè),在我這個(gè)場景里來說坛善,我都不希望在調(diào)用每個(gè)第三方的http api時(shí)寫上一堆http調(diào)用代碼省容。

所以,在這個(gè)場景里,我得對(duì)每種不同的http api進(jìn)行封裝。這樣的代碼才能更加優(yōu)雅,業(yè)務(wù)代碼和http調(diào)用邏輯耦合度更低响逢。

可惜,我比較懶。一來覺得封裝起來比較費(fèi)時(shí)間误甚,二來覺對(duì)封裝這種底層http調(diào)用來說,應(yīng)該有更好的選擇。不想自己再去造輪子导盅。

于是绢片,我發(fā)現(xiàn)了一款優(yōu)秀的開源http框架,能屏蔽不同細(xì)節(jié)http api所帶來的所有差異。能通過簡單的配置像調(diào)用rpc框架一樣的去完成極為復(fù)雜的http調(diào)用茸歧。

Forest

https://gitee.com/dt_flys/forest

1.png

2.上手

Forest支持了Springboot的自動(dòng)裝配,所以只需要引入一個(gè)依賴就行

<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);
  
}

在啟動(dòng)類里配置代理接口類的掃描包

@SpringBootApplication
@ForestScan(basePackages = "com.example.demo.forest")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

這時(shí)候只锭,你就可以從spring容器中注入你的代理接口纵顾,像調(diào)用本地方法一樣去調(diào)用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打印了內(nèi)部所用的http框架妓灌,和實(shí)際請求url和返回俱萍。當(dāng)然日志可以通過配置去控制開關(guān)枪蘑。

2.png

3.特點(diǎn)

我覺得對(duì)于尤其是做對(duì)接第三方api的開發(fā)同學(xué)來說话侧,這款開源框架能幫你提高很多效率鹿寨。

Forest 底層封裝了2種不同的http框架:Apache httpClientOKhttp。所以這個(gè)開源框架并沒有對(duì)底層實(shí)現(xiàn)進(jìn)行重復(fù)造輪子,而是在易用性上面下足了功夫霹俺。

我用Forest最終完成了和多個(gè)服務(wù)商api對(duì)接的項(xiàng)目,這些風(fēng)格迥異的API珊佣,我僅用了1個(gè)小時(shí)時(shí)間就把他們轉(zhuǎn)化為了本地方法。然后項(xiàng)目順利上線披粟。

Forest作為一款更加高層的http框架咒锻,其實(shí)你并不需要寫很多代碼,大多數(shù)時(shí)候守屉,你僅通過一些配置就能完成http的本地化調(diào)用惑艇。而這個(gè)框架所能覆蓋的面,卻非常之廣拇泛,滿足你絕大多數(shù)的http調(diào)用請求滨巴。

Forest有以下特點(diǎn):

  • HttpclientOkHttp為后端框架
  • 通過調(diào)用本地方法的方式去發(fā)送Http請求, 實(shí)現(xiàn)了業(yè)務(wù)邏輯與Http協(xié)議之間的解耦
  • 相比Feign更輕量,不依賴Spring Cloud和任何注冊中心
  • 支持所有請求方法:GET, HEAD, OPTIONS, TRACE, POST, DELETE, PUT, PATCH
  • 支持靈活的模板表達(dá)式
  • 支持過濾器來過濾傳入的數(shù)據(jù)
  • 基于注解碰镜、配置化的方式定義Http請求
  • 支持SpringSpringboot集成
  • 實(shí)現(xiàn)JSONXML的序列化和反序列化
  • 支持JSON轉(zhuǎn)換框架: Fastjson,Jackson, Gson
  • 支持JAXB形式的XML轉(zhuǎn)換
  • 支持SSL的單向和雙向加密
  • 支持http連接池的設(shè)定
  • 可以通過OnSuccessOnError接口參數(shù)實(shí)現(xiàn)請求結(jié)果的回調(diào)
  • 配置簡單兢卵,一般只需要@Request一個(gè)注解就能完成絕大多數(shù)請求的定義
  • 支持異步請求調(diào)用

4.兩個(gè)很棒的功能

這里不對(duì)使用方式和配置方式一一描述,有興趣的可以去閱讀詳細(xì)文檔:

https://dt_flys.gitee.io/forest

這里只想分析這個(gè)框架2個(gè)我認(rèn)為比較好的功能

4.1 模板表達(dá)式和參數(shù)的映射綁定功能


模板表達(dá)式在使用的時(shí)候特別方便绪颖,舉個(gè)栗子

@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
);

上述是用序號(hào)下標(biāo)進(jìn)行取值,也可以通過名字進(jìn)行取值:


@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
);

以上三種寫法是等價(jià)的

當(dāng)然你也可以把參數(shù)綁定到header和body里去甜奄,你甚至于可以用一些表達(dá)式簡單的把對(duì)象序列化成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);

當(dāng)然數(shù)據(jù)綁定這塊詳情請參閱文檔

4.2 對(duì)HTTPS的支持

以前用其他http框架處理https的時(shí)候柠横,總覺得特別麻煩,尤其是雙向證書课兄。每次碰到問題也只能去baidu牍氛。然后根據(jù)別人的經(jīng)驗(yàn)來修改自己的代碼。

Forest對(duì)于這方面也想的很周到烟阐,底層完美封裝了對(duì)https單雙向證書的支持搬俊。也是只要通過簡單的配置就能迅速完成紊扬。舉個(gè)雙向證書栗子:

@Request(
    url = "${base}/pay",
    contentType = "application/json",
    type = "post",
    dataType = "json",
    keyStore = "pay-keystore",
    data = "${json($0)}"
)
public PayResponse pay(PayRequest request);

其中pay-keystore對(duì)應(yīng)著application.yml里的ssl-key-stores

forest:
  ...
  ssl-key-stores:
    - id: pay-keystore
      file: test.keystore
      keystore-pass: 123456
      cert-pass: 123456
      protocols: SSLv3

這樣設(shè)置,就ok了唉擂,剩下的餐屎,就是本地代碼形式的調(diào)用了。

5.最后

Forest有很多其他的功能設(shè)定玩祟,如果感興趣的同學(xué)還請仔細(xì)去閱讀文檔和示例腹缩。

但是我想說的是,相信看到這里空扎,很多人一定會(huì)說藏鹊,這不就是Feign嗎?

我在開發(fā)Spring Cloud項(xiàng)目的時(shí)候转锈,也用過一段時(shí)間Feign盘寡,個(gè)人感覺Forest的確在配置和用法上和Feign的設(shè)計(jì)很像,但Feign的角色更多是作為Spring Cloud生態(tài)里的一個(gè)成員撮慨。充當(dāng)RPC通信的角色宴抚,其承擔(dān)的不僅是http通訊,還要對(duì)注冊中心下發(fā)的調(diào)用地址進(jìn)行負(fù)載均衡甫煞。

Forest這個(gè)開源項(xiàng)目其定位則是一個(gè)高階的http工具菇曲,主打友好和易用性。從使用角度出發(fā)抚吠,個(gè)人感覺Forest配置性更加簡單直接常潮。提供的很多功能也能解決很多人的痛點(diǎn)。

開源精神難能可貴楷力,好的開源需要大家的添磚加瓦和支持喊式。希望這篇文章能給大家在選擇http客戶端框架時(shí)帶來一個(gè)新的選擇:Forest

6.聯(lián)系作者

微信關(guān)注 「jishuyuanren」 獲取更多技術(shù)干貨

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市萧朝,隨后出現(xiàn)的幾起案子岔留,更是在濱河造成了極大的恐慌,老刑警劉巖检柬,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件献联,死亡現(xiàn)場離奇詭異,居然都是意外死亡何址,警方通過查閱死者的電腦和手機(jī)里逆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來用爪,“玉大人原押,你說我怎么就攤上這事≠搜” “怎么了诸衔?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵盯漂,是天一觀的道長。 經(jīng)常有香客問我笨农,道長就缆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任磁餐,我火速辦了婚禮违崇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诊霹。我一直安慰自己羞延,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布脾还。 她就那樣靜靜地躺著伴箩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鄙漏。 梳的紋絲不亂的頭發(fā)上嗤谚,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音怔蚌,去河邊找鬼巩步。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桦踊,可吹牛的內(nèi)容都是我干的椅野。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼籍胯,長吁一口氣:“原來是場噩夢啊……” “哼竟闪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起杖狼,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤炼蛤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蝶涩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體理朋,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年子寓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暗挑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斜友,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垃它,到底是詐尸還是另有隱情鲜屏,我是刑警寧澤烹看,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站洛史,受9級(jí)特大地震影響惯殊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜也殖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一土思、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忆嗜,春花似錦己儒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绩卤,卻和暖如春途样,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背濒憋。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國打工何暇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凛驮。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓裆站,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辐烂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遏插,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348