使用 RESTlet 框架开发符合 JSR311 规范标准的 REST Web Service

来源:互联网 发布:巨大中华 知乎 编辑:程序博客网 时间:2024/04/29 06:04

JSR311 作为 Java 实现 REST Web Service 的规范标准,尽管从出生起就备受争议,但从事实上,已经普遍被大多数 REST 实现框架的接受。这中间,既有 Sun 公司原产的 Jersey, 也有其他的开源项目,如 Jboss 的 RESTEasy,Apache 的 CXF 等。当然,还有发展时间最长,相当成熟的 RESTlet 框架。

  RESTlet 的主体核心是按照 Roy Thomas Fielding 的著作"Architectural Styles and the Design of Network-based Software Architectures"。结构清晰,稳定性强。但是该框架下的资源定义是有别于 JSR311 的那种 JAX-WS 风格的 annotation。这对于钟爱 RESTlet 的 Web Service 开发人员,就面临着选择阵营的风险。所幸的是,RESTlet 的领导开发人员 J é rome Louve 也是 JSR311 的参与者 , 这反映在 RESTlet 1.1 提供了一个 Extension 来帮助 RESTlet 的开发人员编写符合 JSR311 的 Web Service。某些企业级产品,如 IBM Systems Director 6.1.2, 已经在产品中使用这种技术。本文重点介绍 JAX-RS extension 的基本实现结构以及如何利用该插件进行 JSR311 规范标准的 REST Service。

  本文以 Neolies RESTlet 1.1.8 作为讨论的基础,并且假定读者已经对 REST,JAX-RS 以及 RESTlet 有一定的理解。因此不会详细讨论相关的基本知识,读者也可以通过阅读"构建 RESTful Web 服务"来获取这方面的相关知识。

  RESTlet 和 JSR-311

  JAX-RS Annotation 简介

  @Path: 用来映射 URI,为资源类以及资源类中包含的方法提供访问路径。

  @GET: 表示处理 HTTP GET 请求的资源类方法。当 Web Service 获得客户端发出的对与某个网络资源的 HTTP GET 操作时,服务器会调用被 @GET 注解后的方法来处理 GET 请求。当然,被调用的资源类方法首先得满足 URI。

  @POST: 表示处理 HTTP POST 请求的资源类方法。和 @GET 相类似,只不过对应的是 HTTP POST 操作。

  @PUT: 表示处理 HTTP PUT 请求的资源类方法。该 Annotation 通常用于更新网络对象的方法。和 @GET,@POST 处理流程相类似。

  @DELETE: 表示处理 HTTP DELETE 请求的资源类方法。使用该 Annotation 后的方法通常是删去每个网络对象的实例。处理流程和 @GET,@POST,@PUT 相类似。

  @HEAD: 表示处理 HTTP HEAD 请求的资源类方法。通常情况下,根据 JAX-RS 规范的设定,在没有实现 @HEAD 的资源类方法时,RESTlet JAX-RS extension 会自动处理 HTTP HEAD 请求,@GET 注解的资源类方法会自动被调用。和处理普通的 HTTP GET 请求的区别是没有实例被返回。@HEAD 注解的资源类方法通常用来获取 Web Services 能够接受的数据格式。

  @Produces: 用来表示资源类方法能够返回的 MIME 的媒体类型。

  @Consumes: 用来表示资源类方法能够处理的 MIME 的媒体类型。

  Neolies RESTlet 设计风格上尽量遵循 Roy Fielding 博士论文中所阐述的 REST 的目标。从实现层面上,Neolies RESTlet 可以分为三个部分:

  RESTlet API: 这个部分设计了 RESTlet 的框架,包括在经典 REST 结构中所包括的 Application, Component,Route,Connector,VirtualHost, Resource 等,都在这个部分被详细定义。

  NRE(Noelios Restlet Engine):这个部分是对 RESTlet API 的参考实现,RESTlet API 通过代理模式 (Delegation) 将具体的工作转交到 NRE 中执行,如 RESTlet API 中的 Application 在 NRE 中的代理就是 ApplicationHelper。

  Extensions:这个部分是对 RESTlet API 的扩展(不依赖于 NRE)。包括 JAX-RS Extension,还有对 JSON 或是对 JAXB 的 Extensions。

  JAX-RS 与 RESTlet API 的不同之处在于,在 RESTlet 下,REST 资源是结构化组织起来的,如 Component 可以包含多个 Application,Application 又可以包含多个 REST 资源,Component 到 Application,Application 到 REST 资源以 Route 来连接。这样,从 URI 到 REST 资源的定位就自上而下进行查找。JSR311 下,REST 资源是 POJO 并且非结构化的,资源对应的 URI 通过 Annotation 直接在 POJO 类里加以描述(这里不讨论 subresource 资源的定位)。相对来说,JAX-RS 描述能力简单,开发起来更加方便。JAX-RS 所定义的 REST 框架,包括:

  Annotation:比如说在 HttpMethod 支持 @PUT,@POST,@DELETE,@GET 等等,或是 @QueryParam 可以表示 GET 操作的查询参数等等。这些 Annotation 在 REST 资源所在的 POJO 类里被使用。

