RESTful Web 服务和 Apache Wink,第 2 部分: Apache Wink REST 开发中的高级主题

注释,集成及其他

本文是三篇系列文章的第二篇,讨论 Apache Wink 1.0 开发的高级主题,这种新的 Java™ 框架用于实现和消费基于 REST 的 Web 服务。

Vishnu Vettrivel, 首席顾问, PunditLabs Inc.

http://www.ibm.com/developerworks/i/p-vvettrivel.jpgVishnu Vettrivel 是 PunditLabs 的主要顾问,致力于企业咨询和技术,他在构建、设计和开发任务关键性企业应用程序方面有多年的工作经验。他与《财富》50 强客户有广泛的工作接触,并针对许多新兴技术帮助员工制订战略技术规划。



2010 年 8 月 30 日

本文介绍与 Apache Wink version 1.0 开发有关的高级主题,包括使用附加注释、集成 Wink 服务和常用的 Spring Framework,以及使用 Apache Wink Client 框架实现自定义 RESTful 客户端。

常用缩写词

  • API:应用程序编程接口(Application programming interface)
  • CSV:逗号分隔值(Comma-separated values)
  • HTTP:超文本标记语言(Hypertext Transfer Protocol)
  • JSON:JavaScript Object Notation
  • MIME:多用途 Internet 邮件扩展(Multipurpose Internet Mail Extensions)
  • RSS:真正简单的聚合(Really Simple Syndication)
  • URI:统一资源标识符(Uniform resource identifier)
  • XML:可扩展标记语言(Extensible Markup Language)

注释!

在 JAX-RS 中,注释是将传入的 HTTP 请求信息注入 Java™ 方法的主要机制之一。作为一个遵从 JAX-RS 的框架,Apache Wink 根据规范实现需要的注释,但是它还提供了很多非标准的注释,比如 @Asset 注释和 @Scope 注释。

@Asset 注释

@asset 注释是一个标记,将 Java 类标识为资产。资产 是资源方法返回的特殊形式的实体对象。Apache Wink 运行时还可以将资产以参数的形式注入资源方法中。资产是一个数据模型容器对象,为各种内容类型提供转换方法。资产可用于在资源和提供者之间传递信息,有助于减少在 Apache Wink 系统中注册的提供者数量。这一点非常重要,提供者过多会导致 Wink 系统的系统性能降低。

清单 1 演示 @asset 注释的用法。Transaction bean 是一个 Java Architecture for XML Binding (JAXB) class.TransactionAsset 类。TransactionAsset 类包装 Transaction bean 的一个实例,如下所示。

清单 1. TransactionAsset 类
@Asset
public class TransactionAsset {
	public Transaction transaction;   						
	public TransactionAsset(Transaction transaction) {
		this.transaction = transaction;
    }
 	@Produces("application/xml")
    public Transaction getTransaction() {
        return this.transaction;
    }
	@Consumes("application/xml")
	public void setTransaction(Transaction transaction) {
		this.transaction = transaction;
    }
}

该资产类可作为响应由资源方法返回,也可以参数的形式被传递。Apache Wink 运行时通过调用资产类对应的方法构建实际的响应实体。

@Scope 注释

根据 JAX-RS 规范,默认情况下,提供者和资源类为每个 JAX-RS 应用程序实例化一次。这种实例化涉及到要调用的类的默认构造函数,随后还要注入依赖关系。

在对象的生命周期期间,在将提供者和资源对象中的相应方法作为垃圾回收之前,可对其进行多次调用。Apache Wink 通过 @Scope 注释为提供者和资源提供其他生命周期。 清单 2 展示了如何使用原型(每个请求)生命周期定义资源。

清单 2. @Scope 示例
@Scope(ScopeType.PROTOTYPE)
@Path("helloworld")
public class HelloWorldResource {
    ...
}

在原型生命周期中,Apache Wink 运行时为每个传入请求实例化一个新的对象。尽管这种行为从内存/性能角度看可能不太理想,但您无需再担心资源和提供者类中的线程和并发问题。

@Parent 注释

本系列的 第 1 部分 详细介绍了 @Path 注释,并指出 JAX-RS 使用它为传入请求定义 URI 匹配模式。通常将其置于 Java 类或方法。

@Parent 注释与 @Path 注释有 “紧密” 的联系,它为资源中指定的内容提供基本 URI。如果 Apache Wink 运行时在资源中遇到 @Parent 注释,那么它将尝试计算最终的资源 URI 模板:首先计算包含父资源类 URI 的 @Parent 注释的值,之后尝试连接资源路径 URI 和父资源的 URI。清单 3 提供了一个 @Parent 注释的示例。

清单 3. @Parent 示例
@Path("parentservice")
public class ParentResource {
    ...
}

@Parent(ParentResource.class)
@Path("childservice")
public class ChildResource {
    ...
}

在本例中,有两个资源:ParentResourceChildResourceParentResource@Path 注释定义为 parentservice URI。ChildResource@Path 注释定义为 childservice URI。ChildResource 还使用 @Parent 注释将 ParentResource 定义为父资源。在本例中,Apache Wink 运行时将 ChildResource 的最终 URI 变为 parentservice/childservice


