设为首页 收藏本站
查看: 1009|回复: 0

[经验分享] 使用 Apache Wink、Eclipse 和 Maven 开发 RESTful Web 服务

[复制链接]

尚未签到

发表于 2017-1-10 09:02:37 | 显示全部楼层 |阅读模式
  http://www.ibm.com/developerworks/cn/web/wa-useapachewink/
  Apache Wink 是一个促进创建和使用 REST Web 服务的 Apache 孵化器项目。通过 REST Web
服务,客户机和服务之间的交互局限于一组预定义的操作,客户机和服务器之间的交互的复杂性限制为客户机和服务之间交换的资源表示。这种方法支持构建可互操
作、可伸缩、可靠的、基于 REST 的分布式超媒体系统。


常用缩略词



  • API:
    应用程序编程接口

  • HTTP:
    超文本传输协议

  • IDE:
    集成开发环境

  • JSON:
    JavaScript 对象符号

  • REST:
    具象状态传输

  • URI:
    统一资源标识符

  • XML:
    可扩展标记语言




  本文介绍如何使用 Apache Wink、Eclipse IDE 以及 Maven 项目管理工具开发、部署和运行 RESTful Web 服务。

  Web 服务的 REST 方法

  设计 Web 服务的 REST 方法将客户机和服务之间的交互限制到一组创建、读取、更新和删除(CRUD)操作。这些操作直接映射到 HTTP 方法 — 具体而言,映射到
POST
、GET

PUT
和 DELETE
。尽管 RESTful 样式没有绑定到 HTTP 协议,本文假设 HTTP 用于客户机和服务之间的通信。

  REST Web 服务在资源上执行 CRUD 操作。客户机使用资源状态的 REST 服务表示进行交换。这些表示使用的数据格式在
HTTP 请求或响应的头部中指定 — XML 和 JSON
是广泛使用的格式。数据格式可能在不同操作之间发生变化;例如,创建资源的数据格式与用于读取资源的数据格式不同。REST 服务保持资源的状态,但 —
与 servlets 不同的是 — 不保持客户机会话信息。

  REST 方法支持构建可互操作、可伸缩和可靠的基于 REST 的分布式系统。例如,GET
、POST
和 DELETE
方法是等幂的,即多次执行它们与执行一次的结果相同。
由于 GET
操作不会更改资源的状态,因此 GET
请求的结果可以缓存起来以加快 “请求-响应” 循环。

  JAX-RS 为基于 HTTP 协议的 RESTful Java Web 服务定义了一个 API。JAX-RS 实现包括 Apache Wink、Sun Jersey 和 JBoss RESTEasy。

本文将使用 Apache Wink。

  JAX-RS 利用 Java 注释的威力,使用注释来执行诸如以下的操作:



  • 将 HTTP 方法和 URIs 绑定到 Java 类的方法
  • 将来自 URI 或 HTTP 头部的元素作为方法参数注入
  • 在 HTTP 消息体和 Java 类型之间来回转换
  • 将 URI 模式绑定到 Java 类和方法 —
    @Path
    注释
  • 将 HTTP 操作绑定到 Java 方法 —
    @GET
    、 @POST
    、@PUT
    和 @DELETE
    注释
  JAX-RS 还提供了一个框架来构建新功能。例如,对于自定义数据格式,程序员可以开发消息阅读器并将 Java 对象编组到 HTTP 消息并从 HTTP 消息解组它们。

  在本文中,您将使用 Eclipse 和 Maven 下载 Apache Wink,运行 Apache Wink 中包含的 HelloWorld 示例,然后将您自己的 REST Web 服务创建为一个 Eclipse 项目。





回页首

  通过 Eclipse 获取 Apache Wink

  在这个小节中,您将使用 Eclipse 以及 Maven Integration for Eclipse(称为 m2eclipse)和 Subclipse 插件来安装 Apache
