如何构建Apache_Wink_REST服务

首先简要介绍一下REST。REST代表Representational State Transfer,它是World Wide Web所依赖的一套架构原则。Roy Fielding在他的博士论文“Architectural Styles and the Design of Network-based Software Architectures”中首次提出了这个概念。在他的论文中,Fielding明确指出REST和World Wide Web的五个架构原则:
•   可寻址性(Addressability)。REST中的所有东西都基于资源 的概念。资源与OOP中的对象或其他名词不同,它是一种抽象,必须可以通过 URI 寻址或访问。

  接口一致性(Interface uniformity)。与SOAP或其他标准不同,REST 要求用来操纵资源的方法或动词不是任意的。这意味着RESTful服务的开发人员只能使用HTTP支持的方法,比如GET、PUT、POST、DELETE等等。因此不需要使用 WSDL 等服务描述语言。
•   无状态(Statelessness)。为了增强可伸缩性,服务器端不存储客户机的状态信息。这使服务器不与特定的客户机相绑定,负载平衡变得简单多了。这还让服务器更容易监视、更可靠。
•   具象(Representational)。客户机总是与资源的某种具象交互,绝不会直接与资源本身交互。同一资源还可以有多个具象。理论上说,持有资源的具象的任何客户机应该有操纵底层资源的足够信息。
•   连通性(Connectedness)。任何基于REST的系统都应该预见到客户机需要访问相关的资源,应该在返回的资源具象中包含这些资源。例如,可以以超链接的形式包含特定RESTful服务的操作序列中的相关步骤,让客户机可以根据需要访问它们。
  JAX-RS
  Web上的REST以下站点当前正在使用REST:
  Atom Publishing Protocol。Atom是REST协议最正规的实现之一,广泛用于博客发布领域。
  Sun的Cloud API。这是Sun的RESTful API,用于管理和创建计算、连网和存储元素等云资源。
  Digg的API。Digg 是一个流行的社交网站,它使用RESTful API让用户和合作伙伴能够以编程方式与站点和数据交互。
  Netflix API。Netflix是一个DVD出租网站,它使用RESTful API提供对影片目录的细粒度访问,以及以编程方式调整用户队列和获取影片推荐。
  Flickr API。Flickr是一个照片上传网站,用户可以使用它提供的RESTful API上传、更换和搜索照片和像册。

  为什么需要另一个Java标准?定义JAX-RS这个新规范是为了简化基于REST的Java开发。它主要关注使用Java注释和普通旧式Java对象(POJO)实现 RESTful 服务。尽管总是可以使用servlet实现RESTful服务,但是以这种方式实现业务逻辑需要太多HTTP GET请求。
  JAX-RS隐藏所有 HTTP并把servlet绑定到Java类中的各个方法。注释还可以动态地提取HTTP请求中的信息,以及把应用程序生成的异常映射到HTTP响应码。由于这些原因,JAX-RS是一种实现RESTful Java Web服务的有效方法。
  Apache Wink和REST
  我已经介绍了REST和JAX-RS,现在开始讨论Apache Wink。Apache Wink 1.0是一个从头设计的完全兼容的JAX-RS 1.0规范实现。它很容易使用和应用于生产环境,它提供的特性可以增强核心JAX-RS规范。
  Apache Wink运行时架构是JAX-RS 1.0规范的简单实现。Apache Wink部署在Java Platform, Enterprise Edition (Java EE)环境中,由以下三个组件组成:
•   Apache Wink RestServlet。RestServlet在Web应用程序的Java EE web.xml描述符文件中配置。这个servlet作为所有HTTP Web服务请求的主入口点,它把请求和响应对象实例分派给请求处理器进行进一步处理。
•   请求处理器。RequestProcessor是核心Apache Wink引擎,它由Apache Wink RestServlet初始化。请求处理器使用请求 URI 寻找、匹配和调用相应的资源类和方法。在请求处理期间发生的任何异常都会导致RequestProcessor调用Error Handler Chain以处理异常。
•   资源。在REST中,代表Web服务的任何组件或对象都被称为资源。资源允许通过它的许多具象之一获取和操纵数据。实现资源的POJO被称为资源类。资源类进一步实现资源方法,资源方法实际处理底层业务逻辑。
•   整个请求周期被称为Apache Wink逻辑流,见 图 1。

