快捷搜索:

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

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 实例的治理。

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!";

}

}

您可能还会对下面的文章感兴趣: