REST,Web 服务,REST-ful 服务
from: https://www.ibm.com/developerworks/cn/webservices/ws-RESTservices/
介紹
REpresentational State Transfer (REST) 是一種架構(gòu)原則,其中將 web 服務(wù)視為資源,可以由其 URL 唯一標(biāo)識。RESTful Web 服務(wù)的關(guān)鍵特點(diǎn)是明確使用 HTTP 方法來表示不同的操作的調(diào)用。
REST 的基本設(shè)計(jì)原則對典型 CRUD 操作使用 HTTP 協(xié)議方法:
- POST - 創(chuàng)建資源
- GET - 檢索資源
- PUT – 更新資源
- DELETE - 刪除資源
REST 服務(wù)的主要優(yōu)勢在于:
- 它們是跨平臺 (Java、.net、PHP 等)高度可重用的,因?yàn)樗鼈兌家蕾嚮?HTTP 協(xié)議。
- 它們使用基本的 XML,而不是復(fù)雜的 SOAP XML,使用非常方便。
基于 REST 的 web 服務(wù)日益成為后端企業(yè)服務(wù)集成的首選方法。與基于 SOAP 的 web 服務(wù)相比,它的編程模型簡單,而本機(jī) XML(而不是 SOAP )的使用減少了序列化和反序列化過程的復(fù)雜性,并且不再需要其他作用相同的第三方庫。
當(dāng)前用于構(gòu)建 RESTful 服務(wù),比如 Apache CXF、RESTlet、JAX-WS API 和 REST 支持的基于 Java 的框架可從 Spring 3.0 中獲得,它在開發(fā)和 XML 配置方面非常復(fù)雜,通常需要長期的學(xué)習(xí)。此外,由于這些框架依賴特定版本的 jar 文件,它們很難跨應(yīng)用程序服務(wù)器環(huán)境集成。另外,由于一些同時(shí)支持 SOAP 和 REST 服務(wù)的嘗試(Apache CXF、JAX-WS),它們軟件包也往往很大,也可能會影響性能。
因此本文建議使用更簡單的可擴(kuò)展框架將業(yè)務(wù)服務(wù)公開為類 REST 服務(wù)。該框架是輕量級的,采用標(biāo)準(zhǔn)的 Front Controller(前端控制器)模式,非常便于理解。它也是可擴(kuò)展的,可以通過 API 或任何其他集成模式(如 ESB)集成后端服務(wù)。通過使用自定義 XML 序列化程序、JAXB 或任何其他對象到 XML 轉(zhuǎn)換工具,可以方便地配置數(shù)據(jù)交換模型。
本文將詳細(xì)描述此框架。
架構(gòu)概述
在 J2EE 應(yīng)用程序中,Java API 或服務(wù)公開為 Stateless Session Bean API(Session Fa?ade 模式) 或 SOAP web 服務(wù)。在這些服務(wù)與使用非 Java 技術(shù) (如 .net 或 PHP)的客戶端應(yīng)用程序集成時(shí),處理 SOAP Web 服務(wù)將變得非常麻煩,還涉及到大量的開發(fā)工作。
這里提到的方法通常用于有很多服務(wù)、服務(wù)可以重復(fù)使用,但使用 SOAP 創(chuàng)建快速集成障礙的互操作性和開發(fā)成本很大的組織,幫助它們進(jìn)行服務(wù)集成。此外,在內(nèi)部治理組織不會在企業(yè) ESB 或 EAI 上公開服務(wù)的情況下,很難以點(diǎn)到點(diǎn)的方式集成兩種不同的技術(shù)服務(wù)。
例如,在電信 IT 環(huán)境中:
- 將一個(gè) SMS 發(fā)送到特定圓的 SMSC,公開為 SOAP web 服務(wù)或 EJB API;或
- 在 CRM 應(yīng)用程序中創(chuàng)建服務(wù)請求,使用 MQ 或 JMS 綁定通過 ESB 公開為一個(gè)數(shù)據(jù)庫存儲的過程 (如 Oracle CRM);或者
- 創(chuàng)建 Sales Order(銷售訂單)請求,用于使用 SMSGateway 的移動 SMS 的 Distributor。
如果以上服務(wù)是由一個(gè)非 Java 應(yīng)用程序使用的,那么使用 SOAP web 服務(wù)的集成會很麻煩,并需要更多的開發(fā)工作。
這種新方法可以用一種框架的形式實(shí)現(xiàn),使它可以在 Java 服務(wù)公開為一種類 REST 的資源的其他領(lǐng)域中重新使用。這種方法類似于 Struts 框架方法,由以下組件組成(如下圖所示):
圖 1. 架構(gòu)概述
該架構(gòu)包括 Front Controller,作為接收請求并向客戶端提供響應(yīng)的中心點(diǎn)。Front Controller 將請求處理委托給包含此框架處理邏輯的 ActionController。ActionController 執(zhí)行驗(yàn)證,將請求映射到相應(yīng)的 Action,并調(diào)用生成響應(yīng)的動作。為請求處理、日志記錄和異常處理這些可以被單個(gè) Action 以及 ActionController 使用的動作提供了各種 Helper Service。
框架組件
下圖展示了框架的各個(gè)組件以及彼此之間如何相互關(guān)聯(lián)。
圖 2. 框架組件
各種組件描述如下:
服務(wù)客戶端
這是一個(gè)需要調(diào)用服務(wù)的客戶端應(yīng)用程序。此組件可以是基于 Java 的,也可以是任何其他客戶端,只要它能夠支持 HTTP 方法
通用組件
這些都是日志記錄、 異常處理和任何常見功能所需的實(shí)用程序服務(wù)或者實(shí)現(xiàn)所需的常量。在示例代碼中使用 Apache Commons 日志記錄和 Log4j 實(shí)現(xiàn)。
RESTServiceServlet
框架使用 Front Controller 模式進(jìn)行集中請求處理,并使用此 Java Servlet 組件處理輸入的請求。它支持常見的 HTTP 方法,如 GET、PUT、POST 和 DELETE。
RESTActionController
此組件是核心框架控制器,管理加載服務(wù)和框架配置的核心功能,驗(yàn)證請求,映射請求與配置 REST 動作并執(zhí)行動作。
RESTConfiguration
該組件負(fù)責(zé)在運(yùn)行時(shí)加載和緩存框架配置,以及各種 REST 服務(wù)配置。此組件供 RESTActionController 用于確定請求要調(diào)用的正確動作,并驗(yàn)證輸入請求。
RESTMapping
此組件存儲在配置文件中指定的 REST 動作映射。映射主要包括客戶端調(diào)用的 URI 和進(jìn)行處理的動作類。
ActionContext
此組件封裝執(zhí)行 REST 動作所需的所有功能。它可以幫助開發(fā)人員提供請求和響應(yīng)處理功能,因此開發(fā)人員只需要編寫實(shí)際的業(yè)務(wù)邏輯實(shí)現(xiàn)代碼。它向動作組件隱藏協(xié)議特定的請求和響應(yīng)對象,因此允許獨(dú)立測試 POJO 之類。它還提供一個(gè)指向 XML Binding Service 的句柄,讓 Java 業(yè)務(wù)對象可以基于配置的 XML Binding API 方便地轉(zhuǎn)換為 XML,反之亦然。RESTActionController 動態(tài)配置此組件,并將其提供給 Action 組件。
XMLBinding
此組件封裝 Java XML Binding 機(jī)制,提供了一個(gè)統(tǒng)一的界面用于將 Java 業(yè)務(wù)對象轉(zhuǎn)換為 XML,反之亦然。通過實(shí)現(xiàn)標(biāo)準(zhǔn)的框架接口,它支持任何 XML 綁定機(jī)制,如 JAXB、SDO、Castor 等。默認(rèn)情況下,它為 XMLEncoder 和 XMLDecoder 提供了開箱即用功能。
Configuration XML
此組件包含框架和服務(wù)配置。當(dāng)開發(fā) REST 服務(wù)時(shí),它們可以加入服務(wù)配置文件中??蚣芘渲冒罩居涗浐?XML Binding 服務(wù),不需要定期更換。
處理典型 POST 請求的這些組件之間的交互如下所示:
圖 3. 組件交互
如上圖所示,REST 服務(wù)配置最初加載,并緩存到 RESTConfiguration 組件中。對于 REST 服務(wù)的每個(gè) HTTP 請求,RESTServiceServlet 組件將請求委托到 RESTActionController,它又會檢索相應(yīng)的映射、驗(yàn)證請求、創(chuàng)建 ActionContext 組件以及路徑和查詢輸入,并調(diào)用 Action 類 (例如,createUserAction)。Action 類調(diào)用后端 Java 業(yè)務(wù)服務(wù)進(jìn)行處理。
讓所有組件運(yùn)作起來
本節(jié)介紹了這篇文章提供的框架的示例實(shí)現(xiàn)。它展示了類關(guān)系圖、各種配置文件和顯示如何將上述設(shè)計(jì)付諸實(shí)行的代碼片段。
注意: 示例代碼可能沒有遵循所有 Java 編碼的最佳做法,因?yàn)樗皇且粋€(gè)示例。
示例實(shí)現(xiàn)
下圖顯示了示例實(shí)現(xiàn)中的類。藍(lán)色所示的類是框架外部的類,將它們放在這里是為了展示與框架的結(jié)構(gòu)關(guān)系。
圖 4. 類圖
配置文件
配置文件 "rest-services-config.xml" 包含 REST 服務(wù)表示形式和相應(yīng)的 Java Action 之間的映射,如下:
清單 1. REST 服務(wù)配置
| 1 2 3 4 5 6 7 8 9 10 | <?xml version="1.0" ?> <rest-config> ??<rest-api id="CreateUserProfile" uri="/Registration/CreateUser" method="POST"> ?????<handler id="RegAction" class="ws.registration.restactions.CreateProfile"/> ??</rest-api> ??<rest-api id="GetUserProfile" uri="/Registration/GetUser" method="GET"> ?????<handler id="RegAction" class=" ws.registration.restactions.GetProfile"/> ??</rest-api> ... </rest-config> |
在該示例實(shí)現(xiàn)中,XML Binding 服務(wù)實(shí)現(xiàn)在 "rl-config.xml" 文件中配置的框架配置文件如下所示。通過修改此文件實(shí)現(xiàn)的任何自定義實(shí)現(xiàn)都可以接入,只要實(shí)現(xiàn)了 XMLBindingService 接口。
清單 2:框架配置
| 1 2 3 | # XML Binding Implementation Service # Default implementation ws.rest.xmlbinding.service.impl=ws.rest.xmlbinding.service.impl.XMLEncDecServiceImpl |
日志配置文件 "ws_log.properties" 指定 log4j 屬性和日志文件的位置。這可以按需要作出適當(dāng)修改。
Controller Servlet
RESTServiceServlet 在 web.xml 中配置,處理所有具有上下文路徑的請求,其中上下文路徑的 <web-app>/restservices/* 如下所示:
清單 3:Servlet 配置
| 1 2 3 4 5 6 7 8 9 10 | <servlet> ????<description></description> ????<display-name>RESTServletService</display-name> ????<servlet-name>RESTServletService</servlet-name> ????<servlet-class>ws.rest.servlet.RESTServiceServlet</servlet-class> ??</servlet> ??<servlet-mapping> ????<servlet-name>RESTServletService</servlet-name> ????<url-pattern>/restservices/*</url-pattern> ??</servlet-mapping> |
REST Action
對于每個(gè) REST 資源,例如 GetUserProfile,都將創(chuàng)建一個(gè)實(shí)現(xiàn) ActionInterface 的相應(yīng)動作類。該接口定義了動作類需要實(shí)現(xiàn)的 "doExecute(ActionContext ctx)" 方法。ActionContext 提供服務(wù),獲取 REST 路徑輸入或查詢參數(shù),獲取 XMLBindingService 實(shí)例并將 XML 輸出發(fā)送到客戶端,不公開 Action 的協(xié)議細(xì)節(jié)。PathInputs 是一個(gè)包含路徑值的 List 對象,路徑值的順序與它們在 URL 中指定的順序相同。
清單 4:Action 代碼片段
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class GetProfile implements ActionInterface { ????? ??public void doExecute(ActionContext context) throws Exception { ???// Get the value from URL path ???String userName = context.getPathInputs().get(0); ???// Invoke backend service to retrieve user profile ???UserProfileBean bean = getUser(userName); ???? ???? ???// Serialize the bean using framework service and send response ???String xml = context.getXMLBindingService().serialize(bean); ???// Use the ActionContext to generate XML and ???context.sendResponse(response, xml); } |
動作類負(fù)責(zé)使用超類中的 XMLBindingService 以 XML 形式生成輸出。請查看示例實(shí)現(xiàn)的 ws.registration.restactions.GetProfile 類。ActionContext 還可以提供協(xié)議特定的 HttpServletRequest 和 HttpServletResponse 對象,以防需要自定義處理。它還提供了 Path 值和 URL 參數(shù)。
XML Binding
該代碼示例提供了一個(gè) Java XML Binding 的實(shí)現(xiàn),該實(shí)現(xiàn)使用 java.beans.XMLEncoder 和 java.beans.XMLDecoder 類。XML Binding 服務(wù)實(shí)現(xiàn)接受一個(gè) JavaBean 對象,并將其轉(zhuǎn)換為上述 Encoder 和 Decoder 相應(yīng)的 XML 表示形式。如果需要 JAXB 實(shí)現(xiàn),那么可以開發(fā)一個(gè)實(shí)現(xiàn) ws.rest.xmlbinding.service.XMLBindingService 接口的實(shí)現(xiàn)類。
執(zhí)行示例服務(wù)
示例代碼分發(fā)包含示例 WAR 文件 "RESTWS.war",它可以部署在 Tomcat 容器中(已在 Apache Tomcat 版本 6.0.20 上進(jìn)行了測試)。JDK 要求是 JDK 1.5 以上。
成功部署該應(yīng)用程序之后,在瀏覽器中輸入以下 URL:http://localhost:8080/RESTWS/html/CreateProfile.html ,如下所示:
圖 5. 創(chuàng)建 Profile Service 輸入
該頁面調(diào)用 REST 服務(wù)
| 1 | POST <url-prefix>/Registration/CreateProfile |
您可以修改在 <string></string> 標(biāo)記中指定的 XML 值。
注意:請注意 XML 結(jié)構(gòu)依賴于 JavaBean 對象和 Java 使用的 XML 序列化技術(shù)。
提交時(shí),動作類顯示成功消息,表示后端服務(wù)的調(diào)用??梢圆榭?ws_log.log 文件調(diào)試消息。
圖 6. 創(chuàng)建 Profile Service 輸出
類似地,實(shí)現(xiàn)示例 GET <url-prefix>/Registration/GetProfile/{username} 服務(wù)以檢索配置文件,如下圖所示:
圖 7. 執(zhí)行 Profile Service
小結(jié)
因此,使用這一框架,我們認(rèn)為我們可以輕松地將任何 Java 服務(wù)公開為一種 REST API。通過使用 XML 作為輸出數(shù)據(jù),服務(wù)可以方便地集成以任何非 Java 語言編寫的客戶端應(yīng)用程序,只要它支持 HTTP 協(xié)議。此外,實(shí)現(xiàn) Action 類大大減少了開發(fā)工作。
可以開展進(jìn)一步工作,使用適當(dāng)?shù)漠惓L幚砗途彺娣?wù)加強(qiáng)實(shí)現(xiàn)。也可以實(shí)現(xiàn)注釋支持,協(xié)助開發(fā)人員創(chuàng)建默認(rèn)配置,無需在配置文件中指定它。
致謝
我真誠地感謝我的同事 Rajesh Mishra 先生,他幫助我審查內(nèi)容,提供了寶貴的建議和評論。這不僅幫助我提高了框架的可用性,而且還使其外觀更加完美。
下載資源
- 本框架樣例實(shí)現(xiàn)代碼 (RESTWS.war | 10KB)
總結(jié)
以上是生活随笔為你收集整理的REST,Web 服务,REST-ful 服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 把 SOAP 服务转化为 REST 服务
- 下一篇: 构建 RESTful Web 服务