[j2me]利用kSOAP让MIDP设备与
WebService之间传递类对象
编写者 |
日期 |
关键词 |
郑昀@ultrapower |
2005-8-14 |
J2me webservice soa ksoap serialization MIDP CLDC |
无线设备联网的概念
中国移动GPRS网络的连接方式有两种类型,一种是WAP+GPRS,接入名称叫CMWAP,一种是KJava+GPRS,接入名称叫CMNET。也就是说,我们使用J2ME访问远端服务器的Web Service,将走移动的CMNET接入点。
MIDP的概念
MIDP的概念我就不再说了,有一个不错的图片,可以作为注脚:
kSOAP和JSR172
原则上,我们可以通过HttpConnection接口访问远端Web服务器。
但是,对于远端的Web Service,我们还有两种解决方案:
l kSOAP;
l JSR172。
下面,我们来介绍一下:
kSOAP
http://ksoap.objectweb.org/上,你可以下载一系列的包:
ksoap-j2se.zip
ksoap-midp.zip
ksoap-servlet.zip。
这是一个开源项目,它帮助你完成了SOAP的解析和调用工作。虽然kSOAP小组现在已经停止了开发,但是他们留下来的是一个能够工作的kSOAP。
让我们先熟悉一下即将用到的kSOAP的接口:
ListAdapter.cs |
org.ksoap. ClassMap org.ksoap. SoapObject org.ksoap.transport. HttpTransport |
ClassMap能够让你指定序列化/反序列化SOAP Messages的方式;
SoapObject让你自如地构造SOAP调用;
JSR172
在http://jcp.org/en/jsr/detail?id=172,您可以找到“J2METM Web Services Specification”的04年最终发布的规范
http://jcp.org/aboutJava/communityprocess/final/jsr172/index.html。
还有http://java.sun.com/products/wsa/,这里的WSA指的是J2ME Web Services APIs。
“如何真正地将移动设备融入到Web Services中去呢?这就需要使得PDA、手机等成为Web Services的客户端,那么这些设备至少应该具有处理XML信息的能力。J2ME Web Services规范(JSR172)正是为了解决这个问题而来。
首先,该规范的制订是为了给J2ME平台增加两大功能:一是使其能够远程访问基于SOAP/XML的Web Services;二是使其具有解析XML数据的能力。为了实现这两大功能,JSR172新定义了提供相应功能的两个可选包。这两个包占用内存非常少,XML-RPC部分大概需要25-30KB的空间,而XML解析器则需要35KB左右。”
但是目前上市的手机很少有支持JSR172的,所以我们不得不使用kSOAP。
第一小步,Web Service传递String
Web Service传递String给MIDP是一件很简单的事情:
在服务器端,你的由AXIS支撑的Web Service可以这么输出:
服务器端 |
public class SimpleKSoapWS { public SimpleKSoapWS () { } public String foo(String username, String password) { return “fooResult”; } } |
我们来说说,kSOAP是如何调用Web Service的:
SoapObject,一个高度抽象化的类,让无线设备完成SOAP调用。可以调用它的addProperty方法填写要调用的Web Service方法的参数。如下面代码所示:
SoapObject soap = new SoapObject(serviceNamespace, methodName);
SoapObject构造函数的两个参数的意思分别是:
serviceNamespace – 你的Web Service的命名空间;
methodName – 你要调用方法的名字。
然后,按照Web Service方法参数的顺序,依次调用
soap.addProperty( "username", "user" );
soap.addProperty( "password", "pass" );
一般来说,对于仅仅是String的返回值,还用不着ClassMap。
接下来就要声明
HttpTransport tx = new HttpTransport(serviceUrl, methodName);
了。这是一个强大的helper类,来完成Http-call transport process,它封装了network的一切,你完全不用考虑序列化消息。方法HttpTransport.call()自己就能够发送请求给服务器、接收服务器响应并序列化SOAP消息,如下所示:
Object Response = tx.call(request);
客户端的MIDlet的按键事件函数这么写,即可:
midlet |
/* * Respond to commands, including exit * On the exit command, cleanup and notify that the MIDlet has been destroyed. */ public void commandAction(Command c, Displayable s) { if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } if (c == connectCommand) { //匿名内部Thread,访问远程服务。 Thread fetchThread=new Thread() { public void run(){ try { HttpTransport transport = null; String serviceNamespace = "http://localhost:8080/ SimpleWS /services/ SimpleKSoapWS "; String methodName = "foo"; String serviceUrl = "http://localhost:8080/ SimpleWS /services/ SimpleKSoapWS?wsdl"; ClassMap classMap = new ClassMap(true); classMap.prefixMap = new PrefixMap( classMap.prefixMap, "ns", serviceNamespace ); transport = new HttpTransport(serviceUrl, soapAction); transport.setClassMap(classMap); SoapObject soap = new SoapObject( serviceNamespace, methodName); soap.addProperty( "username", "user" ); soap.addProperty( "password", "pass" ); SoapObject response = (SoapObject)transport.call(soap); String sResponse = (String)response; } catch (Exception e) { e.printStackTrace (); } } }; fetchThread.start(); display.setCurrent(mainForm); } |
这里的知识点是,我们需要
Thread fetchThread=new Thread(){…};
来另起一个线程来完成对Web Service的调用。否则,你的模拟器是会一动不动的。