服務(wù)化體用術(shù)之"用" —— JAX-RS IN ACTION

前言

在 Java 的 Web 世界中最住,構(gòu)建Web應(yīng)用最為常見(jiàn)的 dispatcher 框架遍烦,老一點(diǎn)的 Struts 系列狭姨,現(xiàn)在最為流行的 SpringMVC婆硬。它們起初的目標(biāo)都是構(gòu)建基于模板的 web 應(yīng)用程序狠轻,也就是作為一名當(dāng)時(shí)的程序員,前后端都得會(huì)彬犯。

而隨著分布式系統(tǒng) 和 互聯(lián)網(wǎng)的發(fā)展向楼,前后端分離、后端服務(wù)化的趨勢(shì)越來(lái)越明朗谐区,SpringMVC 加入了諸如 @RestController 這樣概念性的 annotation 以 restful 風(fēng)格的 webservice call 來(lái)語(yǔ)義上支持前后分離 和 后端的服務(wù)化湖蜕。前端程序員不強(qiáng)調(diào)必須會(huì)后端,后端程序員也不強(qiáng)調(diào)必須要會(huì)前端卢佣,JAX-RS 不論用來(lái)做 Web 與前端程序員的分離重荠, 或者后端一系列的服務(wù)都是一個(gè)非常好的選擇。

從 51cto 來(lái)的圖來(lái)表述前后端分離:

從百度查來(lái)的后端分布式服務(wù)圖:

1虚茶、對(duì)應(yīng)后端概念

相信資歷比較老一些的研發(fā)戈鲁,或多或少得接觸過(guò) SOA(Service Oriented Architecture)、ESB(Enterprise Service Bus)嘹叫、RPC(Remote Procedure Call), 還有最近的微服務(wù) 這些概念即是為構(gòu)建復(fù)雜的分布式系統(tǒng)而生婆殿,為后端服務(wù)化提供一套套解決方案的思路。

ESB 企業(yè)資源總線例子圖(百度來(lái)的與作者理解一致的圖罩扇,作者很懶):

2婆芦、概念的 Implementations

這些思路的出現(xiàn),也有著對(duì)應(yīng)的 java 框架進(jìn)化著 ——— 從遙遠(yuǎn)過(guò)去的程序員制定規(guī)則到 SOAP 標(biāo)準(zhǔn)的出現(xiàn)到 Sun 建立的 Restful webservice 標(biāo)準(zhǔn) — JAX-RS喂饥, 再到后來(lái)基于 Netty 的一系列 RPC 框架消约, 誕生了非常非常多優(yōu)秀的 Java 框架,如下面舉一些我的程序職業(yè)中見(jiàn)過(guò)得一些例子员帮。

WebService的SOAP標(biāo)準(zhǔn)系列: Apache Axis2或粮、Codehaus XFire、Apache CXF

Rest 的 WebService 的 JAX-RS 系列: RestEasy捞高、Jersey氯材、CXF

基于 Netty 的 RPC 系列: Finagle渣锦、JProtobuf(我們點(diǎn)融內(nèi)部服務(wù)項(xiàng)目在使用這個(gè)RPC框架)、Thrift氢哮、apache avro

它們讓我們從使用菜刀的冷兵器戰(zhàn)場(chǎng)到使用AK47的熱兵器時(shí)代袋毙。

3、派別模式的優(yōu)點(diǎn)和區(qū)別

在我的 java 世界中有兩個(gè)派別:第一派即 j2ee 系列冗尤,走的是標(biāo)準(zhǔn)化道路听盖,先有標(biāo)準(zhǔn)的定義,再由具體廠商去實(shí)現(xiàn)生闲,再慢慢地進(jìn)化標(biāo)準(zhǔn); 另一派走得比較敏捷一些(Spring 系列), 反設(shè)計(jì)模式的特性媳溺,使得這一派如魚(yú)得水;它們共同構(gòu)成了 java web 的世界碍讯,模式不同但又相互交融悬蔽。