图 1. Apache Wink 逻辑流
  Apache Wink不但帮助实现RESTful Web服务,而且提供一个强大的客户机库,可以使用它轻松地消费RESTful服务。最后,Apache Wink附带一组内置的提供者,它们帮助开发人员支持多种行业标准的数据格式:XML、Atom、RSS、JSON、CSV和HTML。
  RESTful设计
  现在该实践一下了。为了保持趣味性,我们要在Apache Wink 1.0上设计、实现和部署一个不太简单的RESTful服务。这个服务是PayPal Payflow支付网关服务的RESTful包装器,它可以通过Internet进行信用卡处理。但是,对于这个示例,我们只关注它的交易查询功能。只要提供一个属于经过身份验证的用户的惟一ID,这个功能可以查询任何交易的状态。
  资源/URI设计
  首先定义服务的接口模型并给它分配URI,这使服务成为REST中的资源。因为这个服务的功能是提供交易状态,可以公开 清单 1 所示的 URI。
  清单 1. 交易服务的URI模式
   
以下是引用片段:
/transactions
/transactions{id}


  transactions URI表示系统中的所有交易。使用/transactions{id}查询某一交易的状态。{id}代表对应于交易模型的交易ID的惟一字母数字值。另外,使用 清单2中的模式验证用户的身份,其中的UNAME、VNAME、PNAME和PWD是在注册时分配给商人的Payflow网关登录凭证的组成部分。
  清单 2. 在查询字符串中包含用户凭证的URI模式
   
以下是引用片段:
/transactions{id}?user=UNAME&vendor=VNAME&partner=PNAME&pwd=PWD


  数据设计
  每个RESTful接口必须决定支持它的客户机使用哪种具象。Apache Wink 1.0可以支持XML、JSON、HTML和Atom 等,这个示例使用JSON,因为这是一种流行的格式,而且Ajax应用程序很容易使用JavaScript代码。清单 3 是一个采用JSON格式的交易状态示例。
  清单 3. JSON字符串形式的交易状态响应
   
以下是引用片段:
{
"RESULT":19,"PNREF":"V19A2A1A7CC5",
"RESPMSG":"Original transaction ID not found: V19A2A192BE9",
"AUTHCODE":null,"CVV2MATCH":null,"AVSADDR":null,
"AVSZIP":null,"IAVS":null,"CARDSECURE":null
}


  HTTP方法设计
  最后,必须决定使用哪些HTTP方法操作资源及其功能。一定要坚持这些HTTP方法的正规用法,不要偏离规范。例如,GET应该是安全的只读幂等(idempotent)调用,它不应该以任何方式更改资源的状态。违反这条原则会增加复杂性,给客户机带来混乱。在这个示例中,因为希望对单一交易的状态执行只读查询,显然应该使用GET方法,使用的URI模式见 清单 4。
  清单 4. 交易服务示例URI模式
   
以下是引用片段:
/transactions{id}
  每个GET调用返回一个JSON格式的字符串,这是查询的交易的状态数据,见 清单 5。
  清单 5. 包含交易ID的GET请求
   
以下是引用片段:
GET /transactions/V19A2A192BE9 HTTP/1.1


  但是,这种查询交易状态的模型有一个问题:服务无法验证查询交易的用户是否确实是交易的所有者。为了解决这个问题,允许客户机在URI中作为查询参数传递登录凭证,见 清单 6。
  清单 6. 在查询字符串中包含安全凭证的GET请求
   
以下是引用片段:
GET /transactions/V19A2A192BE9?user=winktest&vendor=winktest
    &partner=PayPal&pwd=wink123
HTTP/1.1


  Apache Wink服务实现
  Apache Wink服务实现为POJO(即普通的Java类),它使用JAX-RS注释把HTTP请求映射到Java方法。在默认情况下,服务可以是单实例的,也可以为每个请求创建服务实例。在这个示例中,通过创建TransactionResource类实现Apache Wink RESTful服务。它解析状态查询请求,验证用户凭证,调用Payflow网关服务,然后以JSON对象的形式返回交易的状态。清单 7 给出TransactionResource类的代码片段。
  清单 7. Apache Wink服务Java类片段
   
以下是引用片段:
package org.openengine.wink.example.payflow;
import ...;
 
