- 浏览: 105725 次
- 来自: 北京
文章分类
最新评论
-
魔力猫咪:
mathgl 写道C++的书 如果是学习 一本大的就够了C++ ...
《高质量程序设计指南》试读 -
mathgl:
C++的书 如果是学习 一本大的就够了C++ Primer 第 ...
《高质量程序设计指南》试读 -
topbox163:
非常感谢感谢,终于把数据弄出来了,之前一起出不来,希望加下我: ...
猫学Grails之完善编写的第一个程序和数据库设置 -
wangxin0ldrs:
怎么样发送到付件的邮件啊,还望指导,我一下
使用Common Email轻松发送邮件 -
wangxin0ldrs:
Common Email除了可以发送普通邮件,也可以发送HTM ...
使用Common Email轻松发送邮件
猫咪继续翻译Restlet教程。看了这篇文章,应该对Restlet框架有所了解。
Restlet第一个Resource
目录
这篇文章说明Resource如何处理GET,POST,PUT和DELETE方法。
1.引言
2.例子应用
3.实现Items Resource
4.实现Item Resource
5.实现Base Resource
6.运行应用
7.客户端应用
8.结尾
引言
在开始开发前,我们需要简单介绍一下Restlet框架的Resource概念。REST告诉我们,Resource根据URL进行辨认,同时能够有一种或多种表现(也被称作变异体)呈现(Oaxaca的天气),能够响应处理方法。
在Restlet框架中,服务器连接的标准响应由Resource的实例对象最终处理。一个Resource负责声明支持的表现方式列表(Variant对象的实例)和实现你想要支持的REST方法。
GET依赖可更改的“variants”列表和“getRepresentation(Variant)”方法。
POST依赖“allowPost”方法和“post(Representation)”方法。
DELETE依赖“allowPut”方法和“put(Representation)”方法。
DELETE依赖“allowDelete”方法和“delete()”方法。
还有,每一个到达的响应由一个专门的Resource实例处理,你不需要操心这些方法的线程安全。
我们假设你已经读过“第一步”(http://www.restlet.org/documentation/1.0/firstSteps),并且有了一些元件和应用的概念。
例子应用
让我们开始描述我们的例子应用。一个Item列表用来管理创建,读取,更新,和删除活动像一个简单的CRUD应用。一个Item是以名字和描述的简单特征。在简短的分析后,我们定义了两个资源:
Items Resource等于所有可用Item的集合。
Item Resource等于一个单独的item。
现在,让我们定义Resource URIs。假设我们的应用运行在本机“localhost”并且监听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请求创建新的Item。提交的实体包含新Item的名字和描述并接收格式化的Web表单。如果Resource成功创建新Item,它返回一个“Success - resource created”状态(HTTP 201状态代码)并且告诉客户端新Resource在哪里可以找到(HTTP "Location" header)。否则,它返回一个“Client error”状态(HTTP 404状态代码)和一个简单的错误信息。
“item”Resource响应GET请求并以一个XML文档来展示该Resource的名字和描述。通过PUT和DELETE请求也能更新和删除Resource。
在描述两个Resource对象前,先编写你的应用。为了简化,注册的Item列表做为应用的一个属性简单地保存到内存里,并不保存到一个真实的数据库。不管怎样,我们假设你想邀请你的朋友们同时测试这个应用。因为我们只有一个“FirstResourceApplication”实例在运行,所以不得不考虑线程安全。这也就是为什么你会发现Map对象Items是不变的,是一个ConcurrentHashMap对象的实例。
实现Items Resource
让我们开始编写Items Resource。如上文所示,允许GET和POST请求。POST请求支持通过“post(Representation)”方法确定你如何处理消息实体。此外,资源通过“allowPost”方法支持POST。缺省情况下,资源是不可更改的,拒绝POST、PUT和DELETE方法并返回“Method not allowed”状态(HTTP 405状态代码)。同样,GET响应支持通过“represent(Variant)”方法确定你如何依照特定的Variant生成实体。假设,我们只生成“text/xml”形式。
实现Item Resource
让我们继续编写Item Resource。如上文所示,允许GET,PUT和DELETE请求。PUT请求支持通过“put(Representation)”方法确定你如何处理消息实体。
同样,DELETE请求支持执行“delete()”方法。
实现Base Resource
由于我们的Resource都需要访问“FirstResourceApplication”实例中保存Item的Map,这些方法因此被放入父类“BaseResource”。
运行应用
请查阅“第一步”(http://www.restlet.org/documentation/1.0/firstSteps)的相关章节学习如何在一个Servlet容器中运行应用或作为一个单独应用执行。
客户端应用
一旦我们的应用在一个Servlet容器或作为一个单独应用开始运行,我们建议你通过一个简单的客户端应用测试我们的Resource。它简单地创建、读取、更新和删除一个Item Resource并在每一个操作执行时打印标准输出结果。
客户端应用作为单独Java应用运行的时候需要如下的Jar包:
org.restlet.jar
com.noelios.restlet.jar
com.noelios.restlet.ext.httpclient.jar
org.apache.commons.httpclient.jar
你可以从http://www.restlet.org/documentation/1.0/examples/firstResource/sources.zip下载这个例子应用的源文件。
结尾
这篇文章说明了使用Restlet框架的重要方法。当思考你的Resource的时候,记住这些重要问题:
我应该如何识别我的Resource?
它们能够生成哪些表现?
它们有哪些处理方法?
我需要把同级Resource的哪些行为和属性共享?
我们希望你喜欢这些简单步骤并且我们现在鼓励你开始深入Restlet Tutorial。
备注:
感谢Tim Peierls反馈线程安全方面的考虑。
猫咪,你有没有测试过这篇文章的代码,BaseResource似乎有个错误,就在Application.KEY那里。
protected Map<String, Item> getItems() {
return ((FirstResourceApplication) getApplication()).getItems();
}
这个方法应该是这样的,
猫咪,你有没有测试过这篇文章的代码,BaseResource似乎有个错误,就在Application.KEY那里。
Restlet第一个Resource
目录
这篇文章说明Resource如何处理GET,POST,PUT和DELETE方法。
1.引言
2.例子应用
3.实现Items Resource
4.实现Item Resource
5.实现Base Resource
6.运行应用
7.客户端应用
8.结尾
引言
在开始开发前,我们需要简单介绍一下Restlet框架的Resource概念。REST告诉我们,Resource根据URL进行辨认,同时能够有一种或多种表现(也被称作变异体)呈现(Oaxaca的天气),能够响应处理方法。
在Restlet框架中,服务器连接的标准响应由Resource的实例对象最终处理。一个Resource负责声明支持的表现方式列表(Variant对象的实例)和实现你想要支持的REST方法。
GET依赖可更改的“variants”列表和“getRepresentation(Variant)”方法。
POST依赖“allowPost”方法和“post(Representation)”方法。
DELETE依赖“allowPut”方法和“put(Representation)”方法。
DELETE依赖“allowDelete”方法和“delete()”方法。
还有,每一个到达的响应由一个专门的Resource实例处理,你不需要操心这些方法的线程安全。
我们假设你已经读过“第一步”(http://www.restlet.org/documentation/1.0/firstSteps),并且有了一些元件和应用的概念。
例子应用
让我们开始描述我们的例子应用。一个Item列表用来管理创建,读取,更新,和删除活动像一个简单的CRUD应用。一个Item是以名字和描述的简单特征。在简短的分析后,我们定义了两个资源:
Items Resource等于所有可用Item的集合。
Item Resource等于一个单独的item。
现在,让我们定义Resource URIs。假设我们的应用运行在本机“localhost”并且监听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请求创建新的Item。提交的实体包含新Item的名字和描述并接收格式化的Web表单。如果Resource成功创建新Item,它返回一个“Success - resource created”状态(HTTP 201状态代码)并且告诉客户端新Resource在哪里可以找到(HTTP "Location" header)。否则,它返回一个“Client error”状态(HTTP 404状态代码)和一个简单的错误信息。
“item”Resource响应GET请求并以一个XML文档来展示该Resource的名字和描述。通过PUT和DELETE请求也能更新和删除Resource。
在描述两个Resource对象前,先编写你的应用。为了简化,注册的Item列表做为应用的一个属性简单地保存到内存里,并不保存到一个真实的数据库。不管怎样,我们假设你想邀请你的朋友们同时测试这个应用。因为我们只有一个“FirstResourceApplication”实例在运行,所以不得不考虑线程安全。这也就是为什么你会发现Map对象Items是不变的,是一个ConcurrentHashMap对象的实例。
package firstResource; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.restlet.Application; import org.restlet.Context; import org.restlet.Restlet; import org.restlet.Router; public class FirstResourceApplication extends Application { /** The list of items is persisted in memory. */ private final Map<String, Item> items; public FirstResourceApplication(Context parentContext) { super(parentContext); // We make sure that this attribute will support concurrent access. items = new ConcurrentHashMap<String, Item>(); } /** * Creates a root Restlet that will receive all incoming calls. */ @Override public synchronized Restlet createRoot() { // Create a router Restlet that defines routes. Router router = new Router(getContext()); // Defines a route for the resource "list of items" router.attach("/items", ItemsResource.class); // Defines a route for the resource "item" router.attach("/items/{itemName}", ItemResource.class); return router; } /** * Returns the list of registered items. * @return the list of registered items. */ public Map<String, Item> getItems() { return items; } }
实现Items Resource
让我们开始编写Items Resource。如上文所示,允许GET和POST请求。POST请求支持通过“post(Representation)”方法确定你如何处理消息实体。此外,资源通过“allowPost”方法支持POST。缺省情况下,资源是不可更改的,拒绝POST、PUT和DELETE方法并返回“Method not allowed”状态(HTTP 405状态代码)。同样,GET响应支持通过“represent(Variant)”方法确定你如何依照特定的Variant生成实体。假设,我们只生成“text/xml”形式。
import java.io.IOException; import java.util.Collection; import org.restlet.Context; import org.restlet.data.Form; import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; import org.restlet.resource.DomRepresentation; import org.restlet.resource.Representation; import org.restlet.resource.StringRepresentation; import org.restlet.resource.Variant; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Resource that manages a list of items. * */ public class ItemsResource extends BaseResource { /** List of items. */ Collection<Item> items; public ItemsResource(Context context, Request request, Response response) { super(context, request, response); // Get the items directly from the "persistence layer". items = getItems().values(); // Declare the kind of representations supported by this resource. getVariants().add(new Variant(MediaType.TEXT_XML)); } @Override public boolean allowPost() { return true; } /** * Returns a listing of all registered items. */ @Override public Representation getRepresentation(Variant variant) { // Generate the right representation according to its media type. if (MediaType.TEXT_XML.equals(variant.getMediaType())) { try { DomRepresentation representation = new DomRepresentation( MediaType.TEXT_XML); // Generate a DOM document representing the list of // items. Document d = representation.getDocument(); Element r = d.createElement("items"); d.appendChild(r); for (Item item : items) { Element eltItem = d.createElement("item"); Element eltName = d.createElement("name"); eltName.appendChild(d.createTextNode(item.getName())); eltItem.appendChild(eltName); Element eltDescription = d.createElement("description"); eltDescription.appendChild(d.createTextNode(item .getDescription())); eltItem.appendChild(eltDescription); r.appendChild(eltItem); } d.normalizeDocument(); // Returns the XML representation of this document. return representation; } catch (IOException e) { e.printStackTrace(); } } return null; } /** * Handle POST requests: create a new item. */ @Override public void post(Representation entity) { // Parse the given representation and retrieve pairs of // "name=value" tokens. Form form = new Form(entity); String itemName = form.getFirstValue("name"); String itemDescription = form.getFirstValue("description"); // Check that the item is not already registered. if (getItems().containsKey(itemName)) { generateErrorRepresentation( "Item " + itemName + " already exists.", "1", getResponse()); } else { // Register the new item getItems().put(itemName, new Item(itemName, itemDescription)); // Set the response's status and entity getResponse().setStatus(Status.SUCCESS_CREATED); Representation rep = new StringRepresentation("Item created", MediaType.TEXT_PLAIN); // Indicates where is located the new resource. rep.setIdentifier(getRequest().getResourceRef().getIdentifier() + "/" + itemName); getResponse().setEntity(rep); } } /** * Generate an XML representation of an error response. * * @param errorMessage * the error message. * @param errorCode * the error code. */ private void generateErrorRepresentation(String errorMessage, String errorCode, Response response) { // This is an error response.setStatus(Status.CLIENT_ERROR_NOT_FOUND); try { // Generate the output representation DomRepresentation representation = new DomRepresentation( MediaType.TEXT_XML); Document d = representation.getDocument(); Element eltError = d.createElement("error"); Element eltCode = d.createElement("code"); eltCode.appendChild(d.createTextNode(errorCode)); eltError.appendChild(eltCode); Element eltMessage = d.createElement("message"); eltMessage.appendChild(d.createTextNode(errorMessage)); eltError.appendChild(eltMessage); response.setEntity(new DomRepresentation(MediaType.TEXT_XML, d)); } catch (IOException e) { e.printStackTrace(); } } }
实现Item Resource
让我们继续编写Item Resource。如上文所示,允许GET,PUT和DELETE请求。PUT请求支持通过“put(Representation)”方法确定你如何处理消息实体。
同样,DELETE请求支持执行“delete()”方法。
import java.io.IOException; import org.restlet.Context; import org.restlet.data.Form; import org.restlet.data.MediaType; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.data.Status; import org.restlet.resource.DomRepresentation; import org.restlet.resource.Representation; import org.restlet.resource.Variant; import org.w3c.dom.Document; import org.w3c.dom.Element; public class ItemResource extends BaseResource { /** The underlying Item object. */ Item item; /** The sequence of characters that identifies the resource. */ String itemName; public ItemResource(Context context, Request request, Response response) { super(context, request, response); // Get the "itemName" attribute value taken from the URI template // /items/{itemName}. this.itemName = (String) getRequest().getAttributes().get("itemName"); // Get the item directly from the "persistence layer". this.item = getItems().get(itemName); if (this.item != null) { // Define the supported variant. getVariants().add(new Variant(MediaType.TEXT_XML)); } } /** * This resource supports DELETE requests. */ @Override public boolean allowDelete() { return true; } /** * This resource supports PUT requests. */ @Override public boolean allowPut() { return true; } /** * Handle DELETE requests. */ @Override public void delete() { if (item != null) { // Remove the item from the list. getItems().remove(item.getName()); } // Tells the client that the request has been successfully fulfilled. getResponse().setStatus(Status.SUCCESS_NO_CONTENT); } @Override public Representation getRepresentation(Variant variant) { if (MediaType.TEXT_XML.equals(variant.getMediaType())) { // Generate the XML representation of this resource. try { // Generate a DOM document representing the item. DomRepresentation representation = new DomRepresentation( MediaType.TEXT_XML); Document d = representation.getDocument(); Element eltItem = d.createElement("item"); d.appendChild(eltItem); Element eltName = d.createElement("name"); eltName.appendChild(d.createTextNode(item.getName())); eltItem.appendChild(eltName); Element eltDescription = d.createElement("description"); eltDescription.appendChild(d.createTextNode(item .getDescription())); eltItem.appendChild(eltDescription); d.normalizeDocument(); // Returns the XML representation of this document. return representation; } catch (IOException e) { e.printStackTrace(); } } return null; } /** * Handle PUT requests. */ @Override public void put(Representation entity) { // Tells if the item is to be created of not. boolean creation = (item == null); // The PUT request updates or creates the resource. if (item == null) { item = new Item(itemName); } // Update the description. Form form = new Form(entity); item.setDescription(form.getFirstValue("description")); // Update the item in the list. getItems().put(item.getName(), item); if (creation) { getResponse().setStatus(Status.SUCCESS_CREATED); } else { getResponse().setStatus(Status.SUCCESS_OK); } } }
实现Base Resource
由于我们的Resource都需要访问“FirstResourceApplication”实例中保存Item的Map,这些方法因此被放入父类“BaseResource”。
import java.util.Map; import org.restlet.Application; import org.restlet.Context; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.resource.Resource; /** * Base resource class that supports common behaviours or attributes shared by * all resources. * */ public abstract class BaseResource extends Resource { public BaseResource(Context context, Request request, Response response) { super(context, request, response); } /** * Returns the map of items managed by this application. * * @return the map of items managed by this application. */ protected Map<String, Item> getItems() { return ((FirstResourceApplication) getContext().getAttributes().get( Application.KEY)).getItems(); } }
运行应用
请查阅“第一步”(http://www.restlet.org/documentation/1.0/firstSteps)的相关章节学习如何在一个Servlet容器中运行应用或作为一个单独应用执行。
客户端应用
一旦我们的应用在一个Servlet容器或作为一个单独应用开始运行,我们建议你通过一个简单的客户端应用测试我们的Resource。它简单地创建、读取、更新和删除一个Item Resource并在每一个操作执行时打印标准输出结果。
客户端应用作为单独Java应用运行的时候需要如下的Jar包:
org.restlet.jar
com.noelios.restlet.jar
com.noelios.restlet.ext.httpclient.jar
org.apache.commons.httpclient.jar
import java.io.IOException; import org.restlet.Client; import org.restlet.data.Form; import org.restlet.data.Protocol; import org.restlet.data.Reference; import org.restlet.data.Response; import org.restlet.resource.Representation; public class FirstResourceClientMain { public static void main(String[] args) throws IOException { // Define our Restlet HTTP client. Client client = new Client(Protocol.HTTP); // The URI of the resource "list of items". Reference itemsUri = new Reference( "http://localhost:8182/firstResource/items"); // Create a new item Item item = new Item("item1", "this is an item."); Reference itemUri = createItem(item, client, itemsUri); if (itemUri != null) { // Prints the representation of the newly created resource. get(client, itemUri); } // Prints the list of registered items. get(client, itemsUri); // Update the item item.setDescription("This is an other description"); updateItem(item, client, itemUri); // Prints the list of registered items. get(client, itemsUri); // delete the item deleteItem(client, itemUri); // Print the list of registered items. get(client, itemsUri); } /** * Try to create a new item. * * @param item * the new item. * @param client * the Restlet HTTP client. * @param itemsUri * where to POST the data. * @return the Reference of the new resource if the creation succeeds, * null otherwise. */ public static Reference createItem(Item item, Client client, Reference itemsUri) { // Gathering informations into a Web form. Form form = new Form(); form.add("name", item.getName()); form.add("description", item.getDescription()); Representation rep = form.getWebRepresentation(); // Launch the request Response response = client.post(itemsUri, rep); if (response.getStatus().isSuccess()) { if (response.isEntityAvailable()) { try { // Always consume the response's entity, if available. response.getEntity().write(System.out); } catch (IOException e) { e.printStackTrace(); } } return response.getEntity().getIdentifier(); } return null; } /** * Prints the resource's representation. * * @param client * client Restlet. * @param reference * the resource's URI * @throws IOException */ public static void get(Client client, Reference reference) throws IOException { Response response = client.get(reference); if (response.getStatus().isSuccess()) { if (response.isEntityAvailable()) { response.getEntity().write(System.out); } } } /** * Try to update an item. * * @param item * the item. * @param client * the Restlet HTTP client. * @param itemUri * the resource's URI. */ public static boolean updateItem(Item item, Client client, Reference itemUri) { // Gathering informations into a Web form. Form form = new Form(); form.add("name", item.getName()); form.add("description", item.getDescription()); Representation rep = form.getWebRepresentation(); // Launch the request Response response = client.put(itemUri, rep); if (response.isEntityAvailable()) { try { // Always consume the response's entity, if available. response.getEntity().write(System.out); } catch (IOException e) { e.printStackTrace(); } } return response.getStatus().isSuccess(); } /** * Try to delete an item. * * @param client * the Restlet HTTP client. * @param itemUri * the resource's URI. */ public static boolean deleteItem(Client client, Reference itemUri) { // Launch the request Response response = client.delete(itemUri); if (response.isEntityAvailable()) { try { // Always consume the response's entity, if available. response.getEntity().write(System.out); } catch (IOException e) { e.printStackTrace(); } } return response.getStatus().isSuccess(); } }
你可以从http://www.restlet.org/documentation/1.0/examples/firstResource/sources.zip下载这个例子应用的源文件。
结尾
这篇文章说明了使用Restlet框架的重要方法。当思考你的Resource的时候,记住这些重要问题:
我应该如何识别我的Resource?
它们能够生成哪些表现?
它们有哪些处理方法?
我需要把同级Resource的哪些行为和属性共享?
我们希望你喜欢这些简单步骤并且我们现在鼓励你开始深入Restlet Tutorial。
备注:
感谢Tim Peierls反馈线程安全方面的考虑。
评论
6 楼
heroqt
2011-07-22
Representation entity 这是个什么对象,比如我要post一个JSON对象给服务器端,怎么传?
5 楼
liyf155
2010-03-10
liyf155 写道
魔力猫咪 写道
我翻译得不好吗?怎么有人踩我?
猫咪,你有没有测试过这篇文章的代码,BaseResource似乎有个错误,就在Application.KEY那里。
protected Map<String, Item> getItems() {
return ((FirstResourceApplication) getApplication()).getItems();
}
这个方法应该是这样的,
4 楼
liyf155
2010-03-10
魔力猫咪 写道
我翻译得不好吗?怎么有人踩我?
猫咪,你有没有测试过这篇文章的代码,BaseResource似乎有个错误,就在Application.KEY那里。
3 楼
Blackbaby
2008-04-25
正想了解下~~~不错啊~~他可能点错了~~呵呵~~
2 楼
teamlet
2008-04-23
写得挺好,继续!
GET ...
POST ...
PUT ...
DELETE ...
需要修改一下。
GET ...
POST ...
PUT ...
DELETE ...
需要修改一下。
1 楼
魔力猫咪
2008-04-20
我翻译得不好吗?怎么有人踩我?
相关推荐
本文是对Restlet官方教程http://restlet.com/learn/tutorial/2.2/的中文翻译。
restlet处理各种请求方式参考示例
Restlet1.0_中文起步_翻译自官网Restlet1.0_中文起步_翻译自官网Restlet1.0_中文起步_翻译自官网
restlet相关文档
用户在安装了Restlet Client之后,直接点击插件图标即可开始使用,只需输入自己的网站并选择好对应的请求模式就能对网站发送Web请求并检查响应,同时使用者可以先将多个API请求组合成一个方案来创建一个针对网站的...
一个简单的Restlet开发框架的Basic认证的例子
restlet项目
org.restlet.jar
Restlet与Spring 集成
restlet2.1学习笔记项目代码
Restlet项目为“建立REST概念与Java类之间的映射”提供了一个轻量级而全面的框架。它可用于实现任何种类的REST式系统,而不仅仅是REST式Web服务;而且,事实证明它自从2005年诞生之时起,就是一个可靠的软件。 ...
Restlet所需要的所有jar包 一次下载,以后高枕无忧!
RESTLET开发实例(二)使用Component、Application的REST服务
restlet是一个支持rest架构的JAVA编写的开源轻量级框架,比较简单易学,不错的框架。
Restlet 实现ServerResource类 列子有: 返回简单JSON类型 获取请求头,返回请求头 接收简单Json类型数据 将复杂对象使用Json格式返回
restlet入门helloworld示例
RESTLET框架学习书籍
Restlet Client 插件是一个类似Postman的Api接口测试工具, 界面友好, UI布局也更合理。相比Postman, Restlet Client无需安装本地客户端, 即装即用, 占用空间小, 功能强大。
Restlet2.0用户指南