Wink。(M2eclipse 提供从 Eclipse 对 Maven 的访问;Subclipse 提供对 Subversion 资源库的访问。)您还可以将 Eclipse 用作一个平台,从这个平台构建并运行 Web 服务。

  先决条件

  在获取 Apache Wink 之前,要先下载并安装以下软件包(参见 参考资料
获取下载 URLs):




  • Java Software Development Kit (JDK) version 6。
    设置 JAVA_HOME 环境变量并添加到路径
    %JAVA_HOME%\bin(在 Windows® 中)或
    $JAVA_HOME/bin(在 Linux® 中)。

  • Apache Tomcat version 6.0。
    设置 CATALINA_HOME 环境变量以指向安装目录。

  • Eclipse IDE for Java™ Platform, Enterprise Edition (Java EE)
    developers。

    本文撰写之时的当前版本为 Eclipse
    Galileo。
  安装 Subclipse

  要使用 Eclipse 管理具有 Maven 感知的项目,要安装 Eclipse 插件 Subclipse
和 m2eclipse。要安装 Subclipse 插件,执行以下步骤:



  • 启动 Eclipse。
  • 单击菜单栏中的 Help
    ,然后选择 Install new
    software


  • Available Software
    窗口中,单击 Add

  • Add Site
    窗口中,输入:


         Name:     Subclipse
    Location: http://subclipse.tigris.org/update_1.6.x/



      然后单击 OK


  • Available Software
    窗口中,选择 Subclipse
    下的 Subclipse
    (Required)

    SVNKit Client Adapter (Not required)
    复选框(如 图 1
    所示),然后单击 Next



    图 1. 安装 Subclipse 插件

    DSC0000.jpg
  • Install Details
    窗口中,单击 Next

  • Review Licenses
    窗口中,检查许可,接受许可协议条款,然后单击 Finish

  • 单击 Yes
    重新启动 Eclipse。
  安装 m2eclipse

  m2eclipse 插件的安装步骤与安装 Subclipse 插件类似,但有以下几点例外:



  • Add Site
    窗口中输入:


         Name:     Maven Integration for Eclipse
    Location: http://m2eclipse.sonatype.org/update/



      然后单击 OK


  • Available Software
    窗口中,选择 Maven Integration
    for Eclipse (Required)

    Maven SCM handler for Subclipse
    (Optional)

    复选框(如 图 2
    所示),然后单击 Next



    图 2. 安装 m2eclipse 插件

    DSC0001.jpg
  获取 Apache Wink

  现在,您可以使用 Eclipse 从资源库检查 Apache Wink 示例,将必要的 Java 归档(JAR)文件(包括 Apache Wink JAR 文件)下载到一个本地资源库,构建并运行 Apache Wink
HelloWorld 示例。为此,执行以下步骤:



  • 在 Eclipse 中,选择 File > Import
    启动 Import Wizard。
  • Select
    向导页面的 Select and import source
    文本框中输入 maven

  • Maven
    下,选择 Materialize Maven Projects
    并单击 Next

  • Select Maven artifacts
    向导页面上单击 Add

  • Add Dependency
    页面上的 Enter groupId, artifactId
    文本框中输入 org.apache.wink.example

    注意:
    Artifact(工件) 是一个用于 Maven 的术语,指的是设置了版本并存储在资源库中的软件包的层级结构。
  • Search Results
    区域中,选择 org.apache.wink.example apps
    (如 图 3
    所示)并单击 OK



    图 3. org.apache.wink.example 组中的应用程序工件

    DSC0002.jpg
  • Select Maven artifacts
    向导页面上,单击 Next
    ,然后单击 Finish

  • Maven Projects
    向导页面上,只选择 /pom.xml
    复选框,然后单击 Finish

  Maven 处理一个工件的所有依赖项的方式是从远程资源库下载它们并构建一个本地资源库。Maven 的优势之一是能够处理临时依赖项;因此,在 Maven Project
Object Model (POM) 文件中,只需声明工件的传递依赖项(transitive dependencies),Maven 将为您处理高阶依赖项(higher-order dependencies)。

  步骤 8 完成后,将创建一个 Eclipse 项目,它包含 Apache Wink 示例的 apps
模块中的代码。在 Eclipse 的 Project Explorer 中浏览项目文件。





回页首

  Apache Wink HelloWorld 服务

  我们来检查一下 apps
模块中的 HelloWorld
Java 类。在 Project Explorer 视图中,单击 apps > HelloWorld > src > main
,然后打开文件 HelloWorld.java,该文件的结构如 清单 1
所示。

  

清单 1. HelloWorld.java 文件