管理视图

为了帮助开发人员更好地理解他们的 RESTful Web 服务,Apache Wink 提供了两种管理视图:Application Resource XML 视图和 Resource Registry XML 视图。默认情况下,这些视图都是禁用的,您必须在应用程序 web.xml 文件中注册 org.apache.wink.server.internal.servlet.AdminServlet 类才能激活它们。

Application Resources XML 视图公开 REST 资源及其 URI 模板、HTTP 方法以及每个方法支持的 MIME 类型,类似于帮助用户获得应用程序的方式。这种视图可以方便地为部署的服务生成自动化服务文档。

Resource Registry XML 视图比 Application Resources XML 视图更加详细,它显示了服务公开的实际实现细节,包括在注册表中实现资源及其优先级的类名称。该视图对于调试过程非常有用,但是不应在生产中启用,因为它披露了实现细节,可能会影响安全性。


WebDAV 支持

基于 Web 的分布式编辑和版本控制(Distributed Authoring and Versioning,WebDAV)是 HTTP 协议的一个扩展集合,支持用户在 Web 服务器上(比如 Apache Web Server)编辑和管理文件。WebDAV 协议的一些主要功能包括:

  • 锁定文件
  • 文件属性或元数据
  • 文件名称空间管理

Apache Wink 通过扩展模块支持 WebDAV 协议。Apache Wink 扩展模块包括 WebDAV XML 模型和 WebDAV 响应构建程序,用于帮助创建和处理 WebDAV 响应。


运行中的 Spring

Spring 是一个常用的开源 Java 框架,原本是用作现有 Java 标准(比如 Enterprise JavaBean (EJB) 技术)的一个轻量级替代方法。与 EJB 标准类似,Spring Framework 还提供了事务、持久性、安全性 —— 以及更重要的 —— 依赖关系注入(JAX-RS 中也借用了这个概念)方面的功能。有关 Spring Framework 的更多信息,请参考 参考资料

Apache Wink 通过核心框架中的其他模块提供了与 Spring 的轻松集成。Apache Wink Spring 集成模块提供了以下主要功能:

  • 在 Spring 上下文中将资源和提供者注册为类或 Spring bean
  • 定义资源/提供者生命周期,并覆盖默认的 singleton 范围
  • 使用 Spring 功能,如 Inversion of Control (IoC) 和事后处理程序(postprocessor)
  • 通过轻松自定义 Spring 上下文中的挂钩自定义 Apache Wink

Spring 上下文加载

在 Spring Framework 中,Spring 上下文类似于 Apache Wink 应用程序,必须在定义和加载其他 Spring bean 之前加载。加载 Spring 上下文之后,它可以轻松将资源和提供者注册为 Spring bean。

要加载 Spring 上下文,您首先必须定义上下文加载侦听器并将其添加到 Web 应用程序的 web.xml 文件。同样,contextConfigLocation context-param 应该指示 Apache Wink 核心上下文文件的位置和特定于应用程序的上下文文件。清单 4 提供了定义和加载 Spring 上下文的 web.xml 文件示例。

清单 4. Spring 上下文加载 web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/server/winkCoreContext-server.xml
	classpath:mySpringcontext.xml
</param-value>
</context-param>
<listener>
<listener-class>
	org.springframework.web.context.ContextLoaderListener
  	</listener-class>
</listener>

资源和提供者注册

加载了 Spring 上下文之后,您可以使用 Apache Wink 提供的 org.apache.wink.spring.Registrar 类注册资源和提供者。Registrar 类是我们熟悉的 WinkApplication 类的扩展,首先必须定义为 spring bean。

还可以使用 Registrar 类定义以下属性:

  • 实例。资源和提供者实例通常定义为 Spring bean,可以自动获取 IoC 以及其他 Spring 功能。
  • 类。定义资源和提供者的类名;该属性与 Wink Application 类中的 getClasses 方法相同。
  • 优先级。该属性定义 WinkApplication 的优先级。

清单 5 是 Spring bean 配置文件的一个示例,将 Apache Wink 资源和提供者定义为 Spring bean。

清单 5. Spring 配置文件 mySpringcontext.xml
<bean class="org.apache.wink.spring.Registrar">
  <property name="classes">
    <set value-type="java.lang.Class">
      <value>org.openengine.example.TransactionResource</value>
    </set>
  </property>
  <property name="instances">
    <set>
      <ref bean="resources.TransactionResource"/>
      <ref bean="providers.myprovider"/>
    </set>
  </property>
</bean>

将 Wink 作为客户端

除了是遵从 JAX-RS 的服务器框架外,Apache Wink 还可以作为高级客户端框架。Apache Wink 客户端框架提供一个简单的 Java API,完成实现客户端的任务以直接使用基于 HTTP 的 RESTful Web 服务。Apache Wink 客户端框架还有一个可自定义的处理器机制,用于操作 HTTP 请求和响应。Apache Wink 客户端以 JAX-RS 原则为基础构建,包括基于 REST 的概念和标准。通过将 REST 驱动的构想映射到 Java 类,它们有助于为基于 Apache Wink 的服务和任何 HTTP 驱动的 RESTful Web 服务开发客户端。作为一个独立的基于 REST 的 Java 客户端框架,它们非常有用。

