求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Apache HttpClient 客户端
 
火龙果软件    发布于 2013-9-16
 

简介: 使用 Apache HttpClient 库访问 JAX-RS web 服务。Jersey 是 JAX-RS 的参考实现,它简化了 Java? 环境下的 RESTful Web 服务的开发。Android 是一款流行的智能手机,本文将展示如何为 Android 创建一个 JAX-RS 客户端。您将创建一个访问 JAX-RS Web 服务的 Apache HttpClient 库客户端。

REST 软件架构基于具象资源传输。RESTful Web 服务提供了一些优势:简单、轻量级、快速。RESTful Web 服务公开了一组由 URI 标识的资源。资源将根据 HTTP 方法 GET、POST、PUT 和 DELETE 作出响应。资源可通过各种形式访问,如 HTML、普通文本、XML、PDF、JPEG 或 JSON。Java API for RESTful Web 服务 (JAX-RS) 在 JSR 311 中定义。Jersey 是 JAX-RS 的参考实现,简化了 Java 中 RESTful Web 服务的开发。

在本文中,使用 Apache HttpClient 库为流行的智能手机平台 Android 创建一个 JAX-RS 客户端。您可以 下载 本文使用的样例代码。

常用缩略语

API:应用程序编程接口

HTML:超文本标记语言

HTTP:超文本传输协议

IDE:集成开发环境

JSON:JavaScript 对象符号

MIME:多用途网络邮件扩展

POJO:普通 Java 对象

REST:具象状态传输

SDK:软件开发工具包

UI:用户界面

URI:统一资源标识符

URL:统一资源定位符

XML:可扩展标记语言

设置环境

在为 JAX-RS Web 服务创建客户端之前,需要对环境进行设置。参见 参考资料 中的链接。

1.安装 Eclipse。

2.为 Eclipse 安装 Android Development Tools (ADT) 插件,其中提供了一组供在 Eclipse 中开发 Android 应用程序的扩展。

3.为 Android 2.2 安装 SDK Platform。Android SDK 为开发 Android 应用程序提供了工具。

4.创建一个 Android Virtual Device (AVD),这是 Eclipse 中的一个 Android 仿真器。

5.下载 Jersey 压缩文件 jersey-archive-1.4.zip,其中包含 Jersey JAR 和核心依赖文件。下载 Jersey 包 JAR jersey-bundle-1.4.jar。Jersey 是使用 JDK 6.0 构建的,因此还需要安装 JDK 6.0。

6.安装 Web 服务器,如 Tomcat,或应用程序服务器,如 WebSphere?,或 WebLogic 服务器。将清单 1 中的 Jersey JAR 文件添加到应用程序/Web 服务器的运行时 CLASSPATH 中。

清单 1. Jersey JAR 文件

C:\Jersey\jersey-bundle-1.4.jar;C:\Jersey\jersey-archive-1.4\lib\asm-3.1.jar;
C:\Jersey\jersey-archive-1.4\lib\jsr311-api-1.1.1.jar

创建一个 Eclipse 项目

在本节中,您将创建一个 Web 项目并将 JAX-RS facet 添加到该项目中。使用以下步骤创建 Eclipse 项目。

选择 File > New,在 New 窗口中,选择 Web > Dynamic Web Project。单击 Next。

指定项目名称(例如 AndroidJAX-RS)并单击 New Runtime,为您的 WebSphere、Tomcat 或 WebLogic 服务器配置一个新的目标运行时。图 1 展示了完成设置的 Dynamic Web Project 窗口。

图 1. 配置一个新的运行时

在 New Server Runtime Environment 窗口中,选择一个服务器,如 Tomcat 服务器、WebSphere 服务器或 WebLogic 服务器。单击 Next,如图 2 所示。

图 2. 选择一个应用程序或 Web 服务器

