`
魔力猫咪
  • 浏览: 107074 次
  • 来自: 北京
社区版块
存档分类
最新评论

Restlet第一个Resource(翻译)

    博客分类:
  • REST
阅读更多
猫咪继续翻译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对象的实例。
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反馈线程安全方面的考虑。
12
4
分享到:
评论
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  ...

需要修改一下。
1 楼 魔力猫咪 2008-04-20  
我翻译得不好吗?怎么有人踩我?

相关推荐

    restlet2.1学习笔记项目代码

    Restlet是一个开源框架,专为构建RESTful(Representational State Transfer)Web服务而设计。REST是一种轻量级的架构风格,常用于构建可扩展、高性能的互联网应用程序。本项目是针对Restlet 2.1版本的学习笔记,...

    Restlet1.0_中文起步_翻译自官网

    Restlet 1.0 是一个轻量级的Java框架,专为构建RESTful(Representational State Transfer)Web服务而设计。REST是一种软件架构风格,它强调通过统一接口和无状态交互来实现网络应用程序的简洁性和可扩展性。Restlet...

    restlet项目

    1. **初始化Restlet Engine**: 创建一个Restlet引擎,这是启动Restlet应用的基础。 2. **创建服务器端点(ServerResource)**: 定义一个Restlet类,继承自`org.restlet.resource.ServerResource`,处理HTTP请求。 ...

    restlet实现最简单的restful webservice

    2. **创建资源类**:在Java中创建一个新的类,该类继承自Restlet或更具体的子类,如ServerResource。在这个类中,你可以覆盖handle方法或者重写onGet、onPost等HTTP方法来处理不同的HTTP请求。 ```java import ...

    Restlet开发的Basic认证

    Restlet是一个轻量级的Java Web服务开发框架,它提供了构建RESTful(Representational State Transfer)应用程序的工具和API。REST是一种架构风格,强调简洁、无状态和可缓存的网络交互,常用于构建高性能、高可用性...

    restlet

    在服务器端,RESTlet充当了一个应用服务器,支持多种Java应用服务器,如Jetty、Tomcat等。它提供了一种模块化的方式来组织和处理HTTP请求,允许开发者定义自定义的资源类来响应特定的URI路径。 客户端部分,RESTlet...

    RESTLET开发

    实现一个具体的资源类`StudentResource`,该类需要继承自`javax.ws.rs.core.Resource`,并在其中定义RESTful方法(如`GET`、`POST`等)来处理客户端请求。 #### 四、总结 通过上述步骤,我们可以构建出一个基本的...

    restlet-jse-2.2.1.zip

    总之,Restlet JSE 2.2.1是一个强大的工具,能够帮助开发者高效地构建符合REST原则的Web服务,同时提供丰富的功能和高度的灵活性。通过深入学习和实践,开发者可以充分利用Restlet来提升其在分布式系统和Web应用开发...

    restlet-j2ee-2.0.15.rar

    例如,创建一个新的服务器资源类,继承自`org.restlet.resource.ServerResource`,并在其中覆盖`handle()`方法来定义处理逻辑。 总的来说,Restlet为Java开发者提供了一个高效且灵活的工具,简化了RESTful Web服务...

    Restlet2 + Spring3 注解方式配置

    Restlet是一个轻量级的Java RESTful Web服务开发库,而Spring则是一个广泛使用的全面的企业级应用框架。结合两者,我们可以创建高效、灵活的Web服务。 首先,确保你已经下载了正确的依赖。在这个配置中,Restlet的...

    restlet入门示例

    Restlet是一个开源框架,专为构建RESTful(Representational State Transfer)Web服务而设计。REST是一种轻量级的架构风格,常用于构建Web应用程序和API,强调简洁、可扩展性和可伸缩性。本示例将带你入门Restlet,...

    Restlet所需要的所有jar包

    Restlet是一款开源的Java框架,专门用于构建RESTful(Representational State Transfer)Web服务。REST是一种轻量级的架构风格,常用于构建高效、可扩展的网络应用程序。本压缩包包含Restlet框架运行所需的全部jar...

    restlet处理各种请求方式参考示例

    Restlet是一款轻量级的Java库,专门用于构建RESTful Web...总之,Restlet是一个强大的工具,可以帮助开发者快速、灵活地构建符合REST原则的Web服务。理解和掌握其处理各种请求的方式,将有助于你构建高效、健壮的API。

    RESTLET开发(三)

    接下来,我们需要创建一个`restlet-servlet.xml`文件,该文件用于配置Spring容器中的REST资源映射。 ```xml &lt;lookup-method name="create" bean="StudentResource"/&gt; ...

    基于Spring的Restlet实例

    而Restlet是一个专注于REST(Representational State Transfer)架构风格的Java库,它允许开发人员轻松地创建RESTful Web服务和客户端。将Spring与Restlet结合,可以利用Spring的强大功能来构建高效、可扩展的REST...

    Restlet与Spring 集成

    Restlet是一个轻量级的Java框架,专门用于构建REST(Representational State Transfer)架构风格的应用程序。它遵循JAX-RS(Java API for RESTful Web Services)规范,提供了丰富的API来处理HTTP请求和响应,简化了...

    restlet工程示例

    Restlet是一个开源框架,专门用于构建RESTful(Representational State Transfer)Web服务。REST是一种轻量级的架构风格,常用于构建互联网应用,强调资源的识别、无状态和统一的接口。在本示例中,我们将深入探讨...

    RESTLET框架学习书籍

    - **第一章:反思Web开发**: - 学习REST架构的基本原理。 - 了解RESTLET框架的历史背景和发展现状。 - 实践编写简单的“Hello, World”示例,包括客户端和服务端。 - **第二章:设计RESTful Web API**: - 掌握...

Global site tag (gtag.js) - Google Analytics