Hello World实例
我一直认为实例和代码是最好的说明,还是少说废话,先来个最简单的Hello World实例来体会一下吧。
2.4.1 创建项目
由于我用的是Eclipse,所以先创建一个普通的JAVA项目myxmlrpc,然后将xerces.jar 、xmlrpc-1.2-b1.jar复制到项目的lib目录。再创建一个包:cn.com.chengang.xmlrpc,以后就在此包下写程序。如下图:
2.4.2 创建服务端程序
1、HelloServer
package cn.com.chengang.xmlrpc;
import org.apache.xerces.parsers.SAXParser;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpc;
public class HelloServer {
public static void main(String[] args) {
//使用Xerces的XML解析器
XmlRpc.setDriver(SAXParser.class);
System.out.println("启动一个WEB SERVER, 端口号:8989");
WebServer server = new WebServer(8989);
server.start();
//将HelloHandler类的实例绑定到WEB SERVER上,hello是该处理类的id标识,在客户端调用时要用得到
server.addHandler("hello_id", new HelloHandler());
}
}
说明:
这个文件主要是启动了一个Web Server,并将一个HelloHandler类加到server中。
2、HelloHandler
package cn.com.chengang.xmlrpc;
public class HelloHandler {
public String sayHello(String name) {
return "Hello World, " + name;
}
}
说明:
HelloHandler类不需要实现或继承任何接口抽象类,它的作用就是做为服务器端的处理程序,所有处理逻辑都在Handler类里来实现。我们可以写上很多的Handler类,并且一个Handler类里可以有很多的方法(这里有一个sayHello方法)。
2.4.3 创建客户端程序
1、HelloClient
package cn.com.chengang.xmlrpc;
import java.io.IOException;
import java.util.Vector;
import org.apache.xerces.parsers.SAXParser;
import org.apache.xmlrpc.XmlRpc;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;
public class HelloClient {
public static void main(String args[]) throws XmlRpcException, IOException {
//使用 Apache Xerces SAX 解析器
XmlRpc.setDriver(SAXParser.class);
//定位远程服务器
XmlRpcClient client = new XmlRpcClient("http:// 127.0.0.1:8989");
//创建调用请求,方法的参数列表用一个Vector对象来存储。
Vector params = new Vector();
params.addElement("ChenGang");
//发出请求,并返回结果,execute需要两个参数,第一个参数用“Handler的标识名.方法名”,第二参数是一个刚刚建立的向量对象
String result = (String) client.execute("hello_id.sayHello", params);
System.out.println("服务器的返回值: " + result);
}
}
说明:
l 客户端的程序比较简单,主要是通过XmlRpcClient类来将要调用的服务器端Handler的方法名(Handler的标识),及这个方法的参数(params),传递给服务端。
l 在这里127.0.0.1是指本机,因为服务端和客户端都是在本机运行的,共用同一台电脑。实际运行时,应该是分属在两台电脑上的,这时把127.0.0.1改成真实的服务器IP即可。
l 8989就是HelloServer类中启动Web Server的端口号。
l 有人说这里并没有看到XML文件的影子呀。其实client.execute("hello_id.sayHello", params);这一句已经封装了所有的处理过程,表面上它只是方法名和方法参数,但内部在处理时会将这两者处理成一个XML文件,然后POST到服务 端。
l params.addElement("ChenGang");的参数不能是中文,否则报错。暂未找到解决方法。
2.4.4 运行
1、启动服务
以Application方式来运行HelloServer。Eclipse的“控制台”显示如下图:
2、运行客户端
以Application方式来运行HelloClient。Eclipse的“控制台”显示如下图:
2.5 XML-RPC原理分析
2.5.1 XML-RPC所传输的XML文件
在上面的例程中说了,XML-RPC将远程方法的调用,实际是封装成一个XML文件传给服务器端的,那么我们就来看看这个XML的样子是怎么样的。
1、启动监听器
在上一篇所说的SOAP中有一个监听器,我们把它运行起来。这个监听器可以监听本机上发送到某一个端口的信息。这的监听器的入口类为TcpTunnelGui,启动此监听器的命令如下:
java org.apache.soap.util.net.TcpTunnelGui 8070 localhost 8989
如果报以下错误
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/soap/util/net/TcpTunnelGui
这是因为soap.jar没有定义在classpath变量中,你可以将soap.jar加入到系统变量classpath,也可以在命令中用-cp参数临时指定soap.jar的位置。
java -cp "D:/soap-2_3_1/lib/soap.jar" org.apache.soap.util.net.TcpTunnelGui 8070 localhost 8989
这样所有发向8070端口的信息将被截获,然后这个监听器再把截获的信息转发到8989端口。此监听器的界面如下,左边是发出的信息,右边是从服务端接收的信息。
注意:HelloClient类中的服务器端口号要由8989改成8070。HelloServer还是原来的8989,不用改。
2、客户端发出的XML信息
POST / HTTP/1.1
Content-Length: 165
Content-Type: text/xml
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.4.2_06
Host: 127.0.0.1:8070
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>hello_id.sayHello</methodName><params><param><value>ChenGang</value></param></params></methodCall>
XML的信息是一行,我把它格式化一下,如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<methodCall>
<methodName>hello_id.sayHello</methodName>
<params>
<param>
<value>ChenGang</value>
</param>
</params>
</methodCall>
3、服务端返馈的信息
HTTP/1.1 200 OK
Server: Apache XML-RPC 1.0
Connection: close
Content-Type: text/xml
Content-Length: 144
<?xml version="1.0" encoding="ISO-8859-1"?><methodResponse><params><param><value>Hello World, ChenGang</value></param></params></methodResponse>
XML的信息是一行,我把它格式化一下,如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<methodResponse>
<params>
<param>
<value>Hello World, ChenGang</value>
</param>
</params>
</methodResponse>
2.5.2 客户端的处理流程
在HelloClient的代码中,我们看到是通过XML-RPC中的XmlRpcClient类来处理客户端的请求的,XmlRpcClient 的内部处理逻辑如上,Worker是XmlRpcClient的一个内部类。Worker主要是将“要调用的远程方法以及方法参数”写成一个XML, XML文件的格式在上面“2.5.1 2、客户端发出的XML信息”已经给出了。
2.5.3 服务器端的处理流程(省略)
我修改的XML-RPC源代码不是这个版本的,而是从Apache的CVS上直接check下来的,最新的开发中,其设计已经发生了一些变化。比 如,客户端的XML发送,原版是用HTTP+POST过去的,最新的则将它封成了一个接口:XmlRpcTransport,一个实现是HTTP+ POST,另一个实现则是EMAIL的方式,这样扩展性就更大了。
2.6 参考资料
xml-rpc入门例程及一个通用服务器(CSDN),地址:http://dev.csdn.net/develop/article/39/article/38/38300.shtm