Application:JAX-RS 没有定义 Component 或是 VirtualHost,只是用 Application 来存放所有的 REST 资源。

  HTTP 协议基础类:包括 CacheControl, Cookie 等等,这些类处理 HTTP 协议层的相关字段,这些类的具体实现是以代理模式 (Delegation),通过 RuntimeDelegate 类来连接到具体实现的。

  MessageBodyReader 和 MessageBodyWriter:这对接口的实现主要使用在 Provider。Provider 可以用作 REST 相应体的序列化和反序列化。

  RESTlet JAX-RS Extension 实现了 JAX-RS。主要的技术要点包括:

  internal.Provider:JAX-RS Extension 通过 MessageBodyReader 和 MessageBodyWriter,实现了 InputStream,Jaxb,ByteArray 等 Provider 的序列化和反序列化。

  internal.spi:JAX-RS Extension 实现了 HTTP 协议基础类。

  internal.exceptions:定义了 JAX-RS 抛出的异常。

  JaxRsApplication:实现了 JAX-RS 的 Application 接口,并且包含 JaxRsRestlet。具体的工作是在 JaxRsRestlet 中处理的。

  JaxRsRestlet:包含了所有的 REST POJO 资源,在初始化时分析 REST 资源的 Annotation, 得到 REST 资源所对应的 URI,对应的接口以及其他相关信息。JaxRsRestlet 还包含了所有 Provider 的引用和所有异常的引用。运行过程中,所有的 REST 请求被路由到 JaxRsRestlet,由该对象来选择合适的 REST 资源及方法来进行处理。

  RESTlet JAX-RS Extension 的配置

  配置基于 RESTlet JAX-RS Extension 的 Web Service 也就是部署该架构下的 Web Service。RESTlet 架构提供两种部署 Web Service 的方式。两种方式都方便简单,用户可以根据自己的需求选择任意一种部署方式。

  将 Web Service 当做单独的 Java 程序进行部署

  将 Web Service 部署到 Servelet Container 中

  两种方式都方便简单,用户可以根据自己的需求选择任意一种部署方式。

  将 Web Service 部署成一个单独运行的 Java 应用非常的简单,只需要完成以下几个步骤。

  导入需要的 JAR 包,org.restlet.jar,以及 org.restlet.ext.jaxrs_1.0.jar。

  为 HTTP Server 创建相应 Java 类。在新建的 Java 类中依次完成以下工作,引入 org.restlet.jar 包中需要的类,新建 HTTP Server,定义该 Server 监听的端口,将 Web Service 的配置类加入到 HTTP 服务器中。

  编译运行 HTTP Server。

  将基于 RESTlet Jax-Rs Extension 的 Web Service 部署到 Servelet Container 中的过程和部署一个基本的 Servelet 极其相似。不同的是,部署过程中,用户需要注意添加需要的 Jar 包。以下 Jar 是该部署方式所需要的。

  org.restlet.jar

  org.restlet.ext.jaxrs_1.0.jar

  com.noelios.restlet.jar

  com.noelios.restlet.ext.servlet_2.5.jar

  为了成功将基于 RESTlet Jax-Rs Extension 的 Web Service 部署为 Servelet,用户需要完成以下动作。

  编译基于 RESTlet Jax-Rs Extension 的 Web Service 包含的代码。

  将需要的 JAR 包存放于 /WEB-INF/lib 中。

  创建 Servelet 的配置文件 web.xml。

  将所有相关内容打包成 WAR 包,并部署到用户选定的 Servelet 容器中。

  在 RESTlet 架构下实现 JAX-RS Web Service 示例

  JAX-RS Extension 是在 RESTlet 架构下的对 JAX-RS:Java API for RESTful Web Services 的实现。本段将通过实例说明如何使用 JAX-RS 提供的接口实现 RESTlet 架构下的 Web Service。在正式介绍实例之前,先对实例的应用环境进行简单的分析。本文以一个简单的用户管理功能为基础介绍如何在 RESTlet 架构下实现 JAX-RS Web Service。实例中的用户管理功能主要包括用户组和用户两个对象,使用者可以通过调用 PUT 操作添加新的用户组和用户,GET 操作则可以用来获取已存在用户组和用户的信息,用户组和用户的删除则通过 Delete 操作来实现。为了简单起见,本实例仅提供 GET 操作的实现,POST 操作和 Delete 操作只需要按照 REST 架构类似的实现就可以。本例相关的 URI 实现。

  /users/usergroup:请求用户组的介绍。

  /users/usergroup/{id}: 请求特定的用户组信息。

  /users/user: 请求用户对象的相关介绍。

  /users/user/{id}: 请求特定用户对象的相关信息。

  对需求分析结束后,我们将开始实现该过程主要可以分为三个步骤。

  提供资源类,实现需要支持的操作

根据需求创建应用配置类

  建立 JAX-RS 服务器,部署实例

  创建资源类

  首先需要创建一个 JAVA 类命名为 JaxRsExtensionResource,通过 @GET 的使用,将不同的 HTTP GET 请求映射到资源类方法中。@Path 的使用将 URI 与相应的资源类以及资源方法相结合。例如, @Path("users") 将 URI /users/ 和 ExampleResource 类相关联,Path("user/{id}") 将 URI /users/user/{id} 与 ExampleResource 的 findUser(...) 方法相关联。User 类是对用户的抽象,UserGroup 是对用户组的抽象。UserManager 类负责 User 实例的管理,相应 UserGroupManager 类负责 UserGroup 实例的管理。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 package com.developerworks.jaxrs.resltet.example; 
 
 import java.util.ArrayList; 
 import java.util.List; 
 
 import javax.ws.rs.*; 
 
 @Path("users") 
 public class JaxRsExtensionResource { 
 
  @GET 
  @Path("usergroup") 
  public String getUserGroup() { 
    return "Group are used to classify different kind of users!"; 
  } 
 
  
  @GET 
  @Path("user") 
  public String getUser(){ 
  return "Users inlcudes the information of registered user!"; 
  } 
 
  @GET 
  @Path("user/{id}") 
  public String findUser(@PathParam("id") String id){ 
   User temp = UserManager.get().getDetails(id); 
   if(temp != null) 
    return temp.toString(); 
   else 
    return "The user you queried(ID:" + id + ") doesn't existed!"; 
  } 
   
  @GET 
  @Path("usergroup/{id}") 
  public String findUserGroup(@PathParam("id") String id){ 
   UserGroup group = UserGroupManager.get().getDetails(id); 
   if(group != null) 
    return group.toString(); 
   else 
    return "The group you queried(ID:" + id + ") doesn't existed!"; 
  } 
   
 } 

  创建应用类

  RESTlet 架构中的应用类主要用来初始化 Web Service 的运行环境。Restlet 为了方便使用者,提供了很多可以方便使用的基本功能, 用户通过自己定义的应用类来选择使用需要的功能。这些基本功能包括为客户端和服务器端提供必要的链接,编码解码功能,元数据,状态包装等。本例不涉及到这些功能,所有有关这些功能的说明及使用方法,请参阅 RESTlet 手册。在本例中,我们只需将上节定义的资源类加入即可。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 package com.developerworks.jaxrs.resltet.example; 
 
 import java.util.HashSet; 
 import java.util.Set; 
 import javax.ws.rs.core.*; 
 
 public class ExampleApplication extends Application { 
 
  public Set<Class<?>> getClasses() { 
    Set<Class<?>> rrcs = new HashSet<Class<?>>(); 
    rrcs.add(JaxRsExtensionResource.class); 
    return rrcs; 
  } 
 }

  RESTlet 架构为了更好的支持 JAX-RS 规范,定了 JaxRsApplication 类来初始化基于 JAX-RS 的 Web Service 运行环境。JaxRSApplication 类使用起来非常的方便,只需要将原本基于 RESTlet 架构的应用类加入到用户自己实现的 JaxRsApplication 子类中即可。如果需要认证功能的话,使用 JaxRsApplication 的 setGuard(...) 或者 setAuthentication(...) 方法即可。本例中不设置到认证功能,所以只需要将 ExampleApplication 类加入到本例实现 JaxRsApplication 子类中即可。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 package com.developerworks.jaxrs.resltet.example; 
 
 import org.restlet.Context; 
 import org.restlet.ext.jaxrs.JaxRsApplication; 
 
 public class JaxRsExtensionApplication extends JaxRsApplication { 
 
  public JaxRsExtensionApplication(Context context) { 
    super(context); 
    this.add(new ExampleApplication()); 
  } 
   
  public static void main(){ 
   System.out.println("Hello"); 
  } 
 }

  部署 Web Service

  新建 Java 类,命名为 JaxRsExtensionServer, 在该类中创建一个新的 Http Server,并为该 Http Server 添加监听端口,本例使用 8182 端口。将上面创建的 Web Service 运行环境配置类 JaxRsExtensionApplication 加入到 Http Server 中。


原创粉丝点击