系統用純HTTP+POST+XML的方式來進行信息溝通:XML是信息的載體、HTTP是傳遞的協議、POST是傳遞的方式。也就是說這和Web Service沒什么關系。Web Service現在有兩種不同實現SOAP和XML-RPC,
XML-RPC(RPC是遠程調用的意思)有一個開源的產品,其實現的低層也是基于HTTP+POST+XML的方式。我本來打算用純Servlet就解決這個項目了,但老大說這樣不行,可擴展性太差,因為福建是純HTTP、也許廣東就是SOAP或其他的方式,而且其中還存在一些構架設計等等方面的東東。
最后,我得到的要求和提示就是基于XML-RPC來實現這個項目,但XML-RPC是遠程調用的方式,而福建BOSS并非遠程調用,所以需要修改一下XML- RPC的源代碼(老大花了一個下午改好了,而我花了一周多去研讀和完整,水平不是一個數量級的呀,郁悶一下)。修改后的XML-RPC,在遠程調用的實現外,再提供了一個純 HTTP+POST的現實方式。
注:本篇不涉及到修改XML-RPC的源代碼。
2.2 XML- RPC簡介
XML-RPC是Apache中Web Service方面的一個項目,官方網址:http://ws.apache.org/xmlrpc/ ,其中的RPC- remote procedure call是遠程調用的意思,它本身是通過HTTP進行傳輸,用XML做傳遞信息的載體。XML-RPC是一個規范很簡單的軟件框架,也是Web Service的最早的實現,不過現在SOAP似乎比XML-RPC更流行。
上圖反映了XML-RPC的轉輸方式:數據(DATA)和所要調用的方法被封裝到一個XML中,然后由XML-RPC簡單的HTTP+POST到服務端。服務端也裝有 XML-RPC來接收客戶端的XML文件,并將接收到的XML信息進行分解,然后根據XML中記載的信息調用服務端的相應的方法。
2.3 XML-RPC的下載
1、我的環境
WindowsXP SP2 + JDK1.4.2_6 + Eclipse3.0.1
2、XML-RPC
l 版 本:v1.2-b1
l 文件名:xmlrpc-1.2-b1.zip(下載后還要解壓一下,得到xmlrpc-1.2-b1.jar)
l 下 載:http://apache.justdn.org/ws/xmlrpc/
l 其 它:為了追蹤XML-RPC的代碼執行過程,最好把它的源代碼包一起下了,文件名: xmlrpc-1.2-b1-src.zip
3、SAX實現包:xerces
因為XML-RPC中設及到XML文件的解析等操作,它采用了SAX方式,所以它需要一個SAX實現包的支持。SAX的實現有很多種,我選擇了 xerces
l 版 本:v1.4.4 (版本老了點,是2001年的,不過夠用了)
l 文件名:Xerces-J-bin.1.4.4.zip(下載后還要解壓一下,得到xerces.jar)
l 下 載:http://xml.apache.org/dist/xerces-j/
2.4 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>& lt;params><param><value>ChenGang</value></param>&l t;/params></methodCall>
XML的信息是一行,我把它格式化一下,如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<methodCall>
<methodName>hello_id.sayHello</methodName>
<params>
<param>
&nbs p; <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>
&nbs p; <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的方式,這樣擴展性就更大了。
posted on 2007-05-24 11:18
李大嘴 閱讀(1255)
評論(0) 編輯 收藏