RESTEASY ,從學會使用到了解原理。

轉載本文需註明出處:EAII企業架構創新研究院,違者必究。如需加入微信羣參與微課堂、架構設計與討論直播請直接回復公衆號:「EAII企業架構創新研究院」。(微信號:eaworld)java

 


1,背景知識;程序員

1.1)瞭解Rest是什麼?web

1.2)瞭解JAX-RS是什麼?編程

1.3)RestEasy簡介設計模式

2,手把手教你使用Resteasy;瀏覽器

3,揭祕Resteasy的實現原理;服務器

4,總結;微信

 

 

1、Rest簡介及Resteasy產生背景restful

 

1.1)瞭解Rest是什麼:架構

 

REST是英文RepresentationalState Transfer 的縮寫,有中文翻譯爲「具象狀態傳輸」。REST 這個術語是由 RoyFielding 在他的博士論文《Architectural Styles and the Design ofNetwork-based Software Architectures 》中提出的。REST並不是標準,而是一種開發 Web 應用的架構風格,能夠將其理解爲一種設計模式。REST 基於 HTTP,URI,以及 XML 這些現有的普遍流行的協議和標準,伴隨着 REST,HTTP 協議獲得了更加正確的使用。


相較於基於 SOAP 和 WSDL 的 Web 服務,REST 模式提供了更爲簡潔的實現方案。目前,愈來愈多的 Web 服務開始採用 REST 風格設計和實現,真實世界中比較著名的 REST 服務包括:Google AJAX 搜索 API、Amazon Simple Storage Service (AmazonS3) 等。

基於 REST 的 Web 服務遵循一些基本的設計原則:

 

1)系統中的每個對象或是資源均可以經過一個惟一的 URI 來進行尋址,URI 的結構應該簡單、可預測且易於理解,好比定義目錄結構式的 URI。

 

2)以遵循RFC-2616 所定義的協議的方式顯式地使用 HTTP 方法,創建建立、檢索、更新和刪除(CRUD:Create, Retrieve, Update and Delete)操做與 HTTP 方法之間的一對一映射:


若要建立資源,應該使用 POST方法, URI : xxx/book(在服務器端新建圖書信息,需提供該圖書全部信息)


若要檢索某個資源,應該使用 GET 方法, URI:xxx/book/{ID} (從服務器端得到某圖書信息)

若要更改資源狀態或對其進行更新,應該使用 PUT 方法,URI:xxx/book/{ID}(在服務器端更新某已存在的圖書信息,需提供更新的內容)


若要刪除某個資源,應該使用 DELETE 方法, URI :xxx/book/{ID} (從服務器端刪除某圖書信息)


URI 所訪問的每一個資源均可以使用不一樣的形式加以表示(好比 XML 或者 JSON),具體的表現形式取決於訪問資源的客戶端,客戶端與服務提供者使用一種內容協商的機制(請求頭與 MIME 類型)來選擇合適的數據格式,最小化彼此之間的數據耦合。

 

1.2) 瞭解JAX-RS是什麼?

 

Java EE 6 引入了對 JSR-311 的支持。JSR-311(JAX-RS:JavaAPI for RESTful Web Services)旨在定義一個統一的規範,使得 Java 程序員可使用一套固定的接口來開發 REST 應用,避免了依賴於第三方框架。同時,JAX-RS 使用 POJO 編程模型和基於標註的配置,並集成了JAXB,從而能夠有效縮短 REST 應用的開發週期。

 

JAX-RS是一套用java實現REST服務的規範,提供了一些標註將一個資源類,一個POJOJava類,封裝爲Web資源. 這些標註包括如下:

 

 

@Path:標註資源類或方法的相對路徑。

 

@GET,@PUT,@POST,@DELETE:標註方法是用的HTTP請求的類型。

 

@Produces:標註返回的MIME媒體類型。

 

@Consumes:標註可接受請求的MIME媒體類型。

 

@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam:分別標註方法的參數來自於HTTP請求的不一樣位置,例如@PathParam來自於URL的路徑,@QueryParam來自於URL的查詢參數,@HeaderParam來自於HTTP請求的頭信息,@CookieParam來自於HTTP請求的Cookie。

 

更通俗些說若是你用java寫了一套框架,當開發者本身寫的JAVA類使用了JAX-RS定義的這些註解標註過,而後經過你寫的這套框架就能夠將有這些JAX-RS標註的類發佈成web資源,供其餘客戶端程序去調用。那麼你寫的這套框架就是一套RestFul Web Service框架,就是JAX-RS規範的實現者之一,是JAX-RS標準定義的這些標註的解釋執行者。

 