@Path("/transactions")
public class TransactionResource {   
 
@GET
@Path("{pnref}")
@Produces(MediaType.APPLICATION_JSON)
public JSONObject doInquiry(@PathParam("pnref") String pnref,  
    @QueryParam("user") String userName, 
    @QueryParam("vendor") String vendorName, 
    @QueryParam("partner") String partnerName,
    @QueryParam("pwd") String password) {
  try {
   return getTxnStatus(pnref, 
  userName, vendorName, 
  partnerName, password);
 
  } catch (JSONException e) {
  throw new WebApplicationException
  (Response.Status.INTERNAL_SERVER_ERROR);
  }

....


  @javax.ws.rs.Path注释指出这个类是JAX-RS服务。所有JAX-RS服务都需要这个注释。@Path 注释的值 /transactions 指出交易服务的URI的相对路径。
  @GET注释指出这个方法本身映射到的HTTP动词。方法级@Path注释的值相对于主URI指定子根。方法级@Path和@PathParam中的{pnref}表示交易的惟一ID。例如,如果URI是 /transactions/V19A2A192BE9,V19A2A192BE9字符串会被注入getTxnStatus方法的{pnref}参数中。
  @javax.ws.rs.QueryParam 注释与@PathParam相似,但是它把各个URI查询参数注入Java参数中,见 清单 8。

  清单 8. 包含查询参数的URI
   
以下是引用片段:
/transactions/V19A2A192BE9?user=winktest&vendor=winktest&partner=PayPal&pwd=wink123


  Apache Wink服务配置
  Apache Wink应用程序通常打包为WAR文件,部署在Apache Tomcat等servlet容器中。与其他Web应用程序一样,Apache Wink服务也需要一个web.xml文件。清单 9 给出示例Apache Wink服务的web.xml文件的内容。
  清单 9. web.xml Web配置文件
   
以下是引用片段:
<web-app>
<display-name>Wink demo</display-name>
<description>Demonstration of SDK features</description>
<!-- Wink SDK servlet configuration. 
  This servlet handles HTTP requests
  of SDK web service on application server.-->
    
<servlet>
  <servlet-name>restSdkService</servlet-name>
  <servlet-class>
   org.apache.wink.server.internal.servlet.RestServlet
  </servlet-class>
  <init-param>
   <param-name>applicationConfigLocation</param-name>
   <param-value>/WEB-INF/application</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>restSdkService</servlet-name>
  <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>


  可以看到web.xml文件中定义了Apache Wink RestServlet和它的url-pattern。还有RestServlet的初始化参数,它指向/WEB-INF/application目录中的一个文件。这个文件包含JAX-RS应该部署的所有类和对象的列表。您不需要这个配置文件,可以让应用程序类以编程方式列出服务实现的资源,但是这个示例使用应用程序配置文件的方式,见 清单10。
  清单 10. 应用程序配置文件
   
以下是引用片段:
org.openengine.wink.example.payflow.TransactionResource


  运行Apache Wink服务
  要想运行这个服务,首先必须在Tomcat上构建和部署应用程序。执行以下步骤:
  把PayFlow项目的内容解压到C驱动器上的一个文件夹。C:\PayFlow目录应该像 图 2 这样。

图 2. PayFlow 示例项目的目录结构
  把JAVA_HOME和ANT_HOME变量设置为自己的Java和Apache Ant安装目录。

  在系统变量PATH中添加JAVA_HOME/bin 和 ANT_HOME/bin。
  从C:\PayFlow目录运行Ant,从而对PayFlow项目执行Ant构建。
  这个步骤应该会构建PayFlow项目并创建文件PayFlow.war,见 图 3。

图 3. Ant 脚本构建的输出
  把PayFlow.war文件复制到TOMCAT主目录下的webapps目录中,见 图 4。

图 4. 在 Tomcat 服务器上部署 PayFlow 项目
  通过运行TOMCAT_HOME\bin文件夹中的startup.bat文件启动Tomcat Web服务器。
  启动您喜欢的浏览器,访问URI http://localhost:8080/PayFlow/rest/transactions/V19A2A192BE9?
  user=winktest&vendor=winktest&partner=PayPal&pwd=wink123>(假设Tomcat Web服务器配置为监听端口8080)。
  浏览器应该会提示您保存文件 V19A2A192BE9,其中包含JSON格式的交易状态,见 图 5。

图 5. 浏览器保存文件窗口,保存包含交易状态的JSON文件
  结束语
  本文简要介绍了REST架构和JAX-RS Java标准(这个标准用于简化RESTful服务实现)的基本知识。然后讨论了新的Apache Wink 1.0框架,这是一个完全兼容的容易使用的JAX-RS 1.0规范实现。介绍了Apache Wink的底层架构,然后设计和实现了一个新的示例Apache Wink Web服务,讨论了部署和运行它所需的步骤。

你可能感兴趣的:(企业应用)