以下是 Apache Wink 客户端框架的一些主要功能:

  • 使用可配置的 JAX-RS 提供者序列化和反序列化资源
  • 对各种内容类型提供内置支持,包括 Atom、JSON、RSS、APP、CSV 和 Multipart,以及 Java 中对应的对象模型
  • 提供对 Secure Sockets Layer (SSL) 和 HTTP 代理的支持
  • 类似于服务器端框架,客户端框架有一个可配置的处理程序链,用于操作 HTTP 请求和响应
  • 默认使用 java.net.HttpUrlConnection 类提供核心 HTTP 传输
  • 允许轻松定制核心 HTTP 传输机制

图 1 中的图表演示了 Apache Wink 客户端框架的架构。

图 1. Apache Wink 客户端架构
左边的 4 个框标记为 'Resources'。它们都指向标记为 'Handler'的框。连接它们的线标记为 'Invoke method'。在这些框上方是一个标记为 'RestClient' 的框。下方是两个分别标记为 'Provider registry' 和 'Configuration' 的框。

正如您看到的,Apache Wink 客户端框架主要包括 RestClient 类,该类是保存各种配置和提供者注册的中央位置。要开始处理客户端框架,必须实例化一个新的 RestClient 对象实例。然后,使用希望连接的服务的 URI 从中创建 Resource 类的一个实例。Resource 类是与特定 URI 有关的 RESTful Web 资源的 Java 等效类,用于执行基于 HTTP 的操作。所有的 HTTP 方法调用都通过可自定义的处理程序链进行筛选,处理程序链可以轻松操作 HTTP 请求和响应。

GET 请求

清单 6 演示了通过 Apache Wink 客户端使用 HTTP GET 请求的示例。

清单 6. GET 请求示例
// create the rest client instance
RestClient client = new RestClient();

// create the resource instance to interact with
Resource resource = client.resource("http://localhost:8080/HelloWorld");

// perform a GET on the resource. The resource will be returned as plain text
String response = resource.accept("text/plain").get(String.class);

如前所述,RestClient 对象是 Apache Wink 客户端框架的起点。要构建 RESTful Web 服务客户端,您必须实例化一个新的 RestClient 对象实例,之后使用希望通过 RestClient#resource() 方法调用的服务的 URI 创建一个新的 Resource 对象。要发布 HTTP GET 请求,您必须调用 Resource#get() 方法。该方法返回 HTTP 响应。然后,通过调用相应的提供者,该客户端还可以对响应进行反序列化。

POST 请求

清单 7 演示了通过 Apache Wink 客户端使用 HTTP POST 请求的示例。

清单 7. POST 请求示例
// create the rest client instance
RestClient client = new RestClient();

// create the resource instance to interact with
Resource resource = client.resource("http://localhost:8080 ");

// issue the request
String response = resource.contentType("text/plain").
			accept("text/plain").
				post(String.class, "foo");

从中可以看到,发出 POST 请求类似于发出 GET 请求。就像 GET 请求示例一样,您通过 RestClient 创建一个新的 Resource 实例。唯一的不同在于,指定请求和响应媒体以及响应实体类型之后,POST 字符串本身作为方法参数传递到 resource.post 方法。同样,该响应以字符串形式返回。

Atom 客户端请求

如上所述,Apache Wink 客户端框架还提供一些以多种内容类型发出请求的功能。清单 8 提供了一个示例,演示如何发出发送和接受 Atom 项的 HTTP POST 请求。

清单 8. Atom 请求示例
// create the rest client instance
RestClient client = new RestClient();

// create the resource instance to interact with
Resource resource = client.resource("http://services.co");
AtomEntry request = getAtomEntry();

// issue the request
AtomEntry response = resource.contentType("application/atom+xml").
			accept("application/atom+xml").
				post(AtomEntry.class, request);

由于 Apache Wink 客户端为支持发送和接受 Atom feed 和 Atom 项的 Atom 提供对象模型,所以使用 AtomEntry 对象发出 Atom 请求和解析响应很简单。


结束语

本文简单介绍了与 Apache Wink 1.0 框架相关的一些高级主题,包括注释、管理视图、WebDAV 支持。您还了解了 Apache Wink 如何通过内置的扩展模块支持 Spring 集成,并深入探究了 Apache Wink 客户端框架及其底层架构。请关注本系列的第 3 部分,比较一下 Apache Wink 和其他遵从 JAX-RS 的框架,及其相对优势与劣势。如果希望学习更多有关 REST、JAX-RS 或 Apache Wink 1.0 框架的内容,请参考 参考资料

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development
ArticleID=513961
ArticleTitle=RESTful Web 服务和 Apache Wink,第 2 部分: Apache Wink REST 开发中的高级主题
publish-date=08302010