在 New IBM WebSphere v6.0 Runtime 窗口中,配置 JRE 和 IBM WebSphere Installation Directory。单击 Dynamic Web Project 对话框中的 Next。为 Source 文件夹和 Output 文件夹选择默认的 Java 设置,并单击 Next。

将 Context root 指定为 AndroidJAX-RS,选择默认的 Content Directory,并单击 Finish。

将创建一个 Dynamic Web Project 并添加到 Project Explorer。右键单击项目节点并选择 Properties。

选择 Project Facets,然后选择 JAX-RS (REST Web Services) 1.1 项目 facet。单击 Further configuration required,如图 3 所示。

图 3.配置 JAX-RS Project Facet

在 JAX-RS Capabilities 窗口中,指定一个 Servlet 名称 (JAX-RS Servlet) 并配置一个 JAX-RS Implementation 库。选择 Type as User Library 并单击 Manage。

在 User Libraries 窗口中,单击 New。在 New User Library 对话框中,指定 User library 名并单击 OK。

将添加一个用户库。单击 Add JARs 以将 Jersey JARs 添加到用户库。如图 4 所示,添加以下 Jersey JAR:

jersey-bundle-1.4.jar

C:\Jersey\jersey-archive-1.4\lib\asm-3.1.jar

C:\Jersey\jersey-archive-1.4\lib\jsr311-api-1.1.1.jar

单击 OK。

图 4.添加 Jersey JAR 文件

在 JAX-RS Capabilities 窗口中,指定 JAX-RS servlet 类名为com.sun.jersey.spi.container.servlet.ServletContainer,如图 5 所示。单击 OK。

图 5.指定 JAX-RS servlet 类

在 Project Facets 窗口中,单击 Apply,如图 6 所示,然后单击 OK。

图 6.应用 JAX-RS Project Facet

目标运行时通过 JAX-RS project facet 进行配置。单击 Properties 对话框中的 OK。

JAX-RS User 库被添加到项目中,JAX-RS servlet 和 servlet 映射在 web.xml 中进行了配置。需要为com.sun.jersey.config.property.resourceConfigClass 和 com.sun.jersey.config.property.packages init 参数添加 init-param 元素。清单 2 显示了此 web.xml。

清单 2. 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">
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>jaxrs</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
</web-app>

创建和运行资源类

下一步是使用一个 root 资源类创建一个 RESTful Web 服务资源。root 资源类是带有 @PATH 注释的 POJO。它包含至少一个带注释的方法,该注释为 @PATH、@GET、@PUT、@POST 或 @DELETE。

1.选择 File > New > Other。在 New 对话框中,选择 Java > Class,然后单击 Finish。

2.在 New Java Class 窗口中,如图 7 所示,指定:

1)一个 Source 文件夹:AndroidJAX-RS/src

2)包:jaxrs

3)类名:HelloWorldResource

单击 Finish。

图 7.创建资源类

使用 @PATH 注释标注 Java 类。清单 3 中的代码指定了 URI 路径,Java 类在该路径中应该托管为 /helloworld。

清单 3.使用 @Path 注释资源类

@Path("/helloworld")
public class HelloWorldResource {
....
}

要添加资源方法以生成三个不同的 MIME 类型,添加 getClichedMessage()、getXMLMessage() 和 getHTMLMessage() 方法。使用 @GET 注释每一个方法,这表示方法应当处理 HTTP GET 请求。指定 String 作为每个方法的返回类型。使用 @PRODUCES 注释每一个方法,并为每个方法指定一个不同的 MIME 类型。

现在,需要用 MIME 类型 text/plain、text/xml 和 text/html 输出 “Hello JAX-RS” 方法。getXMLMessage 方法用 @Produces("text/xml")进行了注释,生成一条 XML 消息。对于使用 @GET 注释了的方法,仅取消其中一个方法的注释。如果没有指定其他不同的路径组件,@GET 请求将被路由到用 @GET 注释的方法。如果有多个方法匹配某个请求 URI,将使用 JAX-RS 选择算法来选择资源方法。例如,可以指定带有 @GET 注释的多个方法,做法是对带有 @GET 注释的方法使用不同的 path id。清单 4 展示了 root 资源类。

