65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Jersey 2.x 构建 RESTFul Web 服务(第一部分)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (7投票s)

2015 年 11 月 27 日

MPL

8分钟阅读

viewsIcon

27125

downloadIcon

286

在本篇文章中,我将一步一步地向读者展示如何使用 Jersey 2.x 创建一个 RESTFul Web 服务。

引言

本教程是一个非常简单的教程,用于学习如何设置 Jersey 项目。本教程与网上的一些教程非常相似。它与其它教程的关键区别在于,本教程使用的是最新的 Jersey 库(2.x 版本),而不是旧版本(1.x)。您可能不知道的是,从 Jersey 2.0 开始,所有类都已重新组织到新的包中。正如您在这里看到的,如果您查看使用旧版本 Jersey 库的现有教程,当您升级到最新版本时会遇到问题。

如果您以前从未接触过 Jersey 库,那么这是一个让您亲身体验这些库的机会。再次强调,本教程使用的是最新版本的 Jersey。

背景

Jersey 究竟是什么?Jersey 是一个实现。它是 JAX-RS 规范的一个实现。您可以将 JAX-RS 想象成一组功能的抽象,这些功能描述了如何在 J2EE 容器中实现和执行 RESTful 服务。Jersey 框架由负责 Glassfish J2EE 容器的同一团队开发。似乎有很多公司使用它来开发生产服务。因此,了解它的一些知识是个好主意。

除了 Jersey 框架,还有 RestEasy(由负责 JBoss/Wildfly J2EE 容器的同一团队创建)和 Spring MVC 4.x(支持 RESTFul 服务开发)。RestEasy 是另一个 JAX-RS 实现。Spring MVC 4.x 则不是。我个人会尝试接触这两个框架,以扩展自己的视野。本教程呢?它只是向读者展示如何设置一个 Jersey 项目,进行编译、在模拟容器中运行和测试。

步骤 1 - 创建一个基于 Maven 的 Web 应用项目

第一步是使用 Maven 创建一个空项目。我不知道其他人怎么做,但我主要使用 Maven 来构建我的 Java 项目。我最喜欢的 Maven 功能之一是能够创建一个空项目,这样我就可以稍后向项目中添加类/资源。对于这个项目,我们需要创建一个空的 Web 应用项目。假设您已经在开发机上安装了 Apache Maven。要创建空白 Web 应用程序项目,请运行此命令:

mvn archetype:generate -DgroupId={project-packaging} -DartifactId={project-name} -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

您需要用项目的基本包名和项目名称替换上述命令中的 "{project-packaging}" 和 "{project-name}"。例如,我会这样做:

mvn archetype:generate -DgroupId=org.hanbo.jersey.sample -DartifactId=hanbo-jersey-sample -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

当我在命令提示符上运行上述命令时,我会看到以下输出:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype:
 maven-archetype-webapp:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.hanbo.jersey.sample
[INFO] Parameter: packageName, Value: org.hanbo.jersey.sample
[INFO] Parameter: package, Value: org.hanbo.jersey.sample
[INFO] Parameter: artifactId, Value: hanbo-jersey-sample
[INFO] Parameter: basedir, Value: C:\Users\hsun\workspace-ee\jerseysample
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\Users\hsun\workspace-ee\jerseysample\hanbo-jersey-sample
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.597s
[INFO] Finished at: Fri Nov 20 14:52:14 CST 2015
[INFO] Final Memory: 10M/24M
[INFO] ------------------------------------------------------------------------

输出完成后,您会在当前文件夹中看到一个新文件夹。目录结构将如下所示:

hanbo-jersey-sample
|_____src
       |_____main
              |_____resources
	      |_____webapp
	             |_____WEB-INF
	                    |_____web.xml
		     |_____index.jsp
|_____pom.xml

现在我们有了一个空的 Web 应用程序项目,是时候添加所有组件以使 Jersey RESTful 应用程序正常工作了。

步骤 2 - 修改 POM 文件

我要做的第一件事是修复我的 Maven 项目文件 pom.xml。我通常会添加所有必需的依赖项,添加一个生成构件的构建步骤(如果不存在),并添加一个 Jetty 插件,允许我通过 Maven 运行 Web 应用程序。本教程的修改非常少。这是修改后的 POM 文件:

