简介: 使用 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 和文本输出。

更多相关文章

  1. Android Span的各种使用方法,简单、易懂、全面、详细
  2. Android的两种拍照方法
  3. [Android] Eclipse Android中设置模拟器屏幕大小几种方法
  4. VS2019中用xamarin开发Android,显示需要android sdk28的解决方法
  5. Android声音管理方法
  6. Android中String资源文件的format方法
  7. android性能测试方法
  8. 【Android开机启动Activity或者Service方法】

随机推荐

  1. android学习——GridView实现主界面布局
  2. 【Unity3d】Unity5与Android交互通信(使用
  3. 浅谈Android系统启动过程
  4. Knowledge structure in Android src dev
  5. Unity3d调用android中的方法
  6. 使用Android(安卓)Google Map
  7. Android画图学习总结(四)——Animation(下)
  8. NetBeans 7.0 安装 Android SDK 开发 And
  9. Android使用json对中文进行编码 使用php
  10. Android获取当前已连接的wifi信号强度的