j2ee、spring 類(lèi)似的對(duì)比圖:

講了這么多捉兴,我們進(jìn)入我將要介紹的正題——JAX-RS蝎困, 它屬于 Restful 系列的標(biāo)準(zhǔn)、是 j2ee 系列中的產(chǎn)物之一倍啥。

那么何為標(biāo)準(zhǔn)呢禾乘?標(biāo)準(zhǔn)就像你我寫(xiě)程序時(shí)定義的 interface,我拿著接口使用其中一個(gè)實(shí)現(xiàn)虽缕,即可實(shí)現(xiàn)系統(tǒng)的交互; 標(biāo)準(zhǔn)始藕,也如同攻城射擊獅畫(huà)攻城圖紙使用了神器-UML (統(tǒng)一建模語(yǔ)言), 畫(huà)出來(lái)的東西氮趋,程序員就能夠直接懂里面發(fā)生了什么, 大大減少非標(biāo)準(zhǔn)路子造成的程序員之間的溝通問(wèn)題; 是標(biāo)準(zhǔn) 也就提供了通過(guò)編程序使程序理解程序伍派、自動(dòng)生成代碼的可能性。

JAX-RS 是一種標(biāo)準(zhǔn)也即擁有了這些優(yōu)點(diǎn)剩胁,看了我的后面的代碼诉植,你會(huì)發(fā)現(xiàn)后端程序員可以這樣構(gòu)建 Restful 的 Webservice 服務(wù) 和 客戶端。

下面的代碼中我將介紹一些 JAX-RS 標(biāo)準(zhǔn)能為我們帶來(lái)的好處昵观,如:

自動(dòng)生成可與服務(wù)器交互的客戶端

在客戶端晾腔、服務(wù)端埋點(diǎn):

—— Track可能的性能問(wèn)題

—— 傳遞一些作為上游服務(wù)器擁有的session類(lèi)參數(shù)給無(wú)狀態(tài)的服務(wù)端

—— 其他, 如 配合配置服務(wù)器做 服務(wù)注冊(cè)與發(fā)現(xiàn); 由調(diào)用方傳入 transactionId保證事務(wù)最終一致; 使用 token(如 jwt) 來(lái)獲得 api 的訪問(wèn)權(quán)限 etc啊犬。

4灼擂、Talk is cheap, show me the code.

為了避免篇幅過(guò)于冗長(zhǎng),代碼中僅提供 “四”中明確提出的 3個(gè)好處的實(shí)現(xiàn)觉至。

1)我們既然是 In action缤至, 我不解釋太多標(biāo)準(zhǔn)細(xì)節(jié)的東西,讀者可以自行通過(guò)附件1提供的鏈接,去查詢標(biāo)準(zhǔn)相關(guān)的細(xì)節(jié)领斥,下面是兩張 JAX-RS 的 Lifecycle(具體請(qǐng)參見(jiàn)附件 spec 鏈接)的圖片,讀者可以先嘗試?yán)斫庖幌聢D片 以幫助理解程序沃暗。

Server-side :

Client-side:

2)將附錄2中的源代碼下載下來(lái)月洛,用 intellij 或 eclipse 以 gradle 項(xiàng)目形式導(dǎo)入. 該項(xiàng)目的 JAX-RS 標(biāo)準(zhǔn)由 cxf 實(shí)現(xiàn),與 Springboot 進(jìn)行集成孽锥,在將項(xiàng)目導(dǎo)入后找到 類(lèi) Application嚼黔, 右鍵 debug run,即可將該 springboot 的服務(wù)器端啟動(dòng)惜辑。

3)服務(wù)端啟動(dòng)后唬涧,http 服務(wù)即被放在了 http://localhost:8080, 可訪問(wèn) http://localhost:8080/ws 測(cè)試 cxf servlet dispatcher 是否啟動(dòng)成功。此時(shí)找到 類(lèi) ClientMainDemo盛撑,這個(gè)類(lèi)既是我們生成的客戶端 它是業(yè)務(wù)邏輯碎节、性能監(jiān)控、傳遞一些 session 信息給 stateless 服務(wù)的使用 main 方法的測(cè)試抵卫。我們?cè)?“2” 中的服務(wù)啟動(dòng)好之后狮荔,直接 debug 執(zhí)行 ClientMainDemo 中的 main 方法:

