SOAP的主页:http://ws.apache.org/soap/
SOAP RPC 的工作原理非常类似于WEB的请求/响应方式,两者都以HTTP作为通信协议,不同之处在于WEB客户和WEB服务器之间传输的是HTML数据,而在SOAP RPC模式中,SOAP客户和服务之间传输的是符合SOAP规范的XML数据。本文通过一个简单的SOAP应用来说明SOAP RPC的工作方式。
在Eclipse里面创建SOAP工程,把从SOAP主页上下载到的SOAP分发版本中的webapps/soap/目录中的文件拷贝过来,再把mail.jar/activation.jar/soap.jar拷贝到WEB-INF/lib/目录下。(mail.jar和activation.jar请在SUN网站上找,soap.jar在SOAP分发版本的lib目录中)
目录结构如下:
soap/ |--src/ | |--org.eleaf.soap/ | |--HelloClient.java | |--HelloService.java |--WebRoot/ |--admin/ |--META-INF/ |--WEB-INF/ |--DeploymentDescriptor.xml |--web.xml |--lib/ |--soap.jar |--mail.jar |--activation.jar |
在TOMCAT的conf/server.xml文件中添加一个名为soap的Context标记:
<Context path="/soap" docBase="D:\work\eclipse\soap\WebRoot" workDir="D:\work\eclipse\soap\j2src" reloadable="true" debug="0"/> </Host> …… |
然后启动TOMCAT,访问http://jim:4001/soap/ ,可以看到SOAP的控制页面:
<!--StartFragment --> Apache-SOAP Hello! Welcome to Apache-SOAP. What do you want to do today?
- Run the admin client
- Visit the SOAP RPC router URL for this SOAP server
Apache-SOAP Hello! Welcome to Apache-SOAP. What do you want to do today?
- Run the admin client
- Visit the SOAP RPC router URL for this SOAP server
|
SOAP服务器端程序:包含三个可供客户端调用的方法。
package org.eleaf.soap; import java.util.Date; public class HelloService { public String sayHello(String username) { return "Hello:" + username; } public Date getDate() { return new Date(); } public int sum(int i, int j) { return i+j; } } |
SOAP服务配置文件:DeploymentDescriptor.xml:
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment " id="urn:helloservice"> <isd:provider type="java" scope="Application" methods="sayHello getDate sum"> <isd:java class="org.eleaf.soap.HelloService"/> </isd:provider> </isd:service> |
把soap.jar/mail.jar/activation.jar加入CLASSPATH:
D:\work\eclipse\soap\WebRoot\WEB-INF>set classpath=%classpath%;D:\jakarta-tomcat -5.0.28\shared\lib\activation.jar;D:\jakarta-tomcat-5.0.28\shared\lib\mail.jar;D :\work\eclipse\soap\WebRoot\WEB-INF\lib\soap.jar D:\work\eclipse\soap\WebRoot\WEB-INF> |
发布SOAP服务:
D:\work\eclipse\soap\WebRoot\WEB-INF>java org.apache.soap.server.ServiceManagerC lient http://jim:4001/soap/servlet/rpcrouter deploy DeploymentDescriptor.xml D:\work\eclipse\soap\WebRoot\WEB-INF> |
查看已发布的SOAP服务:
D:\work\eclipse\soap\WebRoot\WEB-INF>java org.apache.soap.server.ServiceManagerC lient http://jim:4001/soap/servlet/rpcrouter list Deployed Services: urn:helloservice D:\work\eclipse\soap\WebRoot\WEB-INF> |
编写客户端调用程序:该类将通过SOAP发出RPC请求,来调用服务器端的三个方法。
package org.eleaf.soap; import java.net.URL; import java.util.Vector; import org.apache.soap.Constants; import org.apache.soap.Fault; import org.apache.soap.rpc.Call; import org.apache.soap.rpc.Parameter; import org.apache.soap.rpc.Response; public class HelloClient { /** * @param args */ public static void main(String[] args) throws Exception{ URL url = new URL("http://jim:4001/soap/servlet/rpcrouter ");
Call call = new Call(); call.setTargetObjectURI("urn:helloservice"); call.setMethodName("sayHello"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); Vector params = new Vector(); params.addElement(new Parameter("username", String.class , "bitan", null )); call.setParams(params); Response resp = call.invoke(url, ""); if (resp.generatedFault()) { Fault fault = resp.getFault(); System.out.println("[code:" + fault.getFaultCode() + "];[description:" + fault.getFaultString() + "]"); } else { Parameter result = resp.getReturnValue(); System.out.println("[value:" + result.getValue() + "];[name:" + result.getName() + "];[class:" + result.getClass() + "];[type:" + result.getType() + "];[encoding:" + result.getEncodingStyleURI() + "]"); } call.setMethodName("getDate"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); call.setParams(null ); resp = call.invoke(url, ""); if (resp.generatedFault()) { Fault fault = resp.getFault(); System.out.println("[code:" + fault.getFaultCode() + "];[description:" + fault.getFaultString() + "]"); } else { Parameter result = resp.getReturnValue(); System.out.println("[value:" + result.getValue() + "];[name:" + result.getName() + "];[class:" + result.getClass() + "];[type:" + result.getType() + "];[encoding:" + result.getEncodingStyleURI() + "]"); }
call.setMethodName("sum"); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); params = new Vector(); params.addElement(new Parameter("i", int .class , new Integer(24), null )); params.addElement(new Parameter("j", int .class , new Integer(37), null )); call.setParams(params); resp = call.invoke(url, ""); if (resp.generatedFault()) { Fault fault = resp.getFault(); System.out.println("[code:" + fault.getFaultCode() + "];[description:" + fault.getFaultString() + "]"); } else { Parameter result = resp.getReturnValue(); System.out.println("[value:" + result.getValue() + "];[name:" + result.getName() + "];[class:" + result.getClass() + "];[type:" + result.getType() + "];[encoding:" + result.getEncodingStyleURI() + "]"); } } } |
执行结果:
D:\work\eclipse\soap\WebRoot\WEB-INF\classes>java org.eleaf.soap.HelloClient [value:Hello:bitan ];[name:return];[class:class org.apache.soap.rpc.Parameter];[t ype:class java.lang.String];[encoding:null] [value:Wed Oct 19 14:32:29 CST 2005 ];[name:return];[class:class org.apache.soap. rpc.Parameter];[type:class java.util.Date ];[encoding:null] [value:61 ];[name:return];[class:class org.apache.soap.rpc.Parameter];[type:int ]; [encoding:null] D:\work\eclipse\soap\WebRoot\WEB-INF\classes> |
删除已发布的SOAP服务:
再次调用客户程序,由于服务已被删除,客户端再次调用时返回错误代码:
D:\work\eclipse\soap\WebRoot\WEB-INF>cd classes D:\work\eclipse\soap\WebRoot\WEB-INF\classes>java org.eleaf.soap.HelloClient [code:SOAP-ENV:Server ];[description:service 'urn:helloservice' unknown ] [code:SOAP-ENV:Server];[description:service 'urn:helloservice' unknown] [code:SOAP-ENV:Server];[description:service 'urn:helloservice' unknown] D:\work\eclipse\soap\WebRoot\WEB-INF\classes> |