目前比較流行的JAX-RS實現有如下幾種:

 

Apache CXF,開源的Web服務框架開源組織Apache的實現。Jersey,由Sun提供的JAX-RS的參考實現。RestEasy,JBoss的JAX-RS的實現。

 

與其餘幾個框架相比較而言,RestEasy以其高性能,輕量級,簡單易上手,高可靠性和穩定性以及易於與其餘容器集成等特色,愈來愈受到開發人員的歡迎。

 

1.3)Resteasy簡介:

 

RESTEasy是JBoss的一個開源項目,提供一套完整的框架幫助開發人員構建RESTful Web Service和RESTful Java應用程序。它是JAX-RS 2.0規範的一個完整實現並經過JCP認證,經過Http協議對外提供基於Java API的 RestFul Web Service。

 

RestEasy能夠運行在任何Servlet容器中,做爲JBoss的官方實現它能夠更好的和Jboss服務器緊密融合從而提供更好的用戶體驗。

 

做爲JAX-RS的標準實現,RestEasy還具備如下亮點特性:

 

1)不須要配置文件,只要把JARs文件放到類路徑裏面,添加 @Path等標註就能夠了

2)徹底的把 RESTEeasy 配置做爲Seam 組件來看待

3)HTTP 請求由Seam來提供,不須要一個額外的Servlet

4)Resources 和providers能夠做爲Seam components (JavaBean or EJB),具備全面的Seaminjection,lifecycle, interception, 等功能支持

5)支持在客戶端與服務器端自動實現GZIP解壓縮

6)支持異步請求處理

7)支持多種數據傳輸格式: XML, JSON, YAML, Fastinfoset, Multipart, XOP, Atom

……

 

 

2、手把手教你使用Resteasy

 

 

Resteasy的配置方法有不少種,本節內容是爲了給下節講解RestEasy原理作個鋪墊,便於你們理解其實現原理,因此使用了RestEasy最基礎的配置方式,其餘配置方法你們能夠去官網找到相關資料。

 

RestEasy的配置使用很是的簡單,如今咱們經過一個 Demo來看一下如何使用RestEasy。

 

新建一個JAVA Web工程: 我使用了Maven來建立webapp項目:

引入依賴包:pom.xml 配置以下:

新建Java 資源類,並添加相應的註解;(要發佈成rest服務的類)

配置web.xml,添加使用Resteasy將資源類發佈成rest服務的能力,配置以下:

驗證,啓動服務器打開瀏覽器訪問:

http://localhost:8080/resteasydemo/path1/subpath/123

出現以上結果說明經過Resteasy發佈 Rest服務成功.怎麼樣 SoEasy吧。

 

3、揭祕Resteasy的實現原理

 

 

經過上面的Demo相信你們都已經學會如何使用Resteasy把一個JavaBean發佈成Rest服務了,接下來咱們結合Demo一塊兒來看一下Resteasy的實現原理。

 

我本人研究Resteasy實現原理的方法是:經過上面這個Demo來調試閱讀Resteasy的源碼進而理解其實現原理。

 

首先要發佈restful的service要解決如下幾個問題:

 

1) 誰來接受來自客戶端的請求,並進行分發交給對應的對象的方法去處理。

 

2) 負責處理客戶端請求的對象由誰來負責產生(上面Demo中的TestRest對象)。

 

3) 如何解析Java類上面的JAX-RS註解,使客戶端過來的請求能夠找到對應的對象的方法去執行。

 

帶着上面的三個問題咱們來看一下Resteasy是如何設計實現來解決上面的問題的。

 

在上面的Demo中要把TestRest發佈成Rest服務首先在web.xml文件中作了如下配置:

其中ResteasyBootstrap做爲監聽器是拉起Resteasy服務的入口,在服務啓動時主要作了如下動做:

1)經過ListenerBootstrap組件讀取在web.xml文件中的一些系統配置信息,建立ResteasyDeployment對象,並將這些配置信息初始化到該對象中,其中就包括將」resteasy.resources」中配置的資源類的路徑初始化到其成員變量resourceClasses中;

 

2)經過調用ResteasyDeployment的start()方法,並根據相關配置信息初始化Resteasy的核心組件ResteasyProviderFactory ,Dispatcher,Registry.

 

