Restlet是一個Java下的輕量級REST框架。通過擁抱REST(REST是一種Web架構風格)它模糊了Web站點和Web服務之間的界限,從而幫助開發(fā)人員構建Web應用。每一個主要的REST概念(REST concept)都有一個對應的Java類。你的REST化的Web設計和你的代碼之間的映射是非常簡單直接的。
為什么有必要創(chuàng)建另一種框架?難道Servlet API還不夠好用嗎?
Servlet AIP在1998年發(fā)布,從那個時候起它的核心設計一直沒有很大的變化。它是Java EE的眾多API中最成功的一個,但是它的幾個設計缺陷和一些限制損害了它。舉個例子,URI模式和它的處理者(handler)之間的映射是受限制的,而且其配置都集中在一個配置文件中。還有,它把socket流的控制直接交給了應用系統(tǒng)開發(fā)人員,Servlet容器阻礙了我們充分使用NIO特性對IO操作進行優(yōu)化。另一個主要問題就是Servlet API鼓勵應用開發(fā)者在應用或者用戶會話級別直接將session狀態(tài)保存于內(nèi)存中,盡管這看上去不錯,但它造成了Servlet容器擴展性和高可用性的主要問題。為了克服這些問題,就必須實現(xiàn)復雜的負載均衡、session復制、持久化機制。這導致了可擴展性必然成為災難。
如何看待別的框架中對REST的支持(例如Axis2,或者CXF/XFire)?
這些支持非常有效,但是作用非常有限。我的主要觀點是設計這些項目是為了符合WS-*/SOAP Stack,它們與REST世界并不非常契合。在REST世界里,定義了一個全新的范例:面向資源的設計,而非通過遠程方法調(diào)用這樣的范例。例如Axis2僅僅支持GET和POST兩種HTTP方法,它需要遠程方法的傳遞需要一個URI參數(shù)。這在REST中式不允許的,這種做法也不能被稱之為REST化。XFire1.2不支持REST,但是它發(fā)布了一個項目用于將POJO映射到REST化的Web服務。這有點類似最近發(fā)布的JSR-311,此JSR試圖基于一套annotation和助手類標準化這種映射。
REST與HTTP協(xié)議
REST軟件架構是由Roy Thomas Fielding博士在2000年首次提出的。他為我們描繪了開發(fā)基于互聯(lián)網(wǎng)的網(wǎng)絡軟件的藍圖。REST軟件架構是一個抽象的概念,是一種為了實現(xiàn)這一互聯(lián)網(wǎng)的超媒體分布式系統(tǒng)的行動指南。利用任何的技術都可以實現(xiàn)這種理念。而實現(xiàn)這一軟件架構最著名的就是HTTP協(xié)議。通常我們把REST也寫作為REST/HTTP,在實際中往往把REST理解為基于HTTP的REST軟件架構,或者更進一步把REST和HTTP看作為等同的概念。今天,HTTP是互聯(lián)網(wǎng)上應用最廣泛的計算機協(xié)議。HTTP不是一個簡單的運載數(shù)據(jù)的協(xié)議,而是一個具有豐富內(nèi)涵的網(wǎng)絡軟件的協(xié)議。它不僅僅能夠?qū)τ诨ヂ?lián)網(wǎng)資源進行唯一定位,而且還能告訴我們對于該資源進行怎樣運作。這也是REST軟件架構當中最重要的兩個理念。而REST軟件架構理念是真正理解HTTP協(xié)議而形成的。有了REST軟件架構理念出現(xiàn),才使得軟件業(yè)避免了對HTTP協(xié)議的片面理解。只有正確的理論指導,才能避免在軟件開發(fā)的實際工作過程中少走彎路。
REST與URI(資源定位)
REST軟件架構之所以是一個超媒體系統(tǒng),是因為它可以把網(wǎng)絡上所有資源進行唯一的定位,不管你的文件是圖片、文件Word還是視頻文件,也不管你的文件是txt文件格式、xml文件格式還是其它文本文件格式。它利用支持HTTP的TCP/IP協(xié)議來確定互聯(lián)網(wǎng)上的資源。
REST與CRUD原則
REST軟件架構遵循了CRUD原則,該原則告訴我們對于資源(包括網(wǎng)絡資源)只需要四種行為:創(chuàng)建(Create)、獲取(Read)、更新(Update)和銷毀(DELETE)就可以完成對其操作和處理了。其實世界萬物都是遵循這一規(guī)律:生、變、見、滅。所以計算機世界也不例外。這個原則是源自于我們對于數(shù)據(jù)庫表的數(shù)據(jù)操作:insert(生)、select(見)、update(變)和delete(滅),所以有時候CRUD也寫作為RUDI,其中的I就是insert。這四個操作是一種原子操作,即一種無法再分的操作,通過它們可以構造復雜的操作過程,正如數(shù)學上四則運算是數(shù)字的最基本的運算一樣。
REST與網(wǎng)絡服務
盡管在Java語言世界中網(wǎng)絡服務目前是以SOAP技術為主,但是REST將是是網(wǎng)絡服務的另一選擇,并且是真正意義上的網(wǎng)絡服務?;赗EST思想的網(wǎng)絡服務不久的將來也會成為是網(wǎng)絡服務的主流技術。REST不僅僅把HTTP作為自己的數(shù)據(jù)運輸協(xié)議,而且也作為直接進行數(shù)據(jù)處理的工具。而當前的網(wǎng)絡服務技術都需要使用其它手段來完成數(shù)據(jù)處理工作,它們完全獨立于HTTP協(xié)議來進行的,這樣增加了大量的復雜軟件架構設計工作。REST的思想充分利用了現(xiàn)有的HTTP技術的網(wǎng)絡能力。在德國電視臺上曾經(jīng)出現(xiàn)過一個這樣的五十萬歐元智力題:如何實現(xiàn)網(wǎng)絡服務才能充分利用現(xiàn)有的HTTP協(xié)議?該問題給出了四個答案:去問微軟;WSDL2.0/SOAP1.2;WS-Transfer;根本沒有。這個問題告訴我們HTTP并不是一個簡單的數(shù)據(jù)傳來傳去的協(xié)議,而是一個聰明的會表現(xiàn)自己的協(xié)議,這也許是REST = Representational State Transfer的真正含義。實際上目前很多大公司已經(jīng)采用了REST技術作為網(wǎng)絡服務,如Google、Amazon等。在Java語言中重要的兩個以SOAP技術開始的網(wǎng)絡服務框架XFire和Axis也把REST作為自己的另一種選擇。它們的新的項目分別是Apache CXF和Axis2。Java語言也制定關于REST網(wǎng)絡服務規(guī)范:JAX-RS: Java API for RESTful Web Services (JSR 311)。相信還會出現(xiàn)更多與REST相關的激動人心的信息。
REST與AJAX技術
盡管AJAX技術的出現(xiàn)才不到兩年時間,但是AJAX技術遵循了REST的一些重要原則。AJAX技術充分利用了HTTP來獲取網(wǎng)絡資源并且實現(xiàn)了HTTP沒有的對于異步數(shù)據(jù)進行傳輸?shù)墓δ堋JAX技術還使得軟件更好地實現(xiàn)分布性功能,在一個企業(yè)內(nèi)只要一個人下載了AJAX引擎,其它企業(yè)內(nèi)部的人員,就可以共享該資源了。AJAX技術遵守REST準則的應用程序中簡單和可伸縮的架構,凡是采用AJAX技術的頁面簡潔而又豐富,一個頁面表現(xiàn)了豐富多彩的形態(tài)。AJAX技術還使用了一種不同于XML格式的JSON文件格式,這個意義在哪里呢?在REST軟件架構下我們不能對于XML文件進行序列化處理,這樣程序員必須要使用自己的XML綁定框架。而以序列化的JavaScript對象為基礎的JSON已經(jīng)獲得了廣泛認可,它被認為能以遠比XML更好的方式來序列化和傳輸簡單數(shù)據(jù)結構,而且它更簡潔。這對REST是一個極大貢獻和補充。當前的網(wǎng)絡應用軟件還違背了REST的“無狀態(tài)服務器”約束。REST服務器只知道自己的狀態(tài)。REST不關心客戶端的狀態(tài),客戶端的狀態(tài)自己來管理,這是AJAX技術的應用之地。通過AJAX技術,可以發(fā)揮有狀態(tài)網(wǎng)絡客戶機的優(yōu)勢。而REST的服務器關心的是從所有網(wǎng)絡客戶端發(fā)送到服務器操作的順序。這樣使得互聯(lián)網(wǎng)這樣一個巨大的網(wǎng)絡得到有序的管理。
REST與Rails框架
Ruby on Rails框架(簡稱Rails或者Rails框架)是一個基于Ruby語言的越來越流行的網(wǎng)絡應用軟件開發(fā)框架。它提供了關于REST最好的支持,也是當今應用REST最成功的一個軟件開發(fā)框架。Rails框架(從版本1.2.x起)成為了第一個引入REST作為核心思想的主流網(wǎng)絡軟件開發(fā)框架。在Rails框架的充分利用了REST軟件架構之后,人們更加堅信REST的重要性和必要性。Rails利用REST軟件架構思想對網(wǎng)絡服務也提供了一流的支持。從最直觀的角度看待REST,它是網(wǎng)絡服務最理想的手段,但是Rails框架把REST帶到了網(wǎng)絡應用軟件開發(fā)框架。這是一次飛躍,讓REST的思想從網(wǎng)絡服務的應用提升到了網(wǎng)絡應用軟件開發(fā)。利用REST思想的simply_restful插件已經(jīng)成為了Rails框架的核心內(nèi)容。
REST安全性
我們把現(xiàn)有基于SOAP的網(wǎng)絡服務和基于REST/HTTP網(wǎng)絡服務作個比喻,前者是一種傳統(tǒng)的寄信方式,而后者是現(xiàn)代網(wǎng)絡的電子郵件方式。要是是寄信和電子郵件都有病毒存在的話,傳統(tǒng)的寄信被送到對方就很危險,而電子郵件是開發(fā)的,電子郵件供應商比如Google為我們檢查了電子郵件是否有病毒。這里并不是說明SOAP網(wǎng)絡服務消息包含義病毒,而是說明HTTP是無法處理SOAP信息包究竟好不好,需要額外的軟件工具解決這一問題,包括防火墻也用不上和管不了。
REST/HTTP網(wǎng)絡服務的信息包可以被防火墻理解和控制。你可以按照操作和鏈接進行過濾信息包,如你可以規(guī)定從外部來的只能讀?。℅ET操作)自己服務器的資源。這樣對于系統(tǒng)管理員而言使得軟件管理更為簡單。REST的安全性還可以利用傳輸安全協(xié)議SSL/TLS、基本和摘要式認證(Basic und Digest Authentication)。除了這些REST自身的安全性功能外,還可以利用像基于信息的Web Services Security(JSR 155)作為REST不錯的補充。
Restlet第一步:
這篇文章讓你在10分鐘內(nèi)嘗試簡單的Restlet框架。告訴你如何創(chuàng)建一個說“hello, world”的Resource。
1.我需要什么?
2.“hello, world”應用
3.在Servlet容器中運行
4.作為一個單獨的Java應用運行
5.結尾
1.我需要什么?
我們假設你已經(jīng)有了一個可以馬上使用的開發(fā)環(huán)境,并且你已經(jīng)安裝了JRE1.5(或更高)。如果你還沒有下載Restlet,請選擇最新的Restlet Framework 1.0發(fā)行版。
2.“hello, world”程序
讓我們從REST應用的核心---資源開始入手。下面的代碼是這個程序涉及的唯一資源??截?粘貼代碼到“HelloWorldResource”類中。
Java代碼
01packagefirstSteps;
02
03importorg.restlet.Context;
04importorg.restlet.data.MediaType;
05importorg.restlet.data.Request;
06importorg.restlet.data.Response;
07importorg.restlet.resource.Representation;
08importorg.restlet.resource.Resource;
09importorg.restlet.resource.StringRepresentation;
10importorg.restlet.resource.Variant;
11
12/**
13* Resource which has only one representation.
14*
15*/
16publicclassHelloWorldResourceextendsResource {
17
18publicHelloWorldResource(Context context, Request request,
19 Response response) {
20super(context, request, response);
21
22// This representation has only one type of representation.
23 getVariants().add(newVariant(MediaType.TEXT_PLAIN));
24 }
25
26/**
27* Returns a full representation for a given variant.
28*/
29 @Override
30publicRepresentation getRepresentation(Variant variant) {
31 Representation representation =newStringRepresentation(
32 "hello, world", MediaType.TEXT_PLAIN);
33returnrepresentation;
34 }
35 }
然后創(chuàng)建應用例子。我們創(chuàng)建名為“FirstStepsApplication”的類并拷貝/粘貼下面的代碼:
01packagefirstSteps;
02
03importorg.restlet.Application;
04importorg.restlet.Context;
05importorg.restlet.Restlet;
06importorg.restlet.Router;
07
08publicclassFirstStepsApplicationextendsApplication {
09
10publicFirstStepsApplication(Context parentContext) {
11super(parentContext);
12 }
13
14/**
15* Creates a root Restlet that will receive all incoming calls.
16*/
17 @Override
18publicsynchronizedRestlet createRoot() {
19// Create a router Restlet that routes each call to a
20// new instance of HelloWorldResource.
21 Router router =newRouter(getContext());
22
23// Defines only one route
24 router.attachDefault(HelloWorldResource.class);
25
26returnrouter;
27 }
28 }
3.在Servlet容器中運行
你可能更熟悉Servlets,我們建議你在你喜歡的Servlet容器里運行Restlet應用。像往常一樣創(chuàng)建一個新的Servlet應用,把下面列出的jar包放入lib目錄。
org.restlet.jar
com.noelios.restlet.jar
com.noelios.restlet.ext.servlet_2.4.jar
然后按下面的配置修改“web.xml”配置文件:
01 <?xml version="1.0" encoding="UTF-8"?>
02<web-appid="WebApp_ID" version="2.4"
03 xmlns="http://java.sun.com/xml/ns/j2ee"
04 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
05 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
06http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
07<display-name>first steps servlet</display-name>
08<!-- Application class name -->
09<context-param>
10<param-name>org.restlet.application</param-name>
11<param-value>
12 firstSteps.FirstStepsApplication
13</param-value>
14</context-param>
15
16<!-- Restlet adapter -->
17<servlet>
18<servlet-name>RestletServlet</servlet-name>
19<servlet-class>
20 com.noelios.restlet.ext.servlet.ServerServlet
21</servlet-class>
22</servlet>
23
24<!-- Catch all requests -->
25<servlet-mapping>
26<servlet-name>RestletServlet</servlet-name>
27<url-pattern>/*</url-pattern>
28</servlet-mapping>
29</web-app>
最后,將程序打包成一個war文件,例如“firstStepsServlet.war”,并部署到你的Servlet容器里。啟動Servlet容器后,打開你喜歡的瀏覽器,輸入URL:“http://<你的服務器名>:<端口號>/firstStepsServlet”。服務器將很高興地用“hello, world”歡迎你。
4.作為一個單獨的Java應用運行
Restlet應用并不是只能運行在Servlet容器里,也可以使用下面幾個Jar包所為一個獨立應用運行:
org.restlet.jar
com.noelios.restlet.jar
com.noelios.restlet.ext.simple.jar
org.simpleframework.jar
如果你想要理解后面兩個Jar包的意義,你可以參考連接器(
http://www.restlet.org/documentation/1.0/connectors)。
創(chuàng)建一個主類,拷貝/粘貼下面的代碼。建立一個新的HTTP服務器監(jiān)聽端口8182并委托所有的請求給“FirstStepsApplication”。
代碼:
01packagefirstSteps;
02importorg.restlet.Component;
03importorg.restlet.data.Protocol;
04
05publicclassFirstStepsMain {
06
07publicstaticvoidmain(String[] args) {
08try{
09// Create a new Component.
10 Component component =newComponent();
11// Add a new HTTP server listening on port 8182.
12 component.getServers().add(Protocol.HTTP, 8182);
13
14// Attach the sample application.
15 component.getDefaultHost().attach(
16newFirstStepsApplication(component.getContext()));
17
18// Start the component.
19 component.start();
20 }catch(Exception e) {
21// Something is wrong.
22 e.printStackTrace();
23 }
24 }
25 }
啟動Main對象,打開你喜歡的瀏覽器,輸入URL:“http://localhost:8182/”,服務器將高興地用“hello, world”歡迎你。否則,確認Classpath正確且沒有其他應用占用8182端口。
RestLet第二步:晉級篇
這里說明Resource如何處理GET,POST,PUT和DELETE方法。
1.引言
2.示例程序
3.實現(xiàn)Items Resource
4.實現(xiàn)Item Resource
5.實現(xiàn)Base Resource
6.運行應用
7.客戶端應用
8.總結
1. 引言
在開始開發(fā)前,我們需要簡單介紹一下Restlet框架的Resource概念。REST告訴我們,Resource根據(jù)URI進行辨認,同時能夠有一種或多種表現(xiàn)(也被稱作變量),用以響應方法調(diào)用。
在Restlet框架中,服務器連接器(server connectors)收到的調(diào)用最終由Resource的實例對象處理。一個Resource負責聲明支持的表現(xiàn)方式列表(Variant對象的實例)和實現(xiàn)你想要支持的REST方法。
GET依賴可更改的“variants”列表和“getRepresentation(Variant)”方法。
POST依賴“allowPost”方法和“post(Representation)”方法。
DELETE依賴“allowPut”方法和“put(Representation)”方法。
DELETE依賴“allowDelete”方法和“delete()”方法。
還有,每一個到達的響應由一個專門的Resource實例處理,你不需要操心這些方法的線程安全問題。
我們假設你已經(jīng)讀過“第一步”,并且有了一些元件和應用的概念。
2.示例程序
一個Item列表用來管理創(chuàng)建,讀取,更新,和刪除活動,如一個典型的CRUD應用。一個Item包含名字和描述。在簡短的分析后,我們定義了兩個資源:
Items Resource代表所有可用Item的集合。
Item Resource代表一個單獨的item。
現(xiàn)在,讓我們定義用來標志item的Resource URIs。假設我們的應用運行在本機“localhost”并且監(jiān)聽8182端口:
http://localhost:8182/firstResource/items:“items”Resource URI。
http://localhost:8182/firstResource/items/{itemName}:“item”Resource URI,每個{itemName}代表一個Item的名字。
下一步,定義每個Resource允許訪問的方法列表。
“items”Resource響應GET請求并以一個XML文檔展示當前注冊的所有Item列表。另外,Resource支持通過POST請求創(chuàng)建新的Item。提交的實體包含新的Item的名字和描述,這些是以格式化的Web表單方式提交的。如果Resource成功創(chuàng)建新Item,它返回一個“Success - resource created”狀態(tài)(HTTP 201狀態(tài)代碼)并且告訴客戶端新Resource在哪里可以找到(HTTP "Location" header)。否則,它返回一個“Client error”狀態(tài)(HTTP 404狀態(tài)代碼)和一個簡單的錯誤信息。
“item”Resource響應GET請求并以一個XML文檔來展示該Resource的名字和描述。也可以通過PUT和DELETE請求更新和刪除Resource。
在描述兩個Resource對象前,首先編寫應用的代碼。為簡化起見,注冊的Item列表做為應用的一個屬性簡單地保存到內(nèi)存里,并不保存到一個真實的數(shù)據(jù)庫。不管怎樣,我們假設你想邀請你的朋友們同時測試這個應用。因為我們只有一個“FirstResourceApplication”實例在運行,所以不得不考慮線程安全。這也就是為什么你會發(fā)現(xiàn)Map對象Items是不不可更改的,它是一個ConcurrentHashMap對象的實例。
代碼:
01packagefirstResource;
02
03importjava.util.Map;
04importjava.util.concurrent.ConcurrentHashMap;
05
06importorg.restlet.Application;
07importorg.restlet.Context;
08importorg.restlet.Restlet;
09importorg.restlet.Router;
10
11publicclassFirstResourceApplicationextendsApplication {
12
13 /** The list of items is persisted in memory. */
14 privatefinalMap<String, Item> items;
15
16 publicFirstResourceApplication(Context parentContext) {
17 super(parentContext);
18 // We make sure that this attribute will support concurrent access.
19 items =newConcurrentHashMap<String, Item>();
20 }
21
22 /**
23 * Creates a root Restlet that will receive all incoming calls.
24 */
25 @Override
26 publicsynchronizedRestlet createRoot() {
27 // Create a router Restlet that defines routes.
28 Router router =newRouter(getContext());
29
30 // Defines a route for the resource "list of items"
31 router.attach("/items", ItemsResource.class);
32 // Defines a route for the resource "item"
33 router.attach("/items/{itemName}", ItemResource.class);
34
35 returnrouter;
36 }
37
38 /**
39 * Returns the list of registered items.
40 *
41 * @return the list of registered items.
42 */
43 publicMap<String, Item> getItems() {
44 returnitems;
45 }
46 }
2. 實現(xiàn)Items Resource
讓我們開始編寫Items Resource。如上文所述,它允許GET和POST請求。POST請求支持實現(xiàn)“post(Representation)”方法賦予處理消息實體的權限。此外,資源通過“allowPost”方法來確定是否開啟POST支持。缺省情況下,資源是不可更改的,拒絕POST、PUT和DELETE方法并返回“Method not allowed”狀態(tài)(HTTP 405狀態(tài)代碼)。
同樣,通過實現(xiàn)“represent(Variant)”方法確定你可以接受GET請求并根據(jù)指定的Variant生成實體。在這個例子中,我們只生成“text/xml”這種形式。
代碼:
001packagefirstResource;
002
003importjava.io.IOException;
004importjava.util.Collection;
005
006importorg.restlet.Context;
007importorg.restlet.data.Form;
008importorg.restlet.data.MediaType;
009importorg.restlet.data.Request;
010importorg.restlet.data.Response;
011importorg.restlet.data.Status;
012importorg.restlet.resource.DomRepresentation;
013importorg.restlet.resource.Representation;
014importorg.restlet.resource.StringRepresentation;
015importorg.restlet.resource.Variant;
016importorg.w3c.dom.Document;
017importorg.w3c.dom.Element;
018
019/**
020* Resource that manages a list of items.
021*
022*/
023publicclassItemsResourceextendsBaseResource {
024
025 /** List of items. */
026 Collection<Item> items;
027
028 publicItemsResource(Context context, Request request, Response response) {
029 super(context, request, response);
030
031 // Get the items directly from the "persistence layer".
032 items = getItems().values();
033
034 // Declare the kind of representations supported by this resource.
035 getVariants().add(newVariant(MediaType.TEXT_XML));
036 }
037
038 @Override
039 publicbooleanallowPost() {
040 returntrue;
041 }
042
043 /**
044 * Returns a listing of all registered items.
045 */
046 @Override
047 publicRepresentation getRepresentation(Variant variant) {
048 // Generate the right representation according to its media type.
049 if(MediaType.TEXT_XML.equals(variant.getMediaType())) {
050 try{
051 DomRepresentation representation =newDomRepresentation(
052 MediaType.TEXT_XML);
053 // Generate a DOM document representing the list of
054 // items.
055 Document d = representation.getDocument();
056 Element r = d.createElement("items");
057 d.appendChild(r);
058 for(Item item : items) {
059 Element eltItem = d.createElement("item");
060
061 Element eltName = d.createElement("name");
062 eltName.appendChild(d.createTextNode(item.getName()));
063 eltItem.appendChild(eltName);
064
065 Element eltDescription = d.createElement("description");
066 eltDescription.appendChild(d.createTextNode(item
067 .getDescription()));
068 eltItem.appendChild(eltDescription);
069
070 r.appendChild(eltItem);
071 }
072 d.normalizeDocument();
073
074 // Returns the XML representation of this document.
075 returnrepresentation;
076 }catch(IOException e) {
077 e.printStackTrace();
078 }
079 }
080
081 returnnull;
082 }
083
084 /**
085 * Handle POST requests: create a new item.
086 */
087 @Override
088 publicvoidpost(Representation entity) {
089 // Parse the given representation and retrieve pairs of
090 // "name=value" tokens.
091 Form. form. =newForm(entity);
092 String itemName = form.getFirstValue("name");
093 String itemDescription = form.getFirstValue("description");
094
095 // Check that the item is not already registered.
096 if(getItems().containsKey(itemName)) {
097 generateErrorRepresentation(
098 "Item " + itemName + " already exists.", "1", getResponse());
099 }else{
100 // Register the new item
101 getItems().put(itemName,newItem(itemName, itemDescription));
102
103 // Set the response's status and entity
104 getResponse().setStatus(Status.SUCCESS_CREATED);
105 Representation rep =newStringRepresentation("Item created",
106 MediaType.TEXT_PLAIN);
107 // Indicates where is located the new resource.
108 rep.setIdentifier(getRequest().getResourceRef().getIdentifier()
109 + "/" + itemName);
110 getResponse().setEntity(rep);
111 }
112 }
113
114 /**
115 * Generate an XML representation of an error response.
116 *
117 * @param errorMessage
118 * the error message.
119 * @param errorCode
120 * the error code.
121 */
122 privatevoidgenerateErrorRepresentation(String errorMessage,
123 String errorCode, Response response) {
124 // This is an error
轉(zhuǎn)載地址:http://blog.ixpub.net/html/07/12399407-251280.html