相信大家在閱讀
CXF官方文檔(http://cxf.apache.org/docs/index.html)時,總是一知半解。這里向大家推薦一本PacktPub.Apache.CXF.Web.Service.Development。目前,這本書是沒有中文版的,為此筆者簡單的寫了一些經驗總結。CXF官方文檔(http://cxf.apache.org/docs/index.html)時,總是一知半解。這里向大家推薦一本PacktPub.Apache.CXF.Web.Service.Development。目前,這本書是沒有中文版的,為此筆者簡單的寫了一些經驗總結。
這本書內容上安排的比較淺顯,語言上也沒有什么深奧的,值得一讀。另外值得一提的是,這本書比官方文檔高明之處是每個概念就介紹得很清楚,像第二章的Code-first和Contract-first,第5章的Feature和Interceptor概念的介紹,還有第6章的REST概念簡介,內容上都比官方文檔詳細很多。缺點就是并沒有將CXF所有的特性都寫下來,這就需要將samples中的內容好好消化一下了。
代碼使用Maven組織
http://dl.iteye.com/topics/download/fbbf344b-2357-33fe-86d7-a44116e6de85
在各個系統(tǒng)交互領域,Web services逐漸成為主流。有兩種主要方式來開發(fā)Web Services:Simple Object Access Protocol (SOAP)和Representational State Transfer (REST)
開發(fā)基于SOAP的Web Services需要很多的約束, 以便客戶端和服務端交互信息,例如,使用Web Service Description Language (WSDL)來描述信息。還有很多WS的標準如WS-Security。
使用REST構架的服務被稱為RESTful服務。這種架構利用簡單的XML在HTTP協(xié)議上,就像網頁一樣發(fā)送請求,簡化了基于SOAP架構開發(fā)。RESTful Web Services尤其適用于只需要提交和接受簡單的XML信息。
接下來會介紹使用CXF框架來開發(fā)RESTful風格的Web Services。
簡介
Java API for RESTful services
CXF JAX-RS實現(xiàn)
開發(fā)RESTful服務
REST也就是Representational State Transfer。REST并不特指一種技術,也不是一個標準,它僅僅是一個構架風格。REST 指的是一組架構約束條件和原則。滿足這些約束條件和原則通過網絡暴露資源給用戶。事實上,WWW就是經典的REST架構風格。在服務器端,應用程序狀態(tài)和功能可以分為各種資源。它向客戶端公開。每個資源都使用 URI (Universal Resource Identifier) 得到一個惟一的地址。所有資源都共享統(tǒng)一的界面,以便在客戶端和服務器之間傳輸狀態(tài)。使用的是標準的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。客戶端通過交換各種資源的表現(xiàn)體來查詢或更新資源。資源的表現(xiàn)體包括HTML,XML,JSON等??蛻舳诵枰馕鲰憫掌鞯谋憩F(xiàn)體。客戶端和服務器之間的交互在請求之間是無狀態(tài)的,無狀態(tài)請求可以由任何可用服務器應答。
下面是一些RESTfu例子,提供雇員和部門的信息,并介紹客戶端怎樣訪問這些服務
URI for the RESTful service—http://<host>/department/deptname/employee:
· GET—獲得deptname部門的所有員工信息
· POST—為deptname部門創(chuàng)建員工信息。
· DELETE—刪除 deptname部門一名員工信息
URI for the RESTful service—http://<host>/department/deptname/employee/naveen:
· GET—獲得deptname部門名叫naveen的員工信息
· PUT—為deptname部門創(chuàng)建名叫naveen的員工信息
· DELETE—刪除deptname部門名叫naveen的員工信息
下面是POST請求的例子http://<host>/department/deptname/employee
POST /department/deptname/employee HTTP/1.1
Content-Type: */*
Accept: application/xml
User-Agent: Apache CXF 2.2.2
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:9001
<employee><firstname>rajeev</firstname><lastname>hathi</lastname>
<dob>10/26/78</dob></employee>
上一節(jié),我們了解雇員POST請求。如果需要提供一種實現(xiàn)去識別雇員POST請求,我們應該做如下工作:
識別這是否一個HTTP POST請求。
將HTTP POST請求中的XML的內容轉換為實現(xiàn)端所需要的格式,例如JAVA對象。
執(zhí)行指定的操作,例如插入雇員信息到數(shù)據(jù)庫。
以HTTP形式響應客戶端,例如設置標志響應成功的HTTP狀態(tài)200 ,并將響應轉換到指定格式(XML或JSON),最后將其設置到HTTP Body。
依據(jù)需求,可能你要實現(xiàn)所有的HTTP方法,如GET,PUT,DELETE等。這不就是標準的RESTful JAVA開發(fā)模式嗎?接著,Java API for RESTful Web services (JAX-RS)規(guī)范制定了開發(fā)RESTful的標準。
JAX-RS規(guī)范定義了創(chuàng)建RESTful服務的語法。JAX-RS使用annotations注解在實現(xiàn)RESTful的服務,使用annotations注解POJO將它暴露為RESTful資源。RESTful服務類中,通過URI(/category)和HTTP(GET, POST)方法注解方法。
@GET
@Path("/category/{id}")
public Category getCategory(@PathParam("id") String id)
實現(xiàn)JAX-RS的框架在運行的時候,通過映射HTTP請求到RESTful方法,負責調用正確的JAVA實現(xiàn)方法。JAX-RS規(guī)范提供這種映射的方法的算法?;A算法包括,判斷JAVA資源類,判斷HTTP URI請求,判斷內容格式(例如application/xml),還有HTTP方法(例如GET)
JAX-RS規(guī)范提出如下要點:
POJO依賴性
為了暴露為資源,使用annotations注解POJO,
HTTP依賴性
RESTful資源暴露在HTTP中,規(guī)范中將HTTP 協(xié)議和JAX-RS API相對應映射。
格式獨立性
API中提供嵌入式的方法,標準化添加HTTP內容的類型。例如,application/xml就是HTTP內容的類型中的一種。
容器獨立性
可以在任何一種容器中部署實現(xiàn)JAX-RS規(guī)范的應用程序。
CXF實現(xiàn)了JAX-RS1.0規(guī)范,并提供了很多特性幫助開發(fā)者搭建企業(yè)級的RESTful服務。
下面是CXF框架提供創(chuàng)建RESTful服務的各種特性。
集成Spring
Spring框架已經變成事實上的構建企業(yè)級JAVA應用程序集成框架。CXF提供與Spring整合,簡化了配置和部署RESTful應用程序。Spring提供依賴注入促進松散耦合,提供各種服務,像聲明式事務管理。所有這些Spring提供的特性都可以被開發(fā)RESTful服務的CXF框架使用。
插入式數(shù)據(jù)綁定
數(shù)據(jù)庫綁定就是映射HTTP請求,例如JSON或XML,到對應的JAVA對象。同樣的,在發(fā)送HTTP響應之前,服務端的JAVA實現(xiàn)需要映射為客戶端所需要的格式。通過提供數(shù)據(jù)庫綁定組件,CXF在后臺透明的處理映射。CXF支持各種數(shù)據(jù)綁定機制,如JAXB,JSON,XMLBean和Aegis。CXF允許指定特定的綁定機制。
客戶端API
JAX-RS規(guī)范并沒有提供客戶端調用REST服務的API。CXF提供了這種API直接調用RESTful服務,也可以使用Spring框架配置到應用程序中。
安全
CXF可以使用Spring框架集成的聲明式安全組件,按照應用程序的需要限制資源類和方法,而不必使用代碼處理安全性問題。
過濾器
過濾器用來預處理或后處理信息。CXF可以創(chuàng)建和配置過濾器來審核信息,記錄信息的日志,還有基于應用要求修改請求或響應。
CXF也運行開發(fā)者使用JAX-WS Provider和Dispatch API來創(chuàng)建RESTful服務。
本節(jié)將介紹使用JAX-RS實現(xiàn)的方法來開發(fā)RESTful服務,并執(zhí)行CRUD操作。首先看一下Book Shop應用。
Book Shop應用是一款網絡應用,提供技術書籍(JAVA或.NET)的分類。Book Shop讓管理員為新的書籍創(chuàng)建分類,修改分類等。一旦這個分類存在,應用可以為這個分類添加新的書籍。
這個應用將提供如下方法:
創(chuàng)建分類
更新分類
刪除分類
獲取分類列表
獲取特定分類
為特定分類添加書籍
獲取特定分類中所有書籍
為了開發(fā)RESTful服務,需要做如下工作:
創(chuàng)建POJO類
為POJO類提供數(shù)據(jù)綁定
創(chuàng)建實現(xiàn)RESTful功能的服務類
創(chuàng)建調用RESTful服務的客戶端
為了提供RESTful服務端和客戶端通信,POJO需要轉換為特定的格式,例如XML或JSON。為了實現(xiàn)這部分功能,需要一個數(shù)據(jù)綁定的組件來映射JAVA對象和XML(或者指定的格式)。
CXF使用JAXB作為默認的數(shù)據(jù)綁定組件。JAXB使用注解來定義JAVA對象和XML之間映射的關系。
在POJO類Category中,注解@XmlRootElement指定Category為XML的根元素。Category類的屬性默認指定映射為@XmlElement。@XmlElement用來定義XML中的子元素。@XmlRootElement和@XmlElement允許自定義命名空間和XML中元素的名稱。如果沒有定義的話,JAXB在運行的時候默認的使用同樣的屬性名和類名來定義XML元素。
下面的XML請求表示了Category數(shù)據(jù)對象。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Category>
<books>
<author>Naveen Balani</author>
<bookISBNnumber>ISBNB001</bookISBNnumber>
<bookId>NB001</bookId>
<bookName>Fiction Book1</bookName>
</books>
<categoryId>005</categoryId>
<categoryName>Fiction Series</categoryName>
</Category>
CategoryService的類聲明上定義了@Path 和@Produces注解。@Path定義了URI路徑,客戶端可以通過這個路徑訪問到CategoryService對象。如@Path("/categoryservice"),那么URI請求,就可以是http://localhost:9000/categoryservice/。@Produces定義了服務類和方法生產內容的類型。如@Produces("application/xml"),那么CategoryService只會生產application/xml。
每個方法都和@Produces相關,它決定了這個方法生產什么樣的響應。每個方法都有和HTTP方法映射的的注解,例如@GET 和@POST。方法中的@Path注解指定了該方法的URI。例如getCategory()方法上的@Path("/category/{id}"),可以使用http://localhost:9000/categoryservice/category/001,訪問到category id 為001的分類。{id}就好比參數(shù)。接著,讓我們看看@PathParam注解。@PathParam注解是用來給URI 路徑一個模板變量,方法的輸入參數(shù)。@PathParam("id") 就是URI中的 @Path ("/category/{id}")。
@GET
@Path("/category/{id}")
public Category getCategory(@PathParam("id") String id)
讓我們看一種情況,客戶端發(fā)送一個請求刪除或者更新一個分類,但是這個分類并不存在,那么服務端需要返回正確的錯誤信息給客戶端。
為了處理異常,JAX-RS提供了WebApplicationException,它繼承自RuntimeException類。WebApplicationException可以使用HTTP狀態(tài)代碼或者javax.ws.rs.core.Response對象作為構造器。Response對象除了提供HTTP狀態(tài)代碼外,還可以提供用戶容易識別的錯誤信息。
RESTful服務的異常處理可以分為如下幾類:
實現(xiàn)類拋出帶有HTTP錯誤代碼的WebApplicationException異常。一般的,4XX定義了客戶端錯誤,如錯誤請求;5XX定義了服務端錯誤,如服務器沒有完成請求。
直接發(fā)回javax.ws.rs.core.Response對象,Response對象中包含了HTTP錯誤代碼。
為了測試異常處理代碼,啟動CategoryServerStart類。在IE瀏覽器中輸入
http://localhost:9000/categoryservice/category/011
由于IE不會顯示自定義的錯誤信息,我們會看到HTTP 400 BAD Request。
如果你在Firefox或者Chrome,就會返回
<error>Category Not Found</error>
在@Produces 和 @Consumes注解中添加application/json,指定CategoryService除了application/xml外,還接收和產生application/json。CXF運行時會處理HTTP JSON請求到JAVA對象的轉換,還有JAVA對象到HTTP JSON響應的映射。
JAX-RS并不提供調用RESTful服務客戶端。CXF框架提供了兩種方式來創(chuàng)建客戶端,這兩種都可以使用Spring配置。
代理API
代理API允許你使用RESTful服務的資源類和接口。代理類是客戶端直接調用接口方法,使用戶不需要手工創(chuàng)建HTTP請求。將RESTful服務類傳遞給org.apache.cxf.jaxrs.client.JAXRSClientFactory類。一旦代理類創(chuàng)建好了,你可以直接使用RESTful服務接口類的任何方法。
CategoryService store = JAXRSClientFactory.create("http://
localhost:9000", CategoryService.class);
//Makes remote call to Category RESTFul service
store.getBooks("001");
HTTP客戶端
使用org.apache.cxf.jaxrs.client.WebClient調用RESTful服務。本例中采用HTTP客戶端。