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