1. 服务端
这次要发布的web service非常简单。它的功能是把从客户端传入的字符串中的小写字母转变成大写字母,再返回给客户端。Soap 服务器采用apache的AXIS(可以从http://ws.apache.org/axis/下载),应用服务器可以选用各种servlet 容器,我这里采用的是weblogic。
1.1 实现类的源代码
// StringProcessor.java
package com.jagie.j2me.ws;
public class StringProcessor {
public StringProcessor() {
}
public String process(String name){
return name.toUpperCase();
}
}
1.2 发布步骤
1.准备一个目录作为web application的发布目录,我这里的这个目录叫jagiews,这个目录的全路径中最好不要有空格和中文。我的发布目录结构如下:
2.编译StringProcessor.java,把生成的StringProcessor.class置于: \jagiews\WEB-INF\classes\com\jagie\j2me\ws目录下。
3.在jagiews\WEB-INF\lib 文件夹中置入以下axis服务器需要的jar文件 axis.jar,axis-ant.jar,commons-discovery.jar,commons-logging.jar,jaxrpc.jar,log4j-1.2.8.jar,saaj.jar ,wsdl4j.jar。这些文件可以在http://ws.apache.org/axis/下载,如图所示:
4.在jagiews\WEB-INF目录下增加2个发布描述文件:server-config.wsdd,web.xml。
#server-config.wsdd
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="adminPassword" value="admin"/>
<parameter name="attachments.Directory" value="C:\Program Files
\Apache Tomcat 4.0\webapps\axis\WEB-INF\attachments"/>
<parameter name="attachments.implementation"
value="org.apache.axis.attachments.AttachmentsImpl"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendMultiRefs" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="axis.sendMinimizedElements" value="true"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="session"/>
</handler>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="request"/>
<parameter name="extension" value=".jwr"/>
</handler>
</requestFlow>
</globalConfiguration>
<handler name="LocalResponder"
type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper"
type="java:org.apache.axis.handlers.http.URLMapper"/>
<handler name="RPCDispatcher"
type="java:org.apache.axis.providers.java.RPCProvider"/>
<handler name="Authenticate"
type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<handler name="MsgDispatcher"
type="java:org.apache.axis.providers.java.MsgProvider"/>
<service name="AdminService" provider="java:MSG">
<parameter name="allowedMethods" value="AdminService"/>
<parameter name="enableRemoteAdmin" value="false"/>
<parameter name="className" value="org.apache.axis.utils.Admin"/>
<namespace>http://xml.apache.org/axis/wsdd/</namespace>
</service>
<service name="Version" provider="java:RPC">
<parameter name="allowedMethods" value="getVersion"/>
<parameter name="className" value="org.apache.axis.Version"/>
</service>
<!-- your service begin-->
<service name="StringProcess" provider="java:RPC">
<parameter name="allowedMethods" value="process"/>
<parameter name="className"
value="com.jagie.j2me.ws.StringProcessor"/>
</service>
<!-- your service end -->
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="java:org.apache.axis.transport.local.LocalResponder"/>
</responseFlow>
</transport>
</deployment>
# web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
<display-name>Apache-Axis</display-name>
<servlet>
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AxisServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<display-name>Axis Admin Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AdminServlet
</servlet-class>
<load-on-startup>100</load-on-startup>
</servlet>
<servlet>
<servlet-name>SOAPMonitorService</servlet-name>
<display-name>SOAPMonitorService</display-name>
<servlet-class>
org.apache.axis.monitor.SOAPMonitorService
</servlet-class>
<init-param>
<param-name>SOAPMonitorPort</param-name>
<param-value>5001</param-value>
</init-param>
<load-on-startup>100</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>*.jws</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SOAPMonitorService</servlet-name>
<url-pattern>/SOAPMonitor</url-pattern>
</servlet-mapping>
<!-- uncomment this if you want the admin servlet -->
<!--
<servlet-mapping>
<servlet-name>AdminServlet</servlet-name>
<url-pattern>/servlet/AdminServlet</url-pattern>
</servlet-mapping>
-->
<!-- currently the W3C havent settled on a media type for WSDL;
http://www.w3.org/TR/2003/WD-wsdl12-20030303/#ietf-draft
for now we go with the basic 'it's XML' response -->
<mime-mapping>
<extension>wsdl</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xsd</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
</web-app>
5.开启你的application server,把目录jagiews发布为一个名叫jagiews的web application。
6.测试:打开浏览器,输入网址(这里使用的是weblogic,其他的服务器请酌情修改): http://localhost:7001/jagiews/services/StringProcess?method=process&name=qqqq,如果浏览器能在返回的xml文档中显示字符串"QQQQ",恭喜你,你的web service发布成功了。如果发布不成功,请按以上发布步骤检查一下。
2. 客户端
客户端自然是用MIDlet了,不过用什么方式来访问web service呢?其实有3种访问方式
直接用HttpConnection访问 http://localhost:7001/jagiews/services/StringProcess?method=process&name=qqqq,得到xml的返回数据,然后用kxml(http://kxml.enhydra.org/)解析,得到返回值。
如果你的手机支持MIDP2.0的话,可以考虑使用JSR172。
用ksoap api。
这里讲述第三种方式。使用之前,你需要从 http://ksoap.enhydra.org/software/downloads/index.html下载稳定的ksoap包,置于你的classpath中。
2.1 客户端源代码
2.1.1 WSClientMIDlet.java
package com.jagie.j2me.ws;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class WSClientMIDlet
extends MIDlet {
static WSClientMIDlet instance;
public WSClientMIDlet() {
instance = this;
}
public void startApp() {
Display display=Display.getDisplay(this);
DisplayForm displayable = new DisplayForm();
display.setCurrent(displayable);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public static void quitApp() {
instance.destroyApp(true);
instance.notifyDestroyed();
instance = null;
}
}
2.1.2 DisplayForm.java
package com.jagie.j2me.ws;
import javax.microedition.lcdui.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class DisplayForm
extends Form
implements CommandListener, Runnable {
private TextField textField1;
private Thread t;
public DisplayForm() {
super("字符转换webservice测试");
try {
jbInit();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
// Set up this Displayable to listen to command events
textField1 = new TextField("", "", 15, TextField.ANY);
this.setCommandListener(this);
textField1.setLabel("待处理的字符串是:");
textField1.setConstraints(TextField.ANY);
textField1.setInitialInputMode("Tester");
setCommandListener(this);
// add the Exit command
addCommand(new Command("Exit", Command.EXIT, 1));
addCommand(new Command("Process", Command.OK, 1));
this.append(textField1);
}
public void commandAction(Command command, Displayable displayable) {
if (command.getCommandType() == Command.EXIT) {
WSClientMIDlet.quitApp();
}
else if (command.getCommandType() == Command.OK) {
t = new Thread(this);
t.start();
}
}
public void run() {
String s1 = textField1.getString();
String s2 = new StringProcessorStub().process(s1);
StringItem resultItem = new StringItem("处理后的字符串是:", s2);
this.append(resultItem);
}
}
2.1.3 StringProcessorStub.java
package com.jagie.j2me.ws;
import org.ksoap.*;
import org.ksoap.transport.HttpTransport;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class StringProcessorStub {
public StringProcessorStub() {
}
public String process(String name) {
String result = null;
try {
SoapObject rpc = new SoapObject
("http://localhost:7001/jagiews/services/StringProcess", "process");
rpc.addProperty("name", name);
HttpTransport ht = new HttpTransport
("http://localhost:7001/jagiews/services/StringProcess", "");
result = (String) ht.call(rpc);
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
测试客户端
现在,试着在你的ide里运行WSClientMIDlet,如果调用成功,则出现以下画面:
总结
有了ksoap,手机上调用web service就很容易了。不过要注意的是,使用网络连接这种费时操作的时候,一定要单独开线程进行,不要直接写在commandAction()方法里,否则出现画面被锁住的情况。