清单 4.HelloWorldResource.java

package jaxrs;

import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;

// The Java class will be hosted at the URI path //"/helloworld"
@Path("/helloworld")
public class HelloWorldResource {

// The Java method will process HTTP GET requests
@GET
// The Java method will produce content identified by the MIME Media
// type "text/plain"
@Produces("text/plain")
public String getClichedMessage() {
// Return some cliched textual content
return "Hello Android";
}

// @GET
// @Produces("text/xml")
// public String getXMLMessage() {
// return "<?xml version=\"1.0\"?>" + "<hello> Hello Android" + "</hello>";
// }

// @GET
//@Produces("text/html")
//public String getHTMLMessage() {
//return "<html> " + "<title>" + "Hello Android" + "</title>"
// + "<body><h1>" + "Hello Android" + "</body></h1>" +
"</html> ";
// }

}

运行资源类以生成不同的输出类型。注释掉不执行测试的方法,对于每一次测试,保持一个方法未注释。首先,将 text/xml MIME 类型作为输出进行测试。启动应用程序/Web 服务器(如果尚未启动的话)。右键单击资源类并选择 Run As > Run on Server,如图 8 所示。

图 8.运行资源类

在服务器上,按照 web.xml 的指定,init 参数 com.sun.jersey.config.property.resourceConfigClass 作为 com.sun.jersey.api.core.PackagesResourceConfig 启动,而 init 参数 com.sun.jersey.config.property.packages 作为 jaxrs 启动。找到 root 资源类 jaxrs.HelloWorldResource。启动 Jersey 应用程序 v1.4,AndroidJAX-RS 模块部署到服务器上。

创建 Android 客户端项目

1.在本节中,您将创建一个 Android 项目,在其中将为 Android 创建 JAX-RS 客户端。

2.在 Eclipse IDE 中,选择 File > New。在 New 对话框中,选择 Android > Android Project,然后单击 Next。
填充 New Android Project 窗口中的字段,如图 9 所示。

1)项目名:AndroidJAXRSClient

2)构建目标:Android Platform 2.2 API 8

3)属性:应用程序名 AndroidJAXRSClient 和包名 android.jaxrs

4)选择 Create Activity,并指定 Activity 类 AndroidJAXRSClient。

5)一项活动代表一个用户交互,而扩展 Activity 类的类为 UI 创建了一个窗口。

6)最低 SDK 版本:8

7)单击 Next

图 9.创建 JAX-RS 客户端类

Android 项目中的文件包括:

1.一个活动类 (AndroidJAXRSClient),该类扩展了 Activity 类

2.res/layout/main.xml 文件,指定 Android 应用程序的布局

3.AndroidManifest.xml 文件,包含应用程序配置信息,如包名、应用程序组件、流程、权限和 Android 系统的最低 API 级别。

在 res/layout/main.xml 文件中,指定 Android UI 组件的布局。使用 android:orientation="vertical" 创建一个 LinearLayout。您将创建一个 UI,其中将以文本消息的形式显示来自 Web 服务的响应。添加 id 为 jaxrs 的 TextView 元素,显示方法调用对其中一个 get 方法的 JAX-WS Web 服务响应。方法调用获得一条 Hello 消息作为响应,消息的格式为 XML、HTML 或文本。清单 5 显示了 main.xml 文件:

清单 5.main.xm

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/jaxrs"
android:layout_width="fill_parent" android:layout_height="wrap_content"
/>
</LinearLayout>

要从 Android 设备访问 JAX-RS web 服务,在 AndroidManifest.xml 中启用 android.permission.INTERNET 权限,从而允许应用程序打开网络套接字。添加 uses-permission 元素,如清单 6 所示。

