最近项目中采用Apache CXF 的REST 方式发布WebService实现,Android手机后台服务的开发,以下以简单是实例实现。
在项目中采用Android+REST WebService服务方式开发的手机平台很少采用 soap协议这种方式,主要soap协议解析问题,增加了代码量。 采用RESTFull 方式开发WebService的好处,相对SOAP协议的WebService来说,比较简单。同时简化了在手机解析工作,减轻了手机端的压力,提高了手机响应的效率。
手机后台服务:
package com.easyway.rest.ws;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* 服务端发布一个简单的WebService服务
* 在手机端接受服务端发送的信息.
* 使用 Apache HttpClient 库访问 JAX-RS web 服务。Jersey 是 JAX-RS
* 的参考实现,它简化了 Java™ 环境下的 RESTful Web 服务的开发。Android
* 是一款流行的智能手机,本文将展示如何为 Android 创建一个 JAX-RS 客户端。
* 您将创建一个访问 JAX-RS Web 服务的 Apache HttpClient 库客户端。
* JAX-RS必须的jar:
* jersey-bundle-1.8.jar,jersey-server-1.10.jar,jsr311-api-1.1.1.jar
* asm-3.1.jar
* 使用一个 root 资源类创建一个 RESTful Web 服务资源。root 资源类是带有 @PATH
* 注释的 POJO。它包含至少一个带注释的方法,该注释为 @PATH、@GET、@PUT、@POST
* 或 @DELETE。
*
* 在服务器上,按照 web.xml 的指定,init 参数 com.sun.jersey.config.property.resourceConfigClass
* 作为 com.sun.jersey.api.core.PackagesResourceConfig 启动,而 init 参数
* com.sun.jersey.config.property.packages 作为 com.easyway.rest.ws 启动。
* 找到 root 资源类 com.easyway.rest.ws.HelloWorldResource。
*
* 备注:如果采用jersey发布JAXRS服务需要配置:
* <pre>
* <servlet>
* <description>JAX-RS</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>com.easyway.rest.ws</param-value>
* </init-param>
* <load-on-startup>1</load-on-startup>
* </servlet>
* <servlet-mapping>
* <servlet-name>JAX-RS-Servlet</servlet-name>
* <url-pattern>/services/*</url-pattern>
* </servlet-mapping>
*
* </pre>
*
* @author longgangbai
*
*/
@Path("/helloworld")
public class HelloWorldResource {
/**
* 一个简单的文本信息
* @return
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getClichedMessage() {
return "Hello Android";
}
}
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>JAXRSWebService</display-name>
<servlet>
<description>JAX-RS</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>com.easyway.rest.ws</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS-Servlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
注意如果没有 Resource 将会报如下异常:
com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes.
手机前台服务:
package com.easyway.rest.ws;
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;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.widget.TextView;
/**
* Android平台主要提供了四种数据存储方式:Shared Preferences、文件存储、Sqlite存储和网络存储。其中:
1)Shared Preferences 一个轻量级的键-值存储机制,专门用于存储键-值对数据,并且仅可以存储基本的数据类型
(boolean、int、long、float和String);通常使用它来存储应用程序的配置信息。
2)文件存储 通过FileInputStream和FileOutputStream对文件进行操作,在Android中,文件是一个应用程序私有的,
一个应用程序无法读写其它应用程序的文件。
3)SQLite存储 SQLite是一款轻型的数据库,支持标准SQL。它的设计目标是嵌入式的,占用资源非常的低,在嵌入式设备中,
只需要几百K的内存就够了。Android平台也为我们提供了SQLite数据库。
4)网络存储 以上3种方式数据均存储在手机上,而网络存储的数据是存储在远程服务器上,手机客户端通过联接到网络来存储和获取数据。
今天要讲解的HttpClient正是常用的网络存储工具之一。记得最早接触HttpClient是在两年前,当时要做一个垂直搜索引擎,
数据自然是来源于互联网,通过一个爬虫系统不断从指定网站上爬取感兴趣的数据,然后通过Lucene搜索引擎框架实现海量数据
的快速检索。而爬虫系统最开始是想采用开源的爬虫框架Heritrix来实现,但接触一段时间后发现Heritrix过于庞大,而且是作
为一个独立的系统运行,不方便嵌入到现有的系统中,再加上学习成本高,最后还是选择了“HttpClient + HtmlParser”来实现的
小型爬虫系统;其中HttpClient可以模拟HTTP的POST和GET请求,用于从指定网站获取网页数据,而HtmlParser用于解析爬取到
的页面,过滤HTML标记,取得最终数据。
是不是发现HttpClient还挺强大的?让我们看看它是什么来头。"HttpClient 是 Apache Jakarta Common 下的子项目,可以用来
提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议"。如果你以前没
有接触过HttpClient,那么你只需要简单记住两点就可以了:
1)HttpClient是一个HTTP协议开发包;
2)HttpClient不是Android的专利。
HttpClient的功能介绍:
1)实现了HTTP请求的所有方法(如GET、POST、PUT、HEAD 等);
2)支持自动转向;
3)支持 HTTPS 协议;
4)支持代理服务器等
HttpClient的基本使用(以POST请求为例):
1)创建HttpClient实例(类似于浏览器客户端);
HttpClient client = new DefaultHttpClient();
2)创建HttpPost请求,需要向HttpPost的构造方法传入所请求的URL;
HttpPost post = new HttpPost(requestUrl);
3)发出POST请求(调用HttpClient的execute()方法,execute()的参数为HttpPost实例);
HttpResponse response = client.execute(post);
4)读取返回结果;
5)释放连接;
6)对返回的结果进行处理。
在Android平台上使用HttpClient,并不需要添加额外的jar包,因为Android平台吸收了许多优秀的开源框架,其中就包括HttpClient,
下面就来看一个Android平台使用HttpClient的例子。
备注:是不是发现HttpClient很容易使用呢?其实,上面所讲解的只是HttpClient最基本的功能(发起POST请求);我们在浏览器客户端
所执行的大多数操作HttpClient都能够模拟,例如:提交表单、查询数据、上传下载文档、页面跳转、Session存储等。比如大家经
常玩“抢车位”、“偷菜”,就可以通过HttpClient编程自动实现。
*
*
* 客户端通过Apache HttpClient调用JAXRS WebService的服务。
* 为 Android 开发访问 JAX-RS Web 服务的 Apache HttpClient 客户端.
*
* 备注:在访问本机的JAXRS Web服务的时候不能使用localhost或者127.0.0.1,
* 因为android模拟机会调用自身的linux内核操作系统,所以可能找不到相关的服务。
* 最好填写ip地址如下:
* "http://192.168.134.1:8080/JAXRSWebService/services/helloworld";
*
* @author longgangbai
*
*/
public class AndroidJAXRSWebServiceActivity extends Activity {
private static final String processURL="http://192.168.134.1:8080/JAXRSWebService/services/helloworld";
private TextView txResult;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
///在Android2.2以后必须添加以下代码
//本应用采用的Android4.0
//设置线程的策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
//设置虚拟机的策略
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
//.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
super.onCreate(savedInstanceState);
//设置UI布局
setContentView(R.layout.main);
//获取结果显示文本框
txResult=(TextView)findViewById(R.id.tvresult);
//获取JAXRS WebService的结果信息
getJAXRSWebService();
}
/**
* 获取JAXRS WebService的结果信息
*/
public void getJAXRSWebService(){
try {
//创建一个HttpClient对象
HttpClient httpclient = new DefaultHttpClient();
//创建HttpGet对象
HttpGet request=new HttpGet(processURL);
//请求信息类型MIME每种响应类型的输出(普通文本、html 和 XML)。允许的响应类型应当匹配资源类中生成的 MIME 类型
//资源类生成的 MIME 类型应当匹配一种可接受的 MIME 类型。如果生成的 MIME 类型和可接受的 MIME 类型不 匹配,那么将
//生成 com.sun.jersey.api.client.UniformInterfaceException。例如,将可接受的 MIME 类型设置为 text/xml,而将
//生成的 MIME 类型设置为 application/xml。将生成 UniformInterfaceException。
request.addHeader("Accept","text/plain");
//获取响应的结果
HttpResponse response =httpclient.execute(request);
//获取HttpEntity
HttpEntity entity=response.getEntity();
//获取响应的结果信息
String result =EntityUtils.toString(entity);
txResult.setText(result);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}