精华内容
下载资源
问答
  • restlet

    2011-11-01 21:37:24
    restlet相关文档
  • Restlet

    2014-04-07 21:43:28
    RestLet与Rest理论与实践相结合(转载)     Restlet是一个Java下的轻量级REST框架。通过拥抱REST(REST是一种Web架构风格)它模糊了Web站点和Web服务之间的界限,从而帮助开发人员构建Web应用。每一个主要的...

     

     

    Restlet是一个Java下的轻量级REST框架。通过拥抱RESTREST是一种Web架构风格)它模糊了Web站点和Web服务之间的界限,从而帮助开发人员构建Web应用。每一个主要的REST概念(REST concept)都有一个对应的Java类。你的REST化的Web设计和你的代码之间的映射是非常简单直接的。

    为什么有必要创建另一种框架?难道Servlet API还不够好用吗?

    Servlet AIP1998年发布,从那个时候起它的核心设计一直没有很大的变化。它是Java EE的众多API中最成功的一个,但是它的几个设计缺陷和一些限制损害了它。举个例子,URI模式和它的处理者(handler)之间的映射是受限制的,而且其配置都集中在一个配置文件中。还有,它把socket流的控制直接交给了应用系统开发人员,Servlet容器阻碍了我们充分使用NIO特性对IO操作进行优化。另一个主要问题就是Servlet API鼓励应用开发者在应用或者用户会话级别直接将session状态保存于内存中,尽管这看上去不错,但它造成了Servlet容器扩展性和高可用性的主要问题。为了克服这些问题,就必须实现复杂的负载均衡session复制、持久化机制。这导致了可扩展性必然成为灾难。

    如何看待别的框架中对REST的支持(例如Axis2,或者CXF/XFire)?

    这些支持非常有效,但是作用非常有限。我的主要观点是设计这些项目是为了符合WS-*/SOAP Stack,它们与REST世界并不非常契合。在REST世界里,定义了一个全新的范例:面向资源的设计,而非通过远程方法调用这样的范例。例如Axis2仅仅支持GETPOST两种HTTP方法,它需要远程方法的传递需要一个URI参数。这在REST中式不允许的,这种做法也不能被称之为REST化。XFire1.2不支持REST,但是它发布了一个项目用于将POJO映射到REST化的Web服务。这有点类似最近发布的JSR-311,此JSR试图基于一套annotation和助手类标准化这种映射。

    REST与HTTP协议

    REST软件架构是由Roy Thomas Fielding博士在2000年首次提出的。他为我们描绘了开发基于互联网网络软件的蓝图。REST软件架构是一个抽象的概念,是一种为了实现这一互联网的超媒体分布式系统的行动指南。利用任何的技术都可以实现这种理念。而实现这一软件架构最著名的就是HTTP协议。通常我们把REST也写作为REST/HTTP,在实际中往往把REST理解为基于HTTP的REST软件架构,或者更进一步把REST和HTTP看作为等同的概念。今 天,HTTP是互联网上应用最广泛的计算机协议。HTTP不是一个简单的运载数据的协议,而是一个具有丰富内涵的网络软件的协议。它不仅仅能够对于互联网 资源进行唯一定位,而且还能告诉我们对于该资源进行怎样运作。这也是REST软件架构当中最重要的两个理念。而REST软件架构理念是真正理解HTTP协 议而形成的。有了REST软件架构理念出现,才使得软件业避免了对HTTP协议的片面理解。只有正确的理论指导,才能避免在软件开发的实际工作过程中少走 弯路。

    REST与URI(资源定位)
    REST软件架构之所以是一个超媒体系统,是因为它可以把网络上所有资源进行唯一的定位,不管你的文件是图片、文件Word还是
    视频文件,也不管你的文件是txt文件格式、xml文件格式还是其它文本文件格式。它利用支持HTTP的TCP/IP协议来确定互联网上的资源。

    REST与CRUD原则
    REST软件架构遵循了CRUD原则,该原则告诉我们对于资源(包括网络资源)只需要四种行为:创建(Create)、获取(Read)、更新 (Update)和销毁(DELETE)就可以完成对其操作和处理了。其实世界万物都是遵循这一规律:生、变、见、灭。所以计算机世界也不例外。这个原则 是源自于我们对于数据库表的数据操作:insert(生)、select(见)、update(变)和delete(灭),所以有时候CRUD也写作为 RUDI,其中的I就是insert。这四个操作是一种原子操作,即一种无法再分的操作,通过它们可以构造复杂的操作过程,正如数学上四则运算是数字的最 基本的运算一样。
     
    REST与网络服务
    尽管在Java语言世界中网络服务目前是以SOAP技术为主,但是REST将是是网络服务的另一选择,并且是真正意义上的网络服务。基于REST思想的网 络服务不久的将来也会成为是网络服务的主流技术。REST不仅仅把HTTP作为自己的数据运输协议,而且也作为直接进行数据处理的工具。而当前的网络服务 技术都需要使用其它手段来完成数据处理工作,它们完全独立于HTTP协议来进行的,这样增加了大量的复杂软件架构设计工作。REST的思想充分利用了现有 的HTTP技术的网络能力。在德国电视台上曾经出现过一个这样的五十万欧元智力题:如何实现网络服务才能充分利用现有的HTTP协议?该问题给出了四个答 案:去问微软;WSDL2.0/SOAP1.2;WS-Transfer;根本没有。这个问题告诉我们HTTP并不是一个简单的数据传来传去的协议,而是 一个聪明的会表现自己的协议,这也许是REST = Representational State Transfer的真正含义。实际上目前很多大公司已经采用了REST技术作为网络服务,如Google、Amazon等。在Java语言中重要的两个以SOAP技术开始的网络服务框架XFire和Axis也把REST作为自己的另一种选择。它们的新的项目分别是
    Apache CXF
    Axis2。Java语言也制定关于REST网络服务规范:JAX-RS: Java API for RESTful Web Services (JSR 311)。相信还会出现更多与REST相关的激动人心的信息。

    REST与AJAX技术
    尽管AJAX技术的出现才不到两年时间,但是AJAX技术遵循了REST的一些重要原则。AJAX技术充分利用了HTTP来获取网络资源并且实现了 HTTP没有的对于异步数据进行传输的功能。AJAX技术还使得软件更好地实现分布性功能,在一个企业内只要一个人下载了AJAX引擎,其它企业内部的人 员,就可以共享该资源了。AJAX技术遵守REST准则的应用程序中简单和可伸缩的架构,凡是采用AJAX技术的页面简洁而又丰富,一个页面表现了丰富多 彩的形态。AJAX技 术还使用了一种不同于XML格式的JSON文件格式,这个意义在哪里呢?在REST软件架构下我们不能对于XML文件进行序列化处理,这样程序员必须要使 用自己的XML绑定框架。而以序列化的JavaScript对象为基础的JSON已经获得了广泛认可,它被认为能以远比XML更好的方式来序列化和传输简 单数据结构,而且它更简洁。这对REST是一个极大贡献和补充。当前的网络应用软件还违背了REST的“无状态
    服务器”约束。REST服务器只知道自己的状态。REST不关心客户端的状态,客户端的状态自己来管理,这是AJAX技术的应用之地。通过AJAX技术,可以发挥有状态网络客户机的优势。而REST的服务器关心的是从所有网络客户端发送到服务器操作的顺序。这样使得互联网这样一个巨大的网络得到有序的管理。

    REST与Rails框架
    Ruby on Rails框架(简称Rails或者Rails框架)是一个基于Ruby语言的越来越流行的网络应用软件开发框架。它提供了关于REST最好的支持,也是 当今应用REST最成功的一个软件开发框架。Rails框架(从版本1.2.x起)成为了第一个引入REST作为核心思想的主流网络软件开发框架。在 Rails框架的充分利用了REST软件架构之后,人们更加坚信REST的重要性和必要性。Rails利用REST软件架构思想对网络服务也提供了一流的 支持。从最直观的角度看待REST,它是网络服务最理想的手段,但是Rails框架把REST带到了网络应用软件开发框架。这是一次飞跃,让REST的思 想从网络服务的应用提升到了网络应用软件开发。利用REST思想的simply_restful插件已经成为了Rails框架的核心内容。

    REST
    安全
    我们把现有基于SOAP的网络服务和基于REST/HTTP网络服务作个比喻,前者是一种传统的寄信方式,而后者是现代网络的电子邮件方式。要是是寄信和 电子邮件都有病毒存在的话,传统的寄信被送到对方就很危险,而电子邮件是开发的,电子邮件供应商比如Google为我们检查了电子邮件是否有病毒。这里并 不是说明SOAP网络服务消息包含义病毒,而是说明HTTP是无法处理SOAP信息包究竟好不好,需要额外的软件工具
    解决这一问题,包括防火墙也用不上和管不了。

    REST/HTTP网 络服务的信息包可以被防火墙理解和控制。你可以按照操作和链接进行过滤信息包,如你可以规定从外部来的只能读取(GET操作)自己服务器的资源。这样对于 系统管理员而言使得软件管理更为简单。REST的安全性还可以利用传输安全协议SSL/TLS、基本和摘要式认证(Basic und Digest Authentication)。除了这些REST自身的安全性功能外,还可以利用像基于信息的Web Services Security(JSR 155)作为REST不错的补充。

    Restlet第一步:

    这篇文章让你在10分钟内尝试简单的Restlet框架。告诉你如何创建一个说“hello, world”的Resource。
    1.我需要什么?
    2.“hello, world”应用
    3.在Servlet容器中运行
    4.作为一个单独的Java应用运行
    5.结尾

    1.我需要什么?
    我们假设你已经有了一个可以马上使用的开发环境,并且你已经安装了JRE1.5(或更高)。如果你还没有下载Restlet,请选择最新的
    Restlet Framework 1.0发行版。

    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 }

    然后创建应用例子。我们创建名为“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应用。像往常一样创建一个新的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)。
    创建一个主类,拷贝/粘贴下面的代码。建立一个新的HTTP服务器监听端口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.实现Items Resource
    4.实现Item Resource
    5.实现Base Resource
    6.运行应用
    7.客户端应用
    8.总结

    1.      引言
    在开始开发前,我们需要简单介绍一下Restlet框架的Resource概念。REST告诉我们,Resource根据URI进行辨认,同时能够有一种或多种表现(也被称作变量),用以响应方法调用。
    在Restlet框架中,服务器连接器(server connectors)收到的调用最终由Resource的实例对象处理。一个Resource负责声明支持的表现方式列表(Variant对象的实例)和实现你想要支持的REST方法。
     GET依赖可更改的“variants”列表和“getRepresentation(Variant)”方法。
     POST依赖“allowPost”方法和“post(Representation)”方法。
     DELETE依赖“allowPut”方法和“put(Representation)”方法。
    DELETE依赖“allowDelete”方法和“delete()”方法。
    还有,每一个到达的响应由一个专门的Resource实例处理,你不需要操心这些方法的线程安全问题。
    我们假设你已经读过“第一步”,并且有了一些元件和应用的概念。

    2.示例程序

    一个Item列表用来管理创建,读取,更新,和删除活动,如一个典型的CRUD应用。一个Item包含名字和描述。在简短的分析后,我们定义了两个资源:
     Items Resource代表所有可用Item的集合。
     Item Resource代表一个单独的item。
    现在,让我们定义用来标志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对象的实例。

    代码:

    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.      实现Items Resource
      让我们开始编写Items Resource。如上文所述,它允许GET和POST请求。POST请求支持实现“post(Representation)”方法赋予处理消息实体的 权限。此外,资源通过“allowPost”方法来确定是否开启POST支持。缺省情况下,资源是不可更改的,拒绝POST、PUT和DELETE方法并 返回“Method not allowed”状态(HTTP 405状态代码)。

    同样,通过实现“represent(Variant)”方法确定你可以接受GET请求并根据指定的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<b


    转载地址:http://blog.ixpub.net/html/07/12399407-251280.html
    展开全文
  • Restlet

    千次阅读 2014-04-23 00:55:09
    过滤器是一种特殊的Restlet,它能够在调用相应Restlet之前进行预处理,或者在相应 Restlet调用返回后进行后期处理。如果你熟知Servlet API,这里的过滤器概念和Servlet API中的Filter接口非常接近。看一下我们如何...

    转载自http://my.oschina.net/javagg/blog/3254



    关于本指南

    本指南的翻译工作经过了Restlet社区的官方授权,cleverpig作为贡献者完成了本文的翻译和整理工作。在此发布Matrix社区试读版的目的是为了让更多的技术爱好者阅读并提出翻译中的不足之处,以提高本指南的质量,以期修改后正式发布。

    Servlet的限制

    在2003年末,Jetty Web容器的作者、Servlet规范的贡献者:Greg Wilkins在其博客上对Servlet的问题进行了如下总计:

        * 没有对协议与应用之间的关系进行清洗的划分。
        * 由于在设计Servlet时存在对阻塞IO的假设,因此不能充分利用非阻塞NIO机制。
        * 所有的Servlet Web容器对于某些应用来讲是过度设计的。

    他提出构思新的API规范,使其能够真实地脱离协议,并定义能够暴露内容和元数据的contentlets。这些想法就是Restlet项目创建的灵感源泉。在之后的文章中,Greg Wilkins解释了为什么当前Servlet API限制非阻塞NIO API得到高效使用的详细理由:这种传统的用法针对每个HTTP请求都创建独立的线程进行处理。并提出了他对下一代Servlet技术的设想

    另一个主要问题就是Servlet API鼓励应用开发者在应用或者用户会话级别直接将session状态保存于内存中,尽管这看上去不错,但它造成了Servlet容器扩展性和高可用性的主要问题。为了克服这些问题,就必须实现复杂的负载均衡、session复制、持久化机制。这导致了可扩展性必然成为灾难。

    Restlet简介

    当复杂核心化模式日趋强大之时,面向对象设计范例已经不总是Web开发中的最佳选择,Java开发者需要认识到这一点,并且在开发新的Web服务端或是AJAX Web客户端时开始思考更加RESTfully的设计。Restlet这个开源项目为那些要采用REST结构体系来构建应用程序的Java开发者提供了一个具体的解决方案。它的非常简单易用的功能和RESTfully的Web框架,这使其成为了Web2.0开发中的又一利器。好吧,朋友们,下面就让我们开始Restlet探索之旅吧!

    1. 注册一个Restlet实现

    Restlet框架由两部分构成。第一部分是"Restlet API", 这个中立的API完美地实现了REST概念并简化了客户端和服务端应用的调用处理。在使用它之前,我们还需要一个支持此API的Restlet实现。Restlet的诸多实现可以通过开源项目或者商业产品获得。


    API与实现的分离和Servlet API与web容器的分离(就像Jetty或Tomcat)、JDBC API与相应JDBC驱动的分离非常类似。目前,"Noelios Restlet Engine" (缩写为NRE)是Restle tAPI的参考实现之一。当下载Restlet发布版本时,API和NRE就绑定在一起,以备随时使用。如果你需要使用不同的实现,那么只需要添加JAR 文件到classpath,并删除com.noelios.restlet.jar这个NRE的JAR文件即可。

    API实现的注册过程是完全自动的,如果你对此存在疑问,那么请参考JAR规范。当完成实现装载工作后,它将自动回调org.restlet.util.Engine.setInstance()方法,来进行自注册。

    2. 接收Web页面的内容

    正如我们在Restlet介绍中所提到的,Restlet框架即是一个客户端,又是一个服务端框架。例如,NRE能够简单地通过它的HTTP客户端 connector(连接器)访问远程资源。在REST中,connector是一种软件元素,它使两个component(组件)之间能够进行通讯,其典型的实现方式是通过某种网络协议完成通讯。NRE提供了多种客户端connector实现,这些实现都基于现存的开源项目。在connector一节中,列举出了所有可用的客户端、服务端connector,并解释了如何使用和配置它们。

    下面,我们将获取一个现存资源的表示法(representation )并将其输出在JVM控制台:

    // Outputting the content of a Web page
    Client client = new Client(Protocol.HTTP);
    client.get("http://www.restlet.org").getEntity().write(System.out);



    请注意上面的示例使用了最简单的方式:通过通用的客户端类(generic Client class)调用。更加灵活的方式是创建一个新的Request对象,然后请求客户端去处理它。下面的示例展示了如何在调用时设置首选项(例如 referrer URI)。当然,也可以是接收回应时的首选语言或者媒体类型:

    // Prepare the request
    Request request = new Request(Method.GET, "http://www.restlet.org");
    request.setReferrerRef("http://www.mysite.org");

    // Handle it using an HTTP client connector
    Client client = new Client(Protocol.HTTP);
    Response response = client.handle(request);

    // Write the response entity on the console
    Representation output = response.getEntity();
    output.write(System.out);



    3. 侦听浏览器

    现在,我们将了解一下Restlet框架是如何侦听客户端请求并作出回应的。这里,我们选用了NRE HTTP服务端connector(例如基于Jetty的HTTP服务端connector),返回简单的字符串表达式“Hello World!”。请注意在更加实际的应用中,我们可以创建一个独立的类,此类继承自Restlet类,而不依靠这里的匿名内部类。

    Restlet类与Servlet非常相似,并且在RESTful应用中处理调用时提供了有限的帮助。我们后面将看到一个提供了一些特定子类的框架,它能够更抽象、简单地进行处理。下面让我们先看一个简单的示例:

    // Creating a minimal Restlet returning "Hello World"
    Restlet restlet = new Restlet() {
        @Override
        public void handle(Request request, Response response) {
            response.setEntity("Hello World!", MediaType.TEXT_PLAIN);
        }
    };

    // Create the HTTP server and listen on port 8182
    new Server(Protocol.HTTP, 8182, restlet).start();



    如果你运行并启动服务端,那么你可以打开浏览器输入http://localhost:8182。实际上,输入任何的URI都可以工作,你也可以尝试一下http://localhost:8182/test/tutorial。值得注意的是,如果你从另一台服务器上测试服务端,那么就需要将localhost替换为服务器的IP地址或者它的域名。

    4. REST架构概述

    让我们先从REST的视角审视一下典型的web架构。在下面的图表中,端口代表了connector,而后者负责component之间的通讯(组件在图中被表示为大盒子)。链接代表了用于实际通讯的特定协议(HTTP,SMTP等)。
    image

    请注意,同一个component能够具有任何数量的客户端/服务端connector。例如,Web服务器B就具有一个用于回应用户代理组件(User Agent component)的服务端connector,和多个发送请求到其它服务端的客户端connector。

    5. Component、virtual hosts和applications

    另外,为了支持前面所表述的标准REST软件架构元素,Restlet框架也提供了一套类:它们极大地简化了在单一JVM中部署多个应用的工作。其目的在于提供一种RESTful、可移植的、比现存的Servlet API更加灵活的框架。在下面的图表中,我们将看到三种Restlet,它们用于管理上述复杂情况:Components能够管理多个Virtual Hosts和Applications。Virtual Hosts支持灵活的配置,例如同一个IP地址能够分享多个域名、使用同一个域名实现跨越多个IP地址的负载均衡。最后,我们使用应用去管理一套相关的 Restlet、Resource、Representations。另外,应用确保了在不同Restlet实现、不同Virtual Hosts之上的可移植性和可配置性。这三种Restlet的协助为我们提供了众多的功能:譬如访问日志、请求自动解码、配置状态页设置等。image

    为了展示这些类,让我们尝试一个简单的示例。首先,我们创建一个component,然后在其上添加一个HTTP服务端connector,并侦听 8182端口。接着创建一个简单的、具有追踪功能的Restlet,将它放置到组件默认的Virtual Hosts上。这个默认的主机将捕捉那些没有路由到指定Virtual Hosts的请求(详见Component.hosts属性)。在后面的一个示例中,我们还将介绍应用类的使用方法。请注意,目前你并不能在控制台输出中看到任何的访问日志。

    // Create a new Restlet component and add a HTTP server connector to it
    Component component = new Component();
    component.getServers().add(Protocol.HTTP, 8182);

    // Create a new tracing Restlet
    Restlet restlet = new Restlet() {
        @Override
        public void handle(Request request, Response response) {
            // Print the requested URI path
            String message = "Resource URI  : " + request.getResourceRef()
                    + ' ' + "Root URI      : " + request.getRootRef()
                    + ' ' + "Routed part   : "
                    + request.getResourceRef().getBaseRef() + ' '
                    + "Remaining part: "
                    + request.getResourceRef().getRemainingPart();
            response.setEntity(message, MediaType.TEXT_PLAIN);
        }
    };

    // Then attach it to the local host
    component.getDefaultHost().attach("/trace", restlet);

    // Now, let's start the component!
    // Note that the HTTP server connector is also automatically started.
    component.start();


    让我们通过在浏览器中输入http://localhost:8182/trace/abc/def?param=123来进行测试,得到测试结果如下:

    Resource URI  : http://localhost:8182/trace/abc/def?param=123
    Root URI      : http://localhost:8182/trace
    Routed part   : http://localhost:8182/trace
    Remaining part: /abc/def?param=123



    6. 为静态文件提供服务

    你遇到过提供静态页面(类似Javadocs)服务的web应用?如果正在使用,那么可以直接编写一个Directory类,而无需为它建立Apache服务。请见下面如何使用:

    // Create a component
    Component component = new Component();
    component.getServers().add(Protocol.HTTP, 8182);
    component.getClients().add(Protocol.FILE);

    // Create an application
    Application application = new Application(component.getContext()) {
        @Override
        public Restlet createRoot() {
            return new Directory(getContext(), ROOT_URI);
        }
    };

    // Attach the application to the component and start it
    component.getDefaultHost().attach("", application);
    component.start();


    正如你所注意到的,我们通过传递应用的父组件上下文(context)的方式来实例化应用,而不是在第5章中提到的代码那样简单。而其主要原因是应用在分配客户端请求时,请求的分配工作需要客户端connector来完成,而后者被component所控制,并在所有被包含其中的应用之间贡献。

    为了运行此示例,你需要为ROOT_URI提供一个有效值,该值依赖于你的Restlet安装路径。默认情况下,它被设置为"file:///D: /Restlet/www/docs/api/"。请注意,这里不需要任何附加的配置。如果你希望自定义在文件扩展名和元数据(metadata,包括媒体类型、语言、编码等)之间的映射,或是提供一个与众不同的索引名,你可以使用应用的“metadataService”属性。

    7. 访问日志

    有目的地记录web应用的活动是一种常见的需求。Restlet组件能够在默认的情况下生成类似Apache风格的日志、甚至自定义日志。通过使用 JDK内置的日志功能,logger能够配置为像任何标准JDK日志那样过滤信息、对它们进行重新格式化或者发送它们到指定位置。并且支持日志的循环(rotation);细节请查看java.util.logging包。

    值得注意的是,你能够通过修改component的"logService"属性来为java.util.logging框架自定义logger名。如果希望完全掌控日志的配置,你需要通过设置系统属性来声明一个配置文件:

    System.setProperty("java.util.logging.config.file", "/your/path/logging.config");



    关于配置文件格式的细节,请查看JDK的LogManager类。

    8. 显示错误页

    另外一个常见的需求是:在调用处理过程中某些期望结果没有出现时,能够自定义返回的状态页面。也许它是某个资源没有找到或者一个可接受的表示是无效的。在这种情况下,或者遇到任何无法处理的异常时,Application或者Component将自动提供一个默认的状态页面。此服务与 org.restlet.util.StatusService类相关联,并可以作为被称为“statusService”的Application或者 Component的属性而被访问。

    为了自定义默认的信息,你只需要简单地创建StatusService类的子类,并覆盖其getRepresentation(Status, Request, Response)方法。然后设置这个类的实例为指定的“statusService”属性即可。

    9. 对敏感资源的访问保护

    当你需要保护对某些Restlet的访问时,可以使用下面的方法:一种通用的方法是依靠cookie来识别客户端(或者客户端session),并根据你的应用状态检查给定的用户ID或者session ID,从而判断次访问是否被允许。Restlet通过访问Request或者Response中的CookieCookieSetting对象支持cookie。

    另一种方法是基于标准HTTP认证机制。Neolios Restlet引擎目前允许基于简单HTTP方案的证书发送、接收和基于Amazon Web服务方案的证书发送。

    当接收到调用时,开发者能够通过Request.challengeResponse.identifier/secret类中的Guard filter(保护过滤器)使用已经解析好的证书。过滤器是一种特殊的Restlet,它能够在调用相应Restlet之前进行预处理,或者在相应 Restlet调用返回后进行后期处理。如果你熟知Servlet API,这里的过滤器概念和Servlet API中的Filter接口非常接近。看一下我们如何修改从前的代码来对目录访问进行访问保护:

    // Create a Guard
    Guard guard = new Guard(getContext(),
            ChallengeScheme.HTTP_BASIC, "Tutorial");
    guard.getSecrets().put("scott", "tiger".toCharArray());

    // Create a Directory able to return a deep hierarchy of files
    Directory directory = new Directory(getContext(), ROOT_URI);
    guard.setNext(directory);
    return guard;


    image

    请注意:认证和授权的最终结果是完全可定制的,这只需要通过authenticate()和authorize()方法便可完成。任何自定义的机制都能够被用来检查给定的证书是否有效、通过认证的用户是否被授权继续访问相应Restlet。下面是我们简单地硬编码了用户、密码对。为了测试,我们使用了客户端Restlet API:

    // Prepare the request
    Request request = new Request(Method.GET, "http://localhost:8182/");

    // Add the client authentication to the call
    ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
    ChallengeResponse authentication = new ChallengeResponse(scheme,
            "scott", "tiger");
    request.setChallengeResponse(authentication);

    // Ask to the HTTP client connector to handle the call
    Client client = new Client(Protocol.HTTP);
    Response response = client.handle(request);

    if (response.getStatus().isSuccess()) {
        // Output the response entity on the JVM console
        response.getEntity().write(System.out);
    } else if (response.getStatus()
            .equals(Status.CLIENT_ERROR_UNAUTHORIZED)) {
        // Unauthorized access
        System.out
                .println("Access authorized by the server, " +
                        "check your credentials");
    } else {
        // Unexpected status
        System.out.println("An unexpected status was returned: "
                + response.getStatus());
    }


    你可以修改这里的user ID或者password,来检查服务端返回的response。请别忘记了在启动客户端之前,先执行Restlet服务端程序。请注意,如果你从另一台机器上测试服务端,那么在浏览器中输入URI时需要将"localhost"替换为服务器的IP地址或者域名。由于使用了默认接收任何类型URI的 VirtualHost,因此服务端无需任何修改。

    10. URI重写和重定向

    Restlet框架的另一个优点是对cool URI的内建支持。Jacob Nielsen在他的AlertBox中给出了对URI设计的重要性的绝佳描述

    首先介绍的工具是Redirector,它能够将cool URI重写为另一个URI,并接着进行相应的自动重定向。这里支持一些重定向类型:通过客户端/浏览器的外部重定向、类似代理行为的connector重定向。在下面的例子中,我们将基于Google为名为"mysite.org"的站点定义一个检索服务。与URI相关的"/search"就是检索服务,它通过"kwd"参数接收一些检索关键字:

    // Create an application
    Application application = new Application(component.getContext()) {
        @Override
        public Restlet createRoot() {
            // Create a Redirector to Google search service
            String target =
               "http://www.google.com/search?q=site:mysite.org+{keywords}";
            return new Redirector(getContext(), target,
                    Redirector.MODE_CLIENT_TEMPORARY);
        }
    };

    // Attach the application to the component's default host
    Route route = component.getDefaultHost().attach("/search", application);

    // While routing requests to the application, extract a query parameter
    // For instance :
    // http://localhost:8182/search?kwd=myKeyword1+myKeyword2
    // will be routed to
    // http://www.google.com/search?q=site:mysite.org+myKeyword1%20myKeyword2
    route.extractQuery("keywords", "kwd", true);


    请注意,Redirector只需要三个参数。第一个参数是父级上下文,第二个参数定义了如何基于URI模板重写URI。这里的URI模板将被Template类处理。第三个参数定义了重定向类型:出于简化的目的,我们选择了客户端重定向。

    同时,当调用被传递给application时,我们使用了Route类从request中提取查询参数“kwd”。如果发现参数,参数将被复制到request的“keywords”属性中,以便Redirector在格式化目标URI时使用。

    11. 路由器和分层URI

    作为Redirector的补充,我们还具有另一个管理cool URI的工具:Router(路由器)。它们是一种特殊的Restlet,能够使其它Restlet(例如Finder和Filter)依附于它们,并基于URI模板进行自动委派调用(delegate call)。通常,你可以将Router设置为Application的根。

    这里,我们将解释一下如何处理下面的URI模板:

       1. /docs/ 用于显示静态文件
       2. /users/{user} 用于显示用户帐号
       3. /users/{user}/orders 用于显示特定用户的所有订单
       4. /users/{user}/orders/{order} 用于显示特定的订单

    实际上,这些URI包含了可变的部分(在大括号中)并且没有文件扩展名,这在传统的web容器中很难处理。而现在,你只需要做的只是使用URI模板将目标Restlet附着到Router上。在Restlet框架运行时,与request的URI最为匹配的Route将接收调用,并调用它所附着的 Restlet。同时,request的属性表也将自动更新为URI模板变量。
    image

    请看下面的具体实现代码。在真实的应用中,你可能希望创建单独的子类来代替我们这里使用的匿名类:

    // Create a component
    Component component = new Component();
    component.getServers().add(Protocol.HTTP, 8182);
    component.getClients().add(Protocol.FILE);

    // Create an application
    Application application = new Application(component.getContext()) {
        @Override
        public Restlet createRoot() {
            // Create a root router
            Router router = new Router(getContext());

            // Attach a guard to secure access to the directory
            Guard guard = new Guard(getContext(),
                    ChallengeScheme.HTTP_BASIC, "Restlet tutorial");
            guard.getSecrets().put("scott", "tiger".toCharArray());
            router.attach("/docs/", guard);

            // Create a directory able to expose a hierarchy of files
            Directory directory = new Directory(getContext(), ROOT_URI);
            guard.setNext(directory);

            // Create the account handler
            Restlet account = new Restlet() {
                @Override
                public void handle(Request request, Response response) {
                    // Print the requested URI path
                    String message = "Account of user \""
                            + request.getAttributes().get("user") + "\"";
                    response.setEntity(message, MediaType.TEXT_PLAIN);
                }
            };

            // Create the orders handler
            Restlet orders = new Restlet(getContext()) {
                @Override
                public void handle(Request request, Response response) {
                    // Print the user name of the requested orders
                    String message = "Orders of user \""
                            + request.getAttributes().get("user") + "\"";
                    response.setEntity(message, MediaType.TEXT_PLAIN);
                }
            };

            // Create the order handler
            Restlet order = new Restlet(getContext()) {
                @Override
                public void handle(Request request, Response response) {
                    // Print the user name of the requested orders
                    String message = "Order \""
                            + request.getAttributes().get("order")
                            + "\" for user \""
                            + request.getAttributes().get("user") + "\"";
                    response.setEntity(message, MediaType.TEXT_PLAIN);
                }
            };

            // Attach the handlers to the root router
            router.attach("/users/{user}", account);
            router.attach("/users/{user}/orders", orders);
            router.attach("/users/{user}/orders/{order}", order);

            // Return the root router
            return router;
        }
    };

    // Attach the application to the component and start it
    component.getDefaultHost().attach(application);
    component.start();



    请注意,变量的值是直接从URI中提取的,因此这是没有精确解码的。为了实现这样的工作,请查看手册中的decode(String)方法

    12. 抵达目标资源

    在前面的示例中,在从目标URI中提取那些有趣部分时,我们利用了Restlet框架非常灵活的路由特性对request进行路由。但是,我们没有注意request方法和客户端对于它所期望的response的偏好。于是,我们如何才能将Restlet处理器和后台系统、域对象联系在一起呢?

    到目前为止,我们已经介绍了一些在Restlet中超越传统Servlet API的特性。但我们并没有在"Restlet"这个框架名称中使用"REST"。如果你还没有做的话,我推荐你学习一些关于REST架构风格和将其应用于Web应用的最佳实践。这里提供了相关的FAQ记录,希望能给你一些启示,同时我们也运营着很有用的REST搜索引擎(基于Google)。如果你对传统MVC框架有一定了解,那么你可以阅读一下另一个FAQ记录,它提供了对MVC与Restlet关系的详细说明。
    image

    总结一下,request中含有标识目标资源的URI,而目标资源就是调用的主旨。这种资源信息被保存在Request.resourceRef属性中,并能够像我们之前所见那样服务于路由机制。因此在处理request时的首要目标就是发现目标资源。。。Resource类的实例或者其子类中的某个。为了帮助我们完成此项任务,我们可以使用专用的Finder,一个Restlet子类,它将Resource类引用作为参数并在request到来时自动实例化它。然后Finder将动态将调用分配给最新创建的实例,实际上就是根据request方法调用它的handle*()方法中的某一个(handleGet,handleDelete等)。当然,我们可以自定义这种行为,甚至使用Router的attach()方法,将URI模板和 Resource类作为其参数透明地创建Finder!现在,让我们看一下展示了示例中主框架类之间关系的全景图表:

    回到代码中,我们在这里重构了Application.createRoot()方法。出于简化目的,我们没有提供具有静态文件的目录。你可以发现将Resource类直接指派给Router的方法。

    // Create a router
    Router router = new Router(getContext());

    // Attach the resources to the router
    router.attach("/users/{user}", UserResource.class);
    router.attach("/users/{user}/orders", OrdersResource.class);
    router.attach("/users/{user}/orders/{order}",
            OrderResource.class);

    // Return the root router
    return router;



    我们最后将重审一下UserResource类。这个类继承自org.restlet.resource.Resource类,因此它覆盖了具有三个参数的构造方法。此方法初始化了"context"、"request"和"response"属性。接着,我们使用从"/users/{user} "URI模板中提取出的"user"属性,将它的值保存在一个方便使用的成员变量中。然后,我们便可以在整个application中查找与"user" 相关的域对象了。最终,我们声明了用于暴露给用户的表示变量(representation variants),在这个简单的例子中只是文字而已。它将用于在运行时透明地完成一些内容导航,以便为每个request选择适合的变量,所有这些工作都是透明的。

    public class UserResource extends Resource {
        String userName;

        Object user;

        public UserResource(Context context, Request request,
                Response response) {
            super(context, request, response);
            this.userName = (String) request.getAttributes().get("user");
            this.user = null; // Could be a lookup to a domain object.

            // Here we add the representation variants exposed
            getVariants().add(new Variant(MediaType.TEXT_PLAIN));
        }

        @Override
        public Representation getRepresentation(Variant variant) {
            Representation result = null;
            if (variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
                result = new StringRepresentation("Account of user \""
                        + this.userName + "\"");
            }
            return result;
        }
    }



    你可以查看本指南中提供的代码包并对应用进行测试,并能够以仅接受Get请求的方式获得在第十一章中的相同行为。如果你希望使用PUT方法,那么就需要在UserResource中创建一个"allowPut()"方法并简单地返回"true",并且添加一个"put (Representation)"方法来处理调用。关于详细内容请查阅Restlet的Javadocs。

    结论

    我们已经涵盖了Restlet框架的许多方面。在你打算行动之前,让我们先回顾一下展示了本指南的主要概念和它们之间关系的两个层次图表:
    image

    这里是核心表示类:
    image

    除了本指南,你最好的信息来源就是Restlet API的Javadocs、Restlet扩展和NRE。还可以阅读一下connector一节,它列举出了客户端和服务端connector,并解释了如何使用、配置它们。集成一节列出了提供可插入特性的所有可用扩展:例如与servlet容器的集成、动态表示的生成等。你还可以在我们的讨论组中提出问题并帮助别人。


    展开全文
  • restlet.demo Restlet演示,用于发现Restlet并发错误
  • Restlet Client

    2021-03-02 15:05:09
    【安装教程】点击链接,可查看安装方法 ...Restlet Client 插件是一个类似Postman的Api接口测试工具, 界面友好, UI布局也更合理。相比Postman, Restlet Client无需安装本地客户端, 即装即用, 占用空间小, 功能强大。
  • restlet-guides Restlet使用指南
  • RESTLET开发

    2017-03-15 15:42:39
    RESTLET开发实例(一)基于JAX-RS的REST服务
  • restlet restful

    2017-11-14 11:17:52
    restlet restful,web工程,可直接运行。启动后,main方法作为client运行调用服务端。服务器数据之间沟通利器,绝对不坑。
  • restlet代码

    2013-09-13 22:04:29
    restlet代码
  • restlet笔记

    2013-04-12 01:35:26
    restlet笔记
  • restlet项目

    2012-05-02 00:14:00
    restlet项目
  • VS_Restlet 这是大学课程“Verteile Systeme”认识RESTlet的一个项目。
  • Restlet Client下载

    2018-05-07 20:30:05
    Restlet Client - REST API Testing.crx控件,谷歌、360浏览器等均可以使用
  • RESTLET框架学习书籍

    2018-10-15 17:20:08
    RESTLET框架学习书籍
  • org.restlet.jar

    2021-01-07 16:10:00
    org.restlet.jar
  • restlet.jar

    2013-10-16 22:33:47
    restlet源代码,restlet jar包
  • restlet in action

    2014-04-27 15:45:14
    restlet

    restlet

    展开全文
  • Restlet开发实例

    2015-05-07 10:32:59
    资源里面包含了Restlet从入门到高级的开发过程,对学习Restlet有很大的帮助
  • Restlet_client

    2018-12-13 16:31:25
    Restlet_client插件,google使用,用来模拟http请求。
  • Restlet学习

    2015-08-06 18:35:12
     import org.restlet.Application; import org.restlet.Component;...import org.restlet.Restlet; import org.restlet.data.Protocol; import org.restlet.routing.Router; public class FirstStepsAppli
    


    import org.restlet.Application;
    import org.restlet.Component;
    import org.restlet.Restlet;
    import org.restlet.data.Protocol;
    import org.restlet.routing.Router;

    public class FirstStepsApplication extends Application {

     public static void main(String[] args) throws Exception { 
         // Create a new Component. 
         Component component = new Component(); 

         // Add a new HTTP server listening on port 8182. 
         component.getServers().add(Protocol.HTTP, 8183); 

         // Attach the sample application. 
         component.getDefaultHost().attach("/firstSteps", 
                 new FirstStepsApplication()); 

         // Start the component. 
         component.start(); 
     } 
        /**
         * Creates a root Restlet that will receive all incoming calls.
         */
        @Override
        public synchronized Restlet createInboundRoot() {
            // Create a router Restlet that routes each call to a new instance of HelloWorldResource.
            Router router = new Router(getContext());

            // Defines only one route
            router.attach("/context", FirstResouce.class);

            return router;
        }

    }


    ---------------------------------------------------------------------------------

    import org.restlet.resource.Get;
    import org.restlet.resource.ServerResource;

    public class FirstResouce extends ServerResource{
     @Get
     public static String testGet() {
      return "hello restlet";
     }
    }

    展开全文
  • restlet-practice java restlet实践,Restlet框架即是一个客户端,又是一个服务端框架。可以使用restlet轻松构建基于ROA服务。 效果截图: POST方法: GET方法:

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,444
精华内容 1,377
关键字:

Restlet