清单 6.设置 INTERNET 权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.jaxrs" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidJAXRSClient" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

Android SDK 包含 Apache HttpClient 库。将清单 8 中的类导入到 AndroidJAXRSClient。

清单 8 Apache HttpClient 库

org.apache.http.HttpEntity;
org.apache.http.HttpResponse;
org.apache.http.client.ClientProtocolException;
org.apache.http.client.HttpClient;
org.apache.http.client.methods.HttpGet;
org.apache.http.impl.client.DefaultHttpClient;

AndroidJAXRSClient 类扩展了 Activity 类。在第一次调用 Activity 时用到了 onCreate(Bundle savedInstanceState) 方法。使用 setContentView 方法和布局资源定义用户界面,如清单 9 所示。

清单 9.定义 UI

setContentView(R.layout.main);

清单 10 展示了如何创建一个 Android 部件 TextView 对象,其中对 TextView 元素使用 findViewById 方法,id 为 main.xml 中定义的 jaxrs。

清单 10.创建 Android 部件

TextView jaxrs = (TextView) findViewById(R.id.jaxrs);

HttpClient 的默认实现是 DefaultHttpClient。创建一个 DefaultHttpClient 对象,如清单 11 所示。

清单 11. 创建一个 HttpClient

HttpClient httpclient = new DefaultHttpClient();

创建一个 HttpGet 对象,从服务器检索信息,如清单 12 所示。为 URI 路径 /helloworld 上托管的资源指定 URL。为主机而不是本地主机指定 IP 地址。客户端运行在 Android 设备之上,Android 设备的本地主机并不是 JAX-RS Web 服务运行的主机(除非 JAX-RS Web 服务也托管在 Android 设备上,但是在本例中并不属于这种情况)。

清单 12.创建 HttpGet 对象

HttpGet request = new HttpGet("http://192.168.1.68:7001/AndroidJAX-RS/jaxrs/helloworld");

使用 Accept 头指定可接受的媒体类型。在 Accept 中只设置一种媒体类型,该类型与 JAX-RS Web 服务中生成的媒体类型对应。在首次运行时,将 Accept 头设置为 text/xml 以输出 text/xml 响应,如清单 13 所示。

清单 13. 设置 Accept 头

request.addHeader("Accept", "text/xml");
//request.addHeader("Accept", "text/html");
//request.addHeader("Accept", "text/plain");

测试每种响应类型的输出(普通文本、html 和 XML)。允许的响应类型应当匹配资源类中生成的 MIME 类型。资源类生成的 MIME 类型应当匹配一种可接受的 MIME 类型。如果生成的 MIME 类型和可接受的 MIME 类型不 匹配,那么将生成 com.sun.jersey.api.client.UniformInterfaceException。例如,将可接受的 MIME 类型设置为 text/xml,而将生成的 MIME 类型设置为 application/xml。将生成 UniformInterfaceException。如清单 14 清单 14 所示,调用 HttpClient 的 execute() 方法,其中 HttpGet 方法作为参数,以检索 HttpResponse 对象。

清单 14.获得 HttpResponse

HttpResponse response = httpclient.execute(request);

使用 getEntity 方法从 HttpResponse 获取 HttpEntity(清单 15 )。

清单 15.获取 HttpEntity

HttpEntity entity = response.getEntity();

使用 getContent() 方法以 InputStream 的形式通过 HttpGet 获取内容(清单 16 )。

清单 16.通过 HttpEntity 创建 InputStream

InputStream instream = entity.getContent();

为返回自 JAX-RS Web 服务的消息创建 StringBuilder(清单 17 )。

清单 17.创建 StringBuilder

StringBuilder sb =  new StringBuilder();

从 InputStream 创建 BufferedReader(清单 18 )。

清单 18.创建一个 BufferedReader

BufferedReader r = new BufferedReader(new InputStreamReader(instream));