3)最關鍵的部分是調用registration(),在該方法中會遍歷以前在web.xml中配置的資源並將其註冊到Registry中, 以Demo中的例子來看會遍歷resourceClasses中配置好的TestRest資源路徑,並加載該類而後經過調用registry.addPerRequestResource(clazz)註冊到Registry中; 詳見如下代碼片斷:

在addPerRequestResource()中作了兩個主要的事情:其中一個是會使用相應的ResourceFactory來包裝資源類TestRest,見如下代碼片斷:

經過閱讀POJOResourceFactory的源碼能夠了解到其做用就是包含了資源類的全部元信息,所以它能夠利用ResteasyProviderFactory提供的注入器在須要時經過createResource()來建立資源類TestRest的對象;

 

第二個主要的事情是Registry能夠經過資源類中的元信息來解析上面的JAX-RS註解,並將該註解的路徑和對應的方法生成的invoker對象註冊到Registry中,在Demo中就是把」/path1/subpath/{id}」和 test()方法的invoker對象註冊到Registry中。

 

(Resteasy在服務啓動時初始化過程圖)

在web.xml文件中另外一個配置是配置了HttpServletDispatcher,該類是HttpServlet的實現是全部請求的入口,經過其service()方法最終將請求交給以前啓動服務時已經初始化好的Dispatcher對象來處理. 以Demo爲例,當請求」http://localhost:8080/resteasydemo/path1/subpath/123」過來時,Dispatcher對象會調用其成員變量Registry對象來解析該請求中的路徑」/path1/subpath/123」, 而後匹配到相應的invoker來執行客戶端請求(詳見如下代碼段),並將結果返回,頁面會顯示」Hello 123」;

 

(Resteasy 客戶端請求處理流程圖)

4、總結

 

 

經過對Resteasy源碼的解讀分析咱們就能夠解答剛開始的三個問題:

 

1)誰來接受來自客戶端的請求,並進行分發交給對應的對象的方法去處理。

----->HttpServletDispatcher,(接受並分發客戶端http請求)

 

2)負責處理客戶端請求的對象由誰來負責產生。

----->ResourceFactory (在服務器啓動時經過web.xml讀取class的配置信息而後經過反射機制產生)

 

3)如何解析Java類上面的註解,使客戶端過來的請求能夠找到對應的方法去執行。

------>Registry(服務器啓動時加載用戶自定義Rest資源時,會解析上面的註解,並將註解相對路徑和該類中執行的方法創建對應關係註冊到Registry中,當客戶端請求過來時會根據請求中的相對路徑去Registry中查找對應的invoker對象,而後執行並將處理結果返回)

 

Resteasy就是經過以上幾個核心組件的相互配合,最終將一個JavaBean發佈成Rest服務,這種基於服務註冊的實現方式,使得Resteasy具備較好的可擴展性,例如它能很好的和Spring進行整合將SpringBean發佈成Rest服務,它是如何作到的呢?首先擴展了Resteasy的ResourceFactory實現了一個SpringResourceFactory(用來從Spring容器中得到對象),而後在服務啓動時當Spring容器初始化好之後,經過擴展Spring的BeanFactoryPostProcessor,將Spring容器中初始化好的SpringBean以及對應的SpringResourceFactory註冊到Resteasy的Registry中.這樣客戶端請求過來後,當請求路徑在Registry中匹配到相應的SpringBean時就能夠調用該SpringBean的ResourceFactory的createResource方法,該方法能夠從Spring容器中得到對象來處理請求。

 

Tips:

 

Resteasy發佈Rest服務的兩種方式:


一種是經過listener (ResteasyBootstrap)方式在server啓動時經過該listener的contextInitialized()初始化Resteasy核心組件及Rest資源。
第二種是若是沒有在web.xml中配置ResteasyBootstrap監聽器,則在HttpServletDispatcher,第一次請求過來時經過servlet的init方法初始化Resteasy核心組件及Rest資源。
不管哪一種方式原理都是同樣的,只是初始化的時機不一樣。

 

 

關於做者:
王磊

現任普元SOA產品部高級軟件工程師,曾供職於Newegg,The ActiveNetWork等知名外企,在Newegg工做期間曾擔任項目經理帶領團隊完成美蛋網O2O平臺LocalPros的開發上線,在J2EE企業級應用方面有豐富的實戰經驗。

 

 

關於EAII

EAII(Enterprise Architecture Innovation Institute)企業架構創新研究院,致力於軟件架構創新與實踐,加速企業數字化轉

相關文章
相關標籤/搜索