您的位置:首页 > 运维架构 > Apache

使用 Apache Wink、Eclipse 和 Maven 开发 RESTful Web 服务

2011-04-27 14:15 681 查看
Apache Wink
是一个促进创建和使用
REST Web
服务的
Apache
孵化器项目。通过
REST
Web
服务,客户机和服务之间的交互局限于一组预定义的操作,客户机和服务器之间的交互的复杂性限制为客户机和服务之间交换的资源表示。这种方法支持构建可互操
作、可伸缩、可靠的、基于
REST
的分布式超媒体系统。

本文介绍如何使用 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


窗口中,输入:

5.

·

Name:
Subclipse

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

7.

然后单击 OK



8.

·

Available Software


窗口中,选择 Subclipse


下的 Subclipse
(Required)


SVNKit
Client Adapter (Not required)


复选框(如
图 1

所示),然后单击 Next



9.

·

图 1.
安装
Subclipse
插件


10.

·

Install Details


窗口中,单击
Next



11.

·

Review Licenses


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



12.

·

单击 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
插件


获取 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
组中的应用程序工件


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
应用程序的部署描述符


注意,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

安装阶段


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
插件


您还需要告知 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
身份验证配置


通过运行以下命令启动
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
目标


单击 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和
DELETEHTTP
方法,并按如下方式将 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}")

@DELETEpublic 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
服务所需的库


您还可以通过从下面的




部分中提供的代码样例中导入
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
中包含的其他示例。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