读取 BufferedReader 中的每一行并添加到 StringBuilder(清单 19 )。

清单 19.读取 BufferedReader

for (String line = r.readLine(); line != null; line = r.readLine()) {
sb.append(line);
}

从 StringBuilder 获取 String 消息并结束 InputStream(清单 20 )。

清单 20.获取 StringBuilder 消息

String jaxrsmessage = sb.toString();		
instream.close();

在 TextView UI 组件上设置 String 消息(清单 21 )。

清单 21.设置 StringBuilder 消息

jaxrs.setText(jaxrsmessage);

清单 22 展示了 AndroidJAXRSClient 类。

清单 22.AndroidJAXRSClient.java

package android.jaxrs;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

public class AndroidJAXRSClient extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

TextView jaxrs = (TextView) findViewById(R.id.jaxrs);
try {
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet(
"http://192.168.1.68:7001/AndroidJAX-RS/jaxrs/helloworld");

//request.addHeader("Accept", "text/html");
// request.addHeader("Accept", "text/xml");
request.addHeader("Accept", "text/plain");
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
InputStream instream = entity.getContent();
String jaxrsmessage = read(instream);
jaxrs.setText(jaxrsmessage);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}

private static String read(InputStream instream) {
StringBuilder sb = null;
try {
sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(
instream));
for (String line = r.readLine(); line != null; line = r.readLine()) {
sb.append(line);
}

instream.close();

} catch (IOException e) {
}
return sb.toString();

}

}

图 10 展示了 Android 客户端应用程序的目录结构。(查看图 10 的 放大图)。

图 10.Android 应用程序的目录结构

运行 Android 客户端

现在,我们准备运行 Android 客户端以调用 JAX-RS Web 服务和输出 XML 消息。右键单击 AndroidJAXRSClient 项目并选择 Run As > Android Application,如图 11 所示。

图 11.运行 Android JAX-RS 客户端

Android AVD 启动,JAX-RS 客户端应用程序安装在 Android 设备上,如图 12 所示。

图 12.Android 上安装的 Android JAX-RS 客户端

AndroidJAXRSClient 活动启动,并且 JAX-RS Web 服务生成的 XML 消息被输出到 Android 设备,如图 13 所示。

图 13.输出 XML 消息到 Android 设备

类似地,如果在资源类中,生成 text/html 媒体类型的方法是未注释的,那么输出为 HTML 消息,而 Accept 头被设置为接收相同的媒体类型。例如,在资源类中,取消清单 23 中的方法的注释。

清单 23.在资源类中生成 HTML

@GET
@Produces("text/html")
public String getHTMLMessage() {
return "<html> " + "<title>" + "Hello Android" + "</title>"
+ "<body><h1>" + "Hello Android" + "</body></h1>" + "</html> ";
}

在客户端类中,取消清单 24 中 addHeader 调用的注释。

清单 24.将媒体类型设置为 Accept

request.addHeader("Accept", "text/html");

重新运行 AndroidJAXRSClient 应用程序以获取 HTML 响应,如图 14 所示。

图 14.到 Android 设备的 HTML 输出

要获得文本响应,对清单 25 中资源类中的方法取消注释。

清单 25.在资源类中生成文本媒体类型

@GET
@Produces("text/plain")
public String getClichedMessage() {
return "Hello Android";
}

在客户端类中,取消清单 26 中的以下 Accept 头媒体类型设置的注释。

清单 26.设置 Accept 头

request.addHeader("Accept", "text/plain");

重新运行 AndroidJAXRSClient 应用程序以获取文本消息输出,如图 15 所示。

图 15.输出文本消息到 Android 设备

结束语

在本文中,您了解了如何创建一个 JAX-RS Web 服务并从 Android 客户端调用该 Web 服务。您向 Android 设备发送了 XML、HTML 和文本输出。

 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
 
分享到
 
 


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...