package org.apache.wink.example.helloworld;
...
@Path("/world")
public class HelloWorld {
public static final String ID = "helloworld:1";
@GET
@Produces(MediaType.APPLICATION_ATOM_XML)
public SyndEntry getGreeting() {
SyndEntry synd = new SyndEntry(new SyndText("Hello World!"), ID, new Date());
return synd;
}
}

  HelloWorld 是一个 JAX-RS 资源(或服务),正如其类定义前面的 @Path("/world")
注释所示。字符串 "/world"
是该资源的相对根 URI。JAX-RS 将匹配相对 URI
"/world"
的 HTTP 请求路由到
HelloWorld
类的方法。

  HelloWorld
类的惟一方法 —
getGreeting
— 拥有一个 @GET
注释,表示它将服务于 HTTP GET
请求。

  @Produces(MediaType.APPLICATION_ATOM_XML)
注释表明 HTTP 响应的媒体类型 — 即,HTTP 响应头部中的
Content-Type
字段的值。

  与相对 URI "/world"
关联的绝对 URI 由部署描述符 web.xml
中的设置决定,这个部署描述符驻留在 HelloWorld/src/main/webapp/WEB-INF 中,如 图 4
所示。

  

图 4. HelloWorld 应用程序的部署描述符


DSC0003.jpg
  注意,URI 模式 /rest/*
被绑定到
restSdkService
servlet,这个 servlet 的 context path 是 HelloWorld
,由 HelloWorld/pom.xml 文件中的 <finalName>
元素定义。这样,HelloWorld
资源的绝对 URI 是:



     http://host:port/HelloWorld/rest/world

  图 4
中的 servlet 名称 restSdkService
引用 org.apache.wink.server.internal.servlet.RestServlet
Apache Wink 类,如图中的 <servlet>
元素所示。RestServlet
类使用初始参数 applicationConfigLocation
传递 HelloWorld
类的名称,这个初始参数反过来指向位于 HelloWorld/src/main/webapp/WEB-INF 文件夹中的 web.xml 旁边的 application 文件。这个 application 文件只有一行,即
HelloWorld
资源的限定名:



org.apache.wink.example.helloworld.HelloWorld

  RestServlet
servlet 可以在 “无 JAX-RS 感知” 的
servlet 容器中运行,从而支持将 JAX-RS 服务轻松部署到 “无 JAX-RS 感知” 的容器中。

  我们现在开始构建 HelloWorld 服务,然后将其部署到 Tomcat 6.0
servlet 容器中并运行。

  构建 HelloWorld

  在 Eclipse 中,可以使用 m2eclipse 插件来构建、部署和运行 HelloWorld。首先,编译源代码并为 HelloWorld 服务构建 Web 归档 (WAR) 文件。要构建这个服务,指示 m2eclipse 执行安装
生命周期阶段。(执行一个 Maven 生命周期阶段将触发项目生命周期中的此前阶段的执行。)要执行安装阶段,在 Project Explorer 视图中右键单击 HelloWorld,然后单击
Run As > Maven install
,如 图 5
所示。

  

图 5. 执行
Maven 安装阶段


DSC0004.jpg
  Maven (从中央资源库
http://repo1.maven.org/maven2 或从镜像资源库)下载所有依赖项,并在 Windows® 中的
%HOMEPATH%\.m2\repository 或 Linux® 中的 $HOME/.m2/repository
下构建本地资源库。Maven 执行的动作记录在 Eclipse 窗口的 Console 视图中。

  如果安装阶段成功结束,那么 WAR 文件 HelloWorld.war 就构建在目标目录下并部署到本地资源库中,Console 视图将显示消息 “Build successful”。

  将 HelloWorld 部署到 Tomcat

  您将使用 Maven 的 Tomcat 插件。(与 Eclipse 一样,Maven 通过插件提供大量功能。)您必须将 Tomcat 插件的位置告知 Maven,方法是指定插件的 groupId
和 artifactId
,如 图 6
所示(pom.xml 中的 45-46 行)。

  

图 6. Tomcat Maven 插件

DSC0005.jpg
  您还需要告知 Maven 用于访问 Tomcat manager 应用程序的用户名和密码。Maven 使用 manager 应用程序来指导 Tomcat 部署或取消部署一个 Web 应用程序。按照以下步骤告知 Maven 身份验证信息:



  • 声明 tomcat-maven-plugin
    工件的一个 Tomcat 服务器配置 — 称为 tomcat-localhost
    ,如
    图 6
    所示(pom.xml 中的 47-49 行)
  • 在 Maven 设置文件 settings.xml(位于 Windows 的 %HOMEPATH%\.m2\ 或 Linux 的 $HOME/.m2 下)中定义这个配置,如 清单 2
    所示。



    清单 2. Maven settings.xml 文件



    <?xml version="1.0" encoding="UTF-8"?>
    <settings
    xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
    http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
    <server>
    <id>tomcat-localhost</id>
    <username>admin</username>
    <password>admin</password>
    </server>
    </servers>
    </settings>


  现在可以将这个服务部署到 Tomcat 了,方法是执行 Tomcat 插件的
redeploy
目标。(一个 Maven 目标(goal) 被自身执行,这与生命周期阶段不同,后者的执行由生命周期中的此前阶段自动推进。)要执行 redeploy 目标,执行以下步骤:



  • 在 Tomcat 配置文件 conf/tomcat-users.xml(位于 CATALINA_HOME 下)中插入身份验证信息(如 图 7
    所示),但要使用一个密码,而不是 admin



    图 7. Tomcat 身份验证配置

    DSC0006.jpg
  • 通过运行以下命令启动 Tomcat:


    In Windows:   %CATALINA_HOME%\bin\catalina.bat start
    In Linux:     $CATALINA_HOME/bin/catalina.sh start


  • 执行 maven tomcat:redeploy
    ,这条命令使用 Tomcat manager 应用程序将 HelloWorld.war 部署到 Tomcat。为此,执行以下步骤:

    • 在 Project Explorer 视图中,右键单击 HelloWorld,然后单击 Run As > Run configurations

    • Create, manage, and run configurations
      窗口中,选择 Maven Build > New_configuration
      ,然后单击 Main
      选项卡(参见 图 8
      )。


      图 8. 运行
      tomcat:redeploy 目标


      DSC0007.jpg
    • 单击 Browse workspace
      ,然后选择 apps > HelloWorld
      ,然后单击 OK

    • Goals
      文本框中,输入 tomcat:redeploy
      ,然后单击 Run
      。  如果 redeploy 目标成功执行,Console 视图将显示消息 “Build successful”。




  现在,您可以使用一个 HTTP 客户机(比如 Curl)调用 HelloWorld 服务,如 清单 3
所示。

  

清单 3. 在 Curl 中调用 HelloWorld 服务




$ curl -X GET  http://localhost:8080/HelloWorld/rest/world
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:ns2="http://a9.com/-/spec/opensearch/1.1/"
xmlns:ns3="http://www.w3.org/1999/xhtml">
<id>helloworld:1</id>
<updated>2010-01-06T13:26:43.924+01:00</updated>
<title type="text">Hello World!</title>
</entry>





回页首

  开发一个 REST Web 服务

  在这个小节中,您将从头开始创建一个 REST Web 服务来管理一个图书资源集合。这个 REST 服务的源代码可以从下面的 下载
表中获取。

  开发这样一个服务的关键步骤是:


  • 定义资源的 URIs,用于操作资源的方法,以及每个方法的数据格式。
  • 定义表示图书资源的 Java 对象,提供 Java 代码或注释来编组和解组 Java 对象。
  • 定义将 URIs 和 HTTP 方法绑定到 Java 方法的 Java 服务。
  • 提供 javax.ws.rs.core.Application
    抽象类的一个具体子类。
  下面我们就执行这些步骤。
  将路径和 HTTP 方法绑定到 Java 方法

  这个服务支持 GET
, POST
、PUT
和 DELETE
HTTP
方法,并按如下方式将 HTTP 请求映射到 Java 方法:



  • 将 POST /books
    请求映射到带有 createBook(@Context UriInfo, Book)
    签名的 Java 方法。(@Context
    注释将在 JAX-RS Web 服务
    小节中介绍。)用于创建一个图书资源的数据格式为:


         POST /books HTTP/1.1
    Content-Type: application/xml
    <book>
    <title> ... </title>
    <isbn> .... </isbn>
    </book>


  • 将 GET /books
    请求映射到 Java 方法 getBook()
    。用于获取图书资源的数据格式为:


         GET /books HTTP/1.1
    Content-Type: application/xml


  • 将 GET /books/{id}
    请求映射到带有 getBook(@PathParam("id") int)
    签名的 Java 方法。(@PathParam
    注释将在 JAX-RS Web 服务
    小节中介绍。)用于获取带有 URI 模式 /books/{id}
    的图书资源的数据格式为:


         GET /books/{id} HTTP/1.1
    Content-Type: application/xml


  • 将 PUT /books/{id}
    请求映射到带有 updateBook(@PathParam("id") int, Book)
    签名的 Java 方法。用于更新带有 URI 模式 /books/{id}
    的图书资源的数据格式为:


         PUT /books/{id} HTTP/1.1
    Content-Type: application/xml
    <book>
    <title> ... </title>
    <isbn> .... </isbn>
    </book>


  • 将 DELETE /books/{id}
    请求映射到带有 deleteBook(@PathParam("id") int)
    签名的 Java 方法。用于删除带有 URI 模式 /books/{id}
    的图书资源的数据格式为:


         DELETE /books/{id} HTTP/1.1
    Content-Type: application/xml


  图书的对象模型

  用于实现这个图书集合的 Java 对象模型有 3 个类:



  • Book
    ,如 清单 4
    所示。

  • BookList
    ,如 清单 5
    所示。

  • Link
    ,如 清单 6
    所示。
  

清单 4. Book 类




package com.ibm.devworks.ws.rest.books;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="book")
@XmlAccessorType(XmlAccessType.FIELD)
public class Book {
@XmlAttribute(name="id")
private int id;
@XmlElement(name="title")
private String title;
@XmlElement(name="isbn")
private String ISBN;
@XmlElement(name = "link")
private Link link;
public Book() { }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getISBN() { return ISBN; }
public void setISBN(String ISBN) { this.ISBN = ISBN; }
public Link getLink() { return link; }
public void setLink(String uri) { this.link = new Link(uri); }
}

  在 Book
类中,您使用 Java Architecture for XML Binding
(JAXB) 注释来执行 Java 对象的编组和解组。Apache
Wink 自动编组和解组带有 JAXB 注释的 Java 对象,包括创建执行编组和解组工作的 Marshaller

Unmarshaller
实例。

  您将使用 BookList
类来表示图书对象的集合,BookList
类将这些对象以内部存储方式存储在 ArrayList
类型的一个字段中,ArrayList
带有 JAXB 注释,以便转换为 XML 格式。

  

清单 5. BookList 类




package com.ibm.devworks.ws.rest.books;
import java.util.ArrayList;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElementRef;
@XmlRootElement(name="books")
public class BookList {
@XmlElementRef
ArrayList<Book> books;
public BookList() {  }
public BookList( Map<Integer, Book> bookMap ) {
books = new ArrayList<Book>( bookMap.values() );
}
}

  您将使用 Link
类将链接元素插入到图书对象的 XML 表示中(参见 清单 6
)。

  

清单 6. Link 类




package com.ibm.devworks.ws.rest.books;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@XmlRootElement(name="link")
@XmlAccessorType(XmlAccessType.FIELD)
public class Link {
@XmlAttribute
String href = null;
@XmlAttribute
String rel = "self";
public Link() { }
public Link( String uri) {
this.href = uri;
}
public Link( String href, String rel) {
this.href = href;
this.rel = rel;
}
}

  JAX-RS Web 服务

  现在,您已经定义了将 URIs 和 HTTP 方法绑定到 Java 方法的 Java 服务。您可以将这个服务定义为一个 Java 接口或一个类;对于前者,还需要定义实现接口的类。在接口中,您本地化 JAX-RS 注释并添加一个类来实现接口。

  清单 7
展示了 BookService
Java 接口。@javax.ws.rs.Path
注释将这个接口指定为一个 JAX-RS 服务。注释的 /books
值定义这个服务的相对根 URI。注释 @javax.ws.rs.POST
、@javax.ws.rs.GET
、@javax.ws.rs.PUT
和 @javax.ws.rs.DELETE
将 HTTP POST
、GET
、PUT
和 DELETE
操作绑定到紧随其后的 Java 方法。

  

清单 7. BookService 接口




package com.ibm.devworks.ws.rest.books;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
@Path("/books")
public interface BookService {
@POST
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response createBook(@Context UriInfo uriInfo, Book book);
@GET
@Produces(MediaType.APPLICATION_XML)
public BookList getBook();
@Path("{id}")
@GET
@Produces(MediaType.APPLICATION_XML)
public Book getBook(@PathParam("id") int id);
@Path("{id}")
@PUT
@Consumes(MediaType.APPLICATION_XML)
public void updateBook(@PathParam("id") int id, Book book_updated);
@Path("{id}")
@DELETE
public void deleteBook(@PathParam("id") int id);
}

  对于其 URI 与接口的 @PATH("/books")
注释指定的值不同的方法,您将一个特定的 @PATH
注释附加到那些方法。@PATH
注释是可以累积的,即,一个路径表达式后面的另一个路径表达式将附加到前面的表达式。因此,绑定到 deleteBook
方法的路径模式为 /books/{id}


  JAX-RS 提供了一种机制,用于从一个 HTTP 请求提取信息,将信息赋予一个 Java 对象,然后将该对象注入一个 Java 方法参数。这种机制称为注入(injection)。注入使用 Java 注释指定。在 BookService
接口中,您将插入两个注入注释:




  • @Context
    注释从 HTTP 请求提取 URI 信息,将其转换为 UriInfo
    对象,然后将这个对象作为方法参数 uriInfo
    注入。

  • @PathParam("id")
    注释匹配前面的 @Path({"id"})
    注释。这个注释从 URI 模式 /books/{id}
    提取 {id}
    ,并将其注入 getBook
    方法的 id
    参数的值。
  注意,BookService
的方法将 Java 对象(比如 Book
)接收为参数并返回 Java 对象;这是可能的,因为这些对象带有 JAXB 注释,因此 Apache Wink 能够对它们进行自动编组和解组。

  清单 8
展示了实现 BookService
的类的结构。BookServiceImpl
是一个 singleton 类,使用一个内存映射图(in-memory map)来维护图书对象集合。singleton 实例使用多线程服务并发请求,因此它必须是线程安全的(thread-safe)。

  

清单 8. BookService 实现类




package com.ibm.devworks.ws.rest.books;
import javax.ws.rs.*;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@Path("/books")
public class BookServiceImpl implements BookService {
private static BookServiceImpl instance = null;
private BookServiceImpl() {  }
public synchronized static BookServiceImpl getInstance() {
if(instance == null) {
instance = new BookServiceImpl();
}
return instance;
}
private Map <Integer, Book> bookMap =
new ConcurrentHashMap <Integer, Book>();
private AtomicInteger seqNumber = new AtomicInteger();
public Response createBook(@Context UriInfo uriInfo, Book book)
throws WebApplicationException {
...
}
public BookList getBook() {
...
}
public Book getBook(@PathParam("id") int id)
throws WebApplicationException {
...
}
public void updateBook(@PathParam("id") int id, Book book_updated)
throws WebApplicationException {
...
}
public void deleteBook(@PathParam("id") int id)
throws WebApplicationException {
...
}
}

  图书集合存储在一个映射图中。要提供对这个映射图的线程安全访问,您将使用一个 ConcurrentHashMap
。要生成惟一的图书 IDs,您将使用一个 AtomicInteger
,它能确保增量操作是原子级的(atomic),从而确保线程安全。

  设置 Application 抽象类的子类

  JAX-RS Web 应用程序包含一组资源(REST Web 服务),这些资源作为 JAX-RS 抽象类 javax.ws.rs.core.Application
的子类出现。清单 9
中显示的 BookWebApp
类扩展了 Application
类。

  

清单 9. javax.ws.rs.core.Application 的具体子类




package com.ibm.devworks.ws.rest.books;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class BookWebApp extends Application {
private Set<Object> svc_singletons = new HashSet<Object>();
private Set<Class<?>> svc_classes  = new HashSet<Class<?>>();
public BookWebApp() {
svc_singletons.add(BookServiceImpl.getInstance());
}
@Override
public Set<Object> getSingletons() {
return svc_singletons;
}
@Override
public Set<Class<?>> getClasses() {
return svc_classes;
}
}

  BookWebApp
的构造函数获取这个图书服务实现对象的 singleton 实例。getSingletons
方法返回一个组,其惟一元素就是这个 singleton。JAX-RS 在服务一个请求后并不删除这个 singleton。





回页首

  构建和部署 REST Web 服务

  您将使用 Eclipse 来创建一个动态 Web 项目,这个项目包含上一小节介绍过的 Java  类和其他资源,比如 Web 应用程序部署描述符和必要的 JAR 文件。

  注意:
创建一个 Eclipse 动态 Web 项目的另一种方法是从一个 archetype(比如 maven-archetype-webapp
或 webapp-jee5
)创建一个Maven 项目(archetype 是一个 Maven
项目模板)。但是,在 Maven 当前版本中,生成 Eclipse 使用的项目元数据时会出现一些问题:要支持 IDE
中的自动代码构建,必须手动修改一些 Eclipse 项目文件。因此,本文使用 Eclipse 动态 Web 项目。

  Web 服务的 Eclipse 项目

  Eclipse 动态 Web 项目支持开发在一个 servlet 容器中运行的 Web 应用程序,因此它是用于开发 Apache
Wink 服务的一个不错的项目模板。要为这个图书 REST 服务创建一个动态 Web 项目,执行以下步骤:



  • 在 Eclipse 中,单击 File > New > Dynamic Web Project

  • 在 Dynamic Web Project Wizard 中,在 Project name
    文本框中输入 Books

  • 单击 Target runtime
    方框旁边的 New
    创建一个 Tomcat 运行时。
  • New Server Runtime Environment
    向导页面上,单击
    Apache > Apache Tomcat v6.0
    ,然后单击 Next

  • Tomcat Server
    向导页面上,单击 Browse
    ,然后导航到 先决条件
    小节中定义的 CATALINA_HOME 目录。
  • 单击 OK
    ,然后单击 Finish

  • Dynamic Web Project
    页面上,单击 Finish

  将上一小节中介绍的 Java 类添加到刚才创建的 Books 项目中。为此,执行以下步骤:



  • 在 Project Explorer 视图中,打开 Books 文件夹。右键单击
    Java Resources:src
    ,然后单击 New > Package

  • Java Package
    窗口中的 Name
    文本框中,输入包名称 —
    com.ibm.devworks.ws.rest.books
    — 并单击 Finish

  • 将 Java 类添加到 com.ibm.devworks.ws.rest.books
    包:

    • 在 Project Explorer 视图中,右键单击上述包,然后单击 New > Class

    • Name
      文本框中,输入类名称(比如为 Book.java
      输入 Book
      ),然后单击 Finish

    • 使用 Eclipse Java 编辑器来创建类。


  然后,向项目添加构建和运行一个 Apache Wink 服务所需的 JAR 文件。当您创建这个应用程序项目时,Maven 将 JAR
文件下载到本地资源库,本地资源库驻留在 %HOMEPATH%\.m2\repository(Windows)或
$HOME/.m2/repository(Linux)中。

  要将 JAR 文件添加到这个项目,执行以下步骤:


  • 在 Project Explorer 视图中,导航到 Books/Web Content/WEB-INF。
  • 右键单击 lib
    ,然后单击 Import > General > File System
    ,然后单击 Next

  • File System
    窗口中,从 Maven 资源库(已在导入应用程序 Apache Wink 模块时由 m2eclipse 填充)导入 JAR 文件 jsr311-api-1.0.jar,方法是导航到包含这个 JAR 文件的目录,然后单击 OK
    。在 File System
    窗口中,选中这个 JAR 文件,然后单击 Finish

  • 重复步骤 2 到步骤 3,分别导入 JAR 文件 wink-server-1.0-incubating.jar、
    wink-common-1.0-incubating.jar、slf4j-api-1.5.8.jar 和
    slf4j-simple-1.5.8.jar。
  所有库都导入后,lib 目录将包含如 图 9
所示的 JAR 文件。

  

图 9. 一个 Apache Wink 服务所需的库

DSC0008.jpg
  您还可以通过从下面的 下载
部分中提供的代码样例中导入 Book 服务来创建这个 Eclipse 项目。为此,下载并解压文件,然后在 Eclipse 中单击 File > Import > Existing
Project Into Workspace

。在 Import Projects Wizard 中,单击 Browse
,
导航到 Books 文件夹,单击 OK
,然后单击 Finish


  将服务部署到 Tomcat

  在部署描述符文件 web.xml(如 清单 10
所示)中,您将带有相对根路径 /* 的 URIs 映射到 Wink servlet
org.apache.wink.server.internal.servlet.RestServlet
。RestServlet
被传递为 init-param
,这是 Books 服务提供的 Application
子类的名称。

  

清单 10. BookService 部署服务描述符 web.xml




<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
<display-name>Book Web Application</display-name>
<servlet>
<servlet-name>restSdkService</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.ibm.devworks.ws.rest.books.BookWebApp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>restSdkService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

  部署描述符设置好后,就可以将这个 Books 服务部署到 Tomcat 了。为了进行测试,将这个 Books 服务部署到一个由 Eclipse 托管的 Tomcat 实例中并运行。为此,执行以下步骤:



  • 在 Project Explorer 视图中,右键单击 Books
    ,然后单击
    Run As > Run on Server

  • Run on Server
    窗口中,单击 Finish
    ,这将把这个 Books 服务部署到创建这个 Books 项目时配置的 Tomcat 运行时中并启动 Tomcat。
  测试完成后,您将这个 Books 服务打包到一个 WAR 文件中,以备部署到生产环境中。为此,在 Project Explorer 视图中,右键单击 Books
,然后单击 Export > WAR file
。在 WAR Export Wizard 中,单击 Browse
,选择创建 WAR 文件的文件夹,然后单击 Save
Finish






回页首

  调用 REST Web 服务

  可以使用一个支持 HTTP 操作 GET
、POST
、PUT
和 DELETE
的 HTTP 客户机来调用这个 Books 服务。
清单 11
展示了如何使用 Curl 来调用这个服务。首先,您将得到所有图书的表示(最初没有图书);然后,您使用 jaxrs.xml 和 rest.xml 两个表示来创建两本图书;最后,您得到所有图书的表示和 id=2
的图书的表示。

  

清单 11. 调用 Books 服务




$ curl   -X GET  http://localhost:8080/Books/books
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<books/>

$ more Books\xml\jaxrs.xml
<?xml version="1.0" encoding="UTF-8"?>
<book>
<titleRESTful Java with JAX-RS</title>
<isbn>978-0-596-15804-0</isbn>
</book>
$ more Books\xml\rest.xml
<?xml version="1.0" encoding="UTF-8"?>
<book>
<title>RESTful Web Services</title>
<isbn>978-0-596-52926-0</isbn>
</book>

$  curl -H "Content-Type: application/xml" -T Books\xml\jaxrs.xml \
-X POST http://localhost:8080/Books/books
$  curl -H "Content-Type: application/xml" -T Books\xml\rest.xml \
-X POST http://localhost:8080/Books/books

$ curl   -X GET  http://localhost:8080/Books/books
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<books>
<book id="2">
<title>RESTful Web Services</title>
<isbn>978-0-596-52926-0</isbn>
<link rel="self" href="http://localhost:8080/Books/books/2"/>
</book>
<book id="1">
<title>RESTful Java with JAX-RS</title>
<isbn>978-0-596-15804-0</isbn>
<link rel="self" href="http://localhost:8080/Books/books/1"/>
</book>
</books>
$ curl   -X GET  http://localhost:8080/Books/books/2
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book id="2">
<title>RESTful Web Services</title>
<isbn>978-0-596-52926-0</isbn>
<link rel="self" href="http://localhost:8080/Books/books/2"/>
</book>





回页首

  结束语

  本文展示了如何联合使用几种技术来支持 Apache Wink REST Web 服务的开发、构建和部署。Java 注释的威力简化了开发工作。

  REST Web 服务支持应用程序交换链接数据。Tim Berners-Lee 先生预言,链接数据将改变 Web 的面貌。Bill
Burke 在他撰写的图书 RESTful Java with JAX-RS 中指出,通过将服务交互的复杂性限制为数据表示,REST Web
服务将服务组合性和重用提高到一个新的水平。

  本文仅仅涉及 Apache Wink 服务开发的皮毛,Apache Wink
的其他重要特性包括链接构建器、自定义消息体阅读器以及针对不受支持的数据格式的编写器。要深入了解 Apache Wink 框架,一定要看一看
Apache Wink 中包含的其他示例。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-326315-1-1.html 上篇帖子: apache网站各种包下载地址 下篇帖子: Apache中多任务并发处理机制研究
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表