Android 为 Android 开发访问 JAX-RS Web 服务的 Apache HttpClient 客户端

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

转自:http://www.ibm.com/developerworks/cn/xml/x-android-jax-rs/

Spring Android 简介

Spring Android 是另一个选择。在本文中学习使用 Spring Android REST 客户端访问 RESTful Web 服务,同时阅读由 Deepak 撰写的文章:

为 JAX-RS web 服务开发 Spring Android 客户端

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 项目。

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

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


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

    图 2. 选择一个应用程序或 Web 服务器
    Android 为 Android 开发访问 JAX-RS Web 服务的 Apache HttpClient 客户端_第1张图片

  4. 在 New IBM WebSphere v6.0 Runtime 窗口中,配置 JRE 和 IBM WebSphere Installation Directory。单击 Dynamic Web Project 对话框中的Next。为 Source 文件夹和 Output 文件夹选择默认的 Java 设置,并单击 Next
  5. 将 Context root 指定为 AndroidJAX-RS,选择默认的 Content Directory,并单击 Finish

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

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

    图 3.配置 JAX-RS Project Facet


  7. 在 JAX-RS Capabilities 窗口中,指定一个 Servlet 名称 (JAX-RS Servlet) 并配置一个 JAX-RS Implementation 库。选择Type as User Library 并单击 Manage
  8. 在 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 文件


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

    图 5.指定 JAX-RS servlet 类


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

    图 6.应用 JAX-RS Project Facet
    Android 为 Android 开发访问 JAX-RS Web 服务的 Apache HttpClient 客户端_第2张图片

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

JAX-RS User 库被添加到项目中,JAX-RS servlet 和 servlet 映射在 web.xml 中进行了配置。需要为 com.sun.jersey.config.property.resourceConfigClasscom.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所示,指定:
    • 一个 Source 文件夹:AndroidJAX-RS/src
    • 包:jaxrs
    • 类名: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/plaintext/xmltext/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 客户端项目

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

  1. 在 Eclipse IDE 中,选择 File > New。在 New 对话框中,选择Android > Android Project,然后单击 Next
  2. 填充 New Android Project 窗口中的字段,如图 9所示。
    • 项目名:AndroidJAXRSClient
    • 构建目标:Android Platform 2.2 API 8
    • 属性:应用程序名 AndroidJAXRSClient 和包名 android.jaxrs
    • 选择 Create Activity,并指定 Activity 类 AndroidJAXRSClient

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

    • 最低 SDK 版本:8
    • 单击 Next


    图 9.创建 JAX-RS 客户端类
    Android 为 Android 开发访问 JAX-RS Web 服务的 Apache HttpClient 客户端_第3张图片

Android 项目中的文件包括:

  • 一个活动类 (AndroidJAXRSClient),该类扩展了 Activity
  • res/layout/main.xml 文件,指定 Android 应用程序的布局
  • AndroidManifest.xml 文件,包含应用程序配置信息,如包名、应用程序组件、流程、权限和 Android 系统的最低 API 级别。

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


清单 5.main.xml

				
<?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 权限

				
<uses-permission  android:name="android.permission.INTERNET"></uses-permission> 

使用 uses-sdk 元素指定最低 Android 版本。AndroidJAXRSClient 活动、intent-filteractionactivity 元素和子元素中指定。清单 7显示了 AndroidManifest.xml 文件。


清单 7.AndroidManifest.xml

				
<?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 所示,调用 HttpClientexecute() 方法,其中 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 服务的 Apache HttpClient 客户端_第4张图片

运行 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 和文本输出。

你可能感兴趣的:(apache,Web,android,servlet,String,websphere)