具體代碼詳解我們下一步再講(其實(shí)我不想講解代碼,代碼即是文檔介粘,還煩請(qǐng)各位有興趣的同學(xué)下載代碼來(lái)看殖氏,代碼并不復(fù)雜)我們可以看到如下的日志:

case a.

第一個(gè) request 在服務(wù)端可以看到日志:

在客戶端看到日志:

我們可以看到,服務(wù)器發(fā)現(xiàn)了一個(gè) request姻采,并且記錄了它被 call 了一次(我在代碼中加的日志)雅采,與此同時(shí) 在客戶端我們看到該 request 發(fā)起和結(jié)束的日志, 可以統(tǒng)計(jì)到 request 的狀態(tài)慨亲、耗時(shí)等信息, 在客戶端的track埋點(diǎn)功能 done婚瓜。

case b.

是 DEMO 中的第三個(gè) request, 我們將一個(gè) ThreadLocal 中的變量設(shè)置好巡雨, 并使用 jaxrs 的 provider 進(jìn)行攔截并將該值讀取出來(lái)放進(jìn) http request 的 header闰渔。

我們可以在客戶端看到日志:

服務(wù)端看到日志:

4)執(zhí)行步驟“3”之后,我們發(fā)現(xiàn)我們需要的三個(gè)功能都已經(jīng)實(shí)現(xiàn)了, 我們?cè)賮?lái)具體看一看代碼是怎么做的(具體的框架搭建請(qǐng)參考源碼):

1铐望、自動(dòng)生成可與服務(wù)器交互的客戶端(該客戶端需要 publish 成 jar 包到 repo 中冈涧,給集成方使用) CXF 框架提供了一個(gè)叫做 JAXRSClientFactory 的類(lèi), 可以根據(jù) endpoint + 接口 + jaxrs providers 的方式來(lái)生成客戶端接口, 詳細(xì)代碼參見(jiàn)JaxrsExampleFacade

2正蛙、埋點(diǎn) track 客戶端執(zhí)行性能(服務(wù)端我沒(méi)做)督弓, 讀者可以自己做我自定義了一個(gè)類(lèi) 叫做 UUIDHeaderClientRequestFilter,該類(lèi)實(shí)現(xiàn)了 jaxrs 標(biāo)準(zhǔn)中 client 端的兩個(gè) filter 接口乒验, 并且我將其放進(jìn)了 client 的生命周期愚隧,即可用于生成每個(gè) request 的 uuid 并且將其性能 track 起來(lái),代碼如下:

3锻全、傳遞一些作為上游服務(wù)器擁有的 session 類(lèi)參數(shù)給無(wú)狀態(tài)的服務(wù)端與 UUIDHeaderClientRequestFilter 一樣狂塘, ?實(shí)現(xiàn)一個(gè)叫做 OperatorHeaderClientRequestFilter 的 jaxrs provider (多個(gè) provider 之后請(qǐng)讀者注意控制它們的 Priority)录煤,該 Filter 會(huì)從 ThreadLocal 中讀取變量值,放進(jìn) requestheader荞胡,具體代碼如下:

與此同時(shí)在服務(wù)器端也實(shí)現(xiàn)一個(gè)叫做 OperatorFilter 的類(lèi)妈踊, 作為 jaxrs 的 provider 實(shí)現(xiàn) ContainerRequestFilter 和 ContainerResponseFilter, 將 http header 中的值讀出來(lái)并放到 ThreadLocal 中泪漂, 在 request 結(jié)束時(shí)清空 threadlocal廊营,詳細(xì)代碼如下:

希望這篇文章在您的服務(wù)化之路上有一定思路上的幫助。

附錄:

jax-rs spec下載地址:https://jcp.org/aboutJava/communityprocess/final/jsr339/index.html

本文源碼地址:https://github.com/Agileaq/jax-rs-example.git

Uniauth的讀服務(wù)提供給了點(diǎn)融網(wǎng)各個(gè)集成系統(tǒng)萝勤,其服務(wù)提供的war包 使用了這一套解決方案并且代碼已經(jīng)開(kāi)源露筒,源碼: https://github.com/dianrong/UniAuth

cxf jaxrs文檔: http://cxf.apache.org/docs/jax-rs.html

有任何疑問(wèn), 都?xì)g迎直接與我聯(lián)系并交流經(jīng)驗(yàn): 286999915@qq.com , ?微信號(hào) ?Arc_Qian

本文作者:錢(qián)晟龍 Arc_Qian(點(diǎn)融黑幫)敌卓,現(xiàn)任點(diǎn)融網(wǎng)架構(gòu)組產(chǎn)品研發(fā)工程師慎式,主要任務(wù)是思考并嘗試解決各類(lèi)點(diǎn)融網(wǎng)邁出第一公里之后遇到的現(xiàn)實(shí)問(wèn)題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末假哎,一起剝皮案震驚了整個(gè)濱河市瞬捕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舵抹,老刑警劉巖肪虎,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惧蛹,居然都是意外死亡扇救,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)香嗓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)迅腔,“玉大人,你說(shuō)我怎么就攤上這事靠娱〔琢遥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵像云,是天一觀的道長(zhǎng)锌雀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)迅诬,這世上最難降的妖魔是什么腋逆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮侈贷,結(jié)果婚禮上惩歉,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好撑蚌,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布上遥。 她就那樣靜靜地躺著,像睡著了一般锨并。 火紅的嫁衣襯著肌膚如雪露该。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天第煮,我揣著相機(jī)與錄音,去河邊找鬼抑党。 笑死包警,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的底靠。 我是一名探鬼主播害晦,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼暑中!你這毒婦竟也來(lái)了壹瘟?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鳄逾,失蹤者是張志新(化名)和其女友劉穎稻轨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雕凹,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡殴俱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枚抵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片线欲。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖汽摹,靈堂內(nèi)的尸體忽然破棺而出李丰,到底是詐尸還是另有隱情,我是刑警寧澤逼泣,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布趴泌,位于F島的核電站,受9級(jí)特大地震影響圾旨,放射性物質(zhì)發(fā)生泄漏踱讨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一砍的、第九天 我趴在偏房一處隱蔽的房頂上張望痹筛。 院中可真熱鬧挺尾,春花似錦、人聲如沸魁瞪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滋早。三九已至榄审,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杆麸,已是汗流浹背搁进。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昔头,地道東北人饼问。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像揭斧,于是被迫代替她去往敵國(guó)和親莱革。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理讹开,服務(wù)發(fā)現(xiàn)盅视,斷路器,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • 我是個(gè)喜歡記錄生活點(diǎn)滴的人旦万,在無(wú)錫綠點(diǎn)電子廠打工的這幾年闹击,我都會(huì)記錄一些人和事,今天跟大家分享一個(gè)我遇到的事情纸型,也...
    看一樹(shù)春秋閱讀 250評(píng)論 0 0
  • A1: 3個(gè)月以前拇砰,上班期間部門(mén)經(jīng)理來(lái)到我們的辦公室,說(shuō)我們與航材部門(mén)昨晚交接了一個(gè)輪胎狰腌,對(duì)方收到的輪胎不完整除破,有...
    陳醋君閱讀 130評(píng)論 1 0
  • 我們活在這個(gè)世上,從一降生就注定了這一生的坎坷與挫折琼腔。 沒(méi)有人的一生是一帆風(fēng)順的瑰枫。我們的人生就像心電圖似的有高就有...
    呆丫閱讀 990評(píng)論 3 2