<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.hanbo.jersey.sample</groupId>
  <artifactId>hanbo-jersey-sample</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Simple Jersey Sample Application</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-server</artifactId>
      <version>2.22.1</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>2.22.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>hanbo-jersey-sample</finalName>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>8.1.16.v20140903</version>
      </plugin>
    </plugins>
  </build>
</project>

您将无法分辨出修改之处。首先,我添加了 Jersey 的依赖项。这是一个简单的 Hello World 应用程序,因此只需要两个依赖项。它们是:

<dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-server</artifactId>
   <version>2.22.1</version>
</dependency>
<dependency>
   <groupId>org.glassfish.jersey.containers</groupId>
   <artifactId>jersey-container-servlet</artifactId>
   <version>2.22.1</version>
</dependency>

为什么使用这两个 jar 包将在本文后面解释。下一步是创建处理用户 RESTFul 请求的 Java 类。

步骤 3 - 创建基于 Jersey 的请求处理程序

为此,首先必须创建 Java 源文件夹。在 src/main 子文件夹下,创建以下文件夹结构:

src
|____main
      |____java
            |____org
	          |____hanbo
		        |____jersey
			      |____sample

您可以通过命令行或文件管理器执行此操作。目录结构 *org/hanbo/jersey/sample* 将是新类的包名。您可能已经猜到,在 sample 文件夹下,我们会放置一个 Java 文件。这个 Java 文件将是 RESTFul 请求的处理程序。我的 Java 文件名为“*HelloWorldService.java*”

这个 Java 文件的源代码如下:

package org.hanbo.jersey.sample;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;

@Path("/hello")
public class HelloWorldService
{
   @GET
   @Path("/{param}")
   public Response getMsg(@PathParam("param") String msg)
   {
      String output = "Jersey say : " + msg;
      return Response.status(200).entity(output).build();
   }
}

看起来很简单,不是吗?我们有一个名为 `HelloWorldServices` 的类。其中有一个名为 `getMsg` 的方法。两者都添加了一些注解。类名上的“`Path`”注解设置了请求的基路径。方法名上的“`Path`”注解是请求的子路径。请注意,子路径的值为“`{param}`”。这意味着路径的值是可以由方法接收以执行工作的某种值。如您在方法参数中看到的,还有一个“`PathParam`”注解,其值与 Path 注解相同。这意味着实际请求路径中“`{param}`”的任何值都将作为参数“`msg`”的值传递到方法中。暂时不用担心这些细节。一旦一切就绪,一个简单的测试将更好地展示这个类的工作方式。

 

下一步是修复 *web.xml*。完成此操作后,我们就准备好进行测试了。

步骤 4 - 修复 web.xml 部署描述符

我们使用 maven 创建了一个空白的 Web 应用程序 Java 项目。它自带了一个简单的 Web 应用程序部署描述符,即 *web.xml* 文件。此 web.xml 位于 *src/main/webapp/WEB-INF* 文件夹中。此文件的原始内容如下:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

它只有一个显示名称。它在容器的应用程序列表中用作显示名称。为了使我们的 Jersey Web 应用程序正常工作,我们需要添加一些新元素。让我列出内容:

<web-app id="JerseyHelloWorld" version="2.4"
   xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>hanbo-jersey-sample</display-name>
  
   <servlet>
      <servlet-name>jersey-servlet</servlet-name>
      <servlet-class>
         org.glassfish.jersey.servlet.ServletContainer
      </servlet-class>
      <init-param>
         <param-name>jersey.config.server.provider.packages</param-name>
         <param-value>org.hanbo.jersey.sample</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
      <servlet-name>jersey-servlet</servlet-name>
      <url-pattern>/rest/*</url-pattern>
   </servlet-mapping>
</web-app>

此文件可能看起来令人生畏。但实际上很简单。它包含两个部分:

  • 第一部分是 servlet 部分。Servlet 是一个接收用户输入并返回响应的 Java 类。在这种情况下,我们使用一个预定义的 servlet,名为“`org.glassfish.jersey.servlet.ServletContainer`”。更多信息稍后介绍。
  • 第二部分是 servlet 映射,此部分的作用是将 servlet 名称与特定的 URI 模式映射。基本上,来自 servlet 根目录的任何请求,如果与此 URI 模式匹配,都将路由到此处指定的 servlet名称。这将在测试部分中进行解释,该部分是下一个。

步骤 5 - 如何测试这个简单的 RESTFul Web 应用程序

在 pom.xml 中,我添加了 Jetty 插件,以便可以使用 Maven 运行我的 Jersey Web 应用程序。现在,我们已经将所有东西都整合在一起了。要运行它,请使用以下命令:

mvn jetty:run

如果一切顺利,您将看到以下输出:

......
[INFO] --- jetty-maven-plugin:8.1.16.v20140903:run (default-cli) @ hanbo-jersey-sample ---
[INFO] Configuring Jetty for project: Simple Jersey Sample Application
[INFO] webAppSourceDirectory not set. Defaulting to C:\Users\hsun\workspace-ee\jerseysample\hanbo-jersey-sample\src\main\webapp
[INFO] Reload Mechanic: automatic
[INFO] Classes = C:\Users\hsun\workspace-ee\jerseysample\hanbo-jersey-sample\target\classes
[INFO] Context path = /
[INFO] Tmp directory = C:\Users\hsun\workspace-ee\jerseysample\hanbo-jersey-sample\target\tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] web.xml file = file:/C:/Users/hsun/workspace-ee/jerseysample/hanbo-jersey-sample/src/main/webapp/WEB-INF/web.xml
[INFO] Webapp directory = C:\Users\hsun\workspace-ee\jerseysample\hanbo-jersey-sample\src\main\webapp
2015-11-25 22:11:11.443:INFO:oejs.Server:jetty-8.1.16.v20140903
2015-11-25 22:11:12.984:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one.
2015-11-25 22:11:22.141:WARN:oejsh.RequestLogHandler:!RequestLog
2015-11-25 22:11:22.403:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server

那么我们如何测试呢?RESTFul Web 应用程序的 URL 是:

https://:8080/rest/hello/{somevalue}

您可以将“{somevalue}”替换为任何字符串。然后按 Enter,您将看到以下输出:

Jersey say : {somevalue}

我是如何组合这个 URL 进行此测试的?这花了我一些时间才弄清楚:

  • 基 URL 始终是 *https://:8080*,这是 J2EE 容器的一个众所周知的特点。
  • URL 的下一部分是应用程序上下文根。在此示例应用程序中,我们使用了 Jetty,并且从未指定应用程序上下文根。因此,我们可以跳过它。
  • 还记得我添加了一个 servlet 映射,值为“/rest/*”吗?我们需要将其添加到 URL 中。URL 看起来像这样:*https://:8080/rest*
  • 当我们使用上述 URL 时,它将被路由到我们的 REST 请求处理程序类。但应该路由到哪个类?对于此示例应用程序,我们将 `HelloWorldService` 类注解为 `Path("hello")`,这意味着如果我们使用 URL:*https://:8080/rest/hello*,请求将被传递到我们的 `HelloWorldService`。
  • 在该类中,`getMsg` 方法有两个注解,第一个指定它将接受哪种类型的 HTTP 方法。在此示例中,`getMsg` 方法将处理任何 GET 请求。第二个注解指定另一个 Path。此路径指定可以作为参数传递给该方法的参数值。因此,我们可以尝试的最终 URL 是:*https://:8080/rest/hello/{somevalue}*。您可以将 `{somevalue}` 替换为您喜欢的任何字符串值。

本教程到此结束。

关注点

本教程的意义是什么?好吧,它为任何读者提供了一个开始构建 RESTFul Web 应用程序项目的机会。读者可以进一步扩展此项目,添加处理其他 HTTP 方法(如 POST、PUT 和 DELETE 操作)的其他类和类包。读者可以通过添加有意义的请求和响应类来转换项目,并通过 XML/JSON 查看请求/响应处理。

在我下一篇教程中,我将向读者展示如何处理 POST、PUT 和 DELETE 操作。我们将把测试从简单的基于浏览器的测试扩展到 PostMan。这会比这篇教程更有趣。

历史

  • 2015/11/25 - 初稿
© . All rights reserved.