J2ME使用KSoap调用C#开发的Web Service(1)
1.概述
对于J2ME访问远端的Web Service,除了官方标准JSR 172,我们还可以使用kSOAP。
kSOAP是Enhydra.org的一个开源作品,是EnhydraME项目的一部分。基于Enhydra.org出品的开源通用XML解析器kXML,kSOAP完成了J2ME/MIDP平台上的SOAP解析和调用工作。
Stefan Haustein领导的kSOAP开发小组于2001年5月17日推出了Alhpa版本。之后又经过了一年的开发,2002年6月6日推出的kSOAP 1.2支持了SOAP1.2规范。2003年8月25日推出的kSOAP2,对SOAP序列化规范支持得更好了。
大多数人选择kSOAP的原因是,kSOAP虽然在2003年8月之后就不再维护了,但它是Open Source的,很容易加入增强特性,比如说默认情况下kSOAP2仅仅支持cmnet接入点,可以修改kSOAP2的HttpTransport.java代码增加对cmwap接入点的支持。kSOAP2.0还有一个优点是,改进了对Microsoft dotNET的兼容。以前有很多人抱怨kSOAP调用dotNET编写的Web Service时遇到了不少的困扰。
2.例子
为了实现这一功能,今天和金金在网上搜了一整天,几乎把网络翻了一遍,见到的不是一样的东西,就是一些没解答的提问,简直是郁闷死了,中途我三次见了一下周公,呵呵,第三次醒来想起来要如何做了。先说一下我在网上收到的方法吧,把KSoap的Jar文件导入到工程中,然后再进行相应的操作,我照着做了,把jar文件导入到工程,在编译的时候是没有问题的,但在运行的时候去报错了,说java.lang.NoClassDefFoundError:org/xmlpull/v1/XmlPullParserException
可是我已经把类库Jar导入进去了啊,找了很长时间也无法解决,不知道网上的是怎么弄的,我用的是Eclipse+EclipseMe+Sun WTK。
还好我找到了解决方案,我从网上找到了KSoap的源码,把它工程src中的文件加进了我的src中,然后编译运行都还成功,在网上下的KSoap源码不全,少几个java文件,我就用反编译工具把相应的.class文件弄成.java文件,这样就生成了比较犬的Ksoap源码,见附件。下面就先从创建Web Service讲起:
我用的是VS2008,创建一个Web服务应用程序,代码如下:
using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using System.Xml.Linq; namespace SimpleKSoapWS { /// <summary> /// Service1 的摘要说明 /// </summary> [WebService(Namespace = "urn:fengxing")] //创建时是自动生成的,把它注释掉 //[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] //[ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 // [System.Web.Script.Services.ScriptService] public class Service1 : System.Web.Services.WebService { [WebMethod] [SoapRpcMethod( Action = "urn:fengxing/Hello",//.NET 要求将 HTTP SOAPAction 头用来标识所请求的操作;其格式是服务的名称空间后跟操作名,中间用 / 隔开(例如, urn:fengxing/foo)。 RequestNamespace="", RequestElementName = "HelloRequest", ResponseNamespace="", ResponseElementName = "HelloResponse" )] public String Hello(String username, String password) { if (username != null) return ("Hello:" + username); else return "null"; } } }
点击启动调试就可以运行。
然后用Ksoap调用Web Service,创建一个J2ME Midlet Suite项目,添加名为Test的J2ME Midlet,再把Ksoap src文件夹下的文件添加到本项目src文件夹下,具体代码如下:
import java.io.IOException; import javax.microedition.midlet.*; import javax.microedition.io.ConnectionNotFoundException; import javax.microedition.lcdui.*; import org.ksoap2.*; import org.ksoap2.serialization.*; import org.ksoap2.transport.*; import org.xmlpull.v1.XmlPullParserException; public class Test extends MIDlet implements CommandListener{ private Display dis; private Command connectCmd=new Command("连接",Command.OK,1); private Command exitCmd=new Command("退出",Command.EXIT,1); private Form f; private StringItem si=new StringItem("",""); public Test() { // TODO Auto-generated constructor stub } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } protected void pauseApp() { // TODO Auto-generated method stub } protected void startApp() throws MIDletStateChangeException { // TODO Auto-generated method stub dis=Display.getDisplay(this); f=new Form("调用Web Service"); f.append("要显示的内容:"+"\n"); f.addCommand(connectCmd); f.addCommand(exitCmd); f.setCommandListener(this); dis.setCurrent(f); } public void commandAction(Command c, Displayable s) { // TODO Auto-generated method stub if (c == exitCmd) { try { destroyApp(false); notifyDestroyed(); } catch (MIDletStateChangeException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(c==connectCmd) { //匿名内部Thread,调用ksoap2访问远程服务 Thread webserviceThread=new Thread() { public void run() { String methodName="Hello"; String serviceURL="http://localhost:4450/Service1.asmx"; SoapObject request=new SoapObject(null,methodName); request.addProperty("username", "xiaowen"); request.addProperty("password", "pwd"); SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut=request; HttpTransport ht=new HttpTransport(serviceURL); ht.debug=true; String Response = null; try { ht.call("urn:fengxing/Hello", envelope);//和.NET中SoapRpcMethod的Action一样 Response = envelope.getResponse().toString(); }catch (ConnectionNotFoundException e) { System.out.println("先打开服务器"); return; } catch (IOException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } System.out.println("dump>>" + ht.responseDump); si.setText(Response); f.append(si); f.removeCommand(connectCmd); } }; webserviceThread.start(); } } }
要保证创建的服务是打开的,最终运行结果如下:
3.详解
明天吧。