第一步:選擇XML-RPC實(shí)現(xiàn)。
XML-RPC的一個(gè)很大優(yōu)勢(shì)就是 它是一個(gè)標(biāo)準(zhǔn),并且各種開發(fā)環(huán)境下都有實(shí)現(xiàn)(酷),這是它能夠輕松跨平臺(tái)的原因。
javascript有3個(gè)實(shí)現(xiàn)。我看了一下最好的應(yīng)該是jsolait(JavaScript o Lait)的實(shí)現(xiàn)了。因?yàn)樗粌H僅是一個(gè)xml-rpc的實(shí)現(xiàn),除此之外還有很多javascript庫(kù),詳細(xì)內(nèi)容請(qǐng)看這里(http://jsolait.net/)。
java的實(shí)現(xiàn)就更多了,我當(dāng)然毫不猶豫地選擇apache的。詳細(xì)內(nèi)容看這里(http://ws.apache.org/xmlrpc/

第二步:建立服務(wù)。
用java建立xml-rpc有兩種方式,一種是單獨(dú)開個(gè)端口,一種是用servlet。我們客戶端是用javascript,那么服務(wù)端用servlet是再好不過(guò)的了。
如何使用apache的xml-rpc,請(qǐng)?jiān)敿?xì)看apache的資料。(大哥你不會(huì)連servlet也不會(huì)建吧,那你還是不要往下看了)。
代碼如下:
這是一個(gè)sayHello的服務(wù)類:

public class HelloService {
 
 
public String sayHello(String name){
  
return "Hello: "+name+" !";
 }


}



下面是一個(gè)Math服務(wù)類:

public class MathService {
 
public double add(Vector v){
  
double a = Double.parseDouble((String)v.get(0));
  
double b = Double.parseDouble((String)v.get(1));
  
return a+b;
 }

 
 
public double mult(Vector v){
  
double a = Double.parseDouble((String)v.get(0));
  
double b = Double.parseDouble((String)v.get(1));
  
return a*b;
 }

}


接著是Servlet啦,作為RPC Server用的,這段代碼比較經(jīng)典,很多資料上都有。

public class RpcServer extends HttpServlet {
 
protected void doPost(HttpServletRequest request,
   HttpServletResponse response) throws ServletException, IOException 
{
  XmlRpcServer xmlrpc 
= new XmlRpcServer();
  xmlrpc.addHandler(
"HelloService"new HelloService());
  xmlrpc.addHandler(
"MathService",new MathService());
  
byte[] result = xmlrpc.execute(request.getInputStream());
  response.setContentType(
"text/xml");
  response.setContentLength(result.length);
  OutputStream 
out = response.getOutputStream();
  
out.write(result);
  
out.flush();
 }

}

 

主要是這三句:
XmlRpcServer xmlrpc = new XmlRpcServer();
xmlrpc.addHandler("HelloService", new HelloService());
xmlrpc.addHandler("MathService",new MathService());
一定要記牢Handler的名字,就是第一個(gè)參數(shù),因?yàn)榭蛻舳司涂克麃?lái)表示要調(diào)用的方法呢。

行了現(xiàn)在可以在web.xml中寫入配置了:

 <servlet>
  
<servlet-name>RpcServer</servlet-name>
  
<servlet-class>org.mstar.rpc.RpcServer</servlet-class>
 
</servlet>
 
<servlet-mapping>
  
<servlet-name>RpcServer</servlet-name>
  
<url-pattern>/RpcServer</url-pattern>
 
</servlet-mapping>


至此,服務(wù)端的工作已經(jīng)完成,啟動(dòng)應(yīng)用服務(wù)器就行了。

下面是javacript的實(shí)現(xiàn),這也是難點(diǎn)(其實(shí)不難理解,只是沒(méi)有中文材料)。
把jsolait的庫(kù)下來(lái)以后解壓縮,得到一些js文件,具體我就不說(shuō)了。

建立一個(gè)html文件:

<html>
<head>
<title>XML-RPC</title>
<script type="text/javascript" src="./js/init.js"></script>
<script type="text/javascript" src="./js/lib/urllib.js"></script>
<script type="text/javascript" src="./js/lib/xml.js"></script>
<script type="text/javascript" src="./js/lib/xmlrpc.js"></script>
<script type="text/javascript" src="./js/hello.js"></script>
</head>
a:
<input type="text" id="a" /><br>
b:
<input type="text" id="b" /><br>
<input type="button" id="do1" value="a+b" onclick="add()"/>
<input type="button" id="do2" value="say" onclick="hello()"/>
<input type="text" id="result" />
</html>


注意到前面那一堆javascript的引用嗎?就這么寫吧??蓜e把hello.js當(dāng)成solait的東西啦(看名字也知道啦),你是找不到的。這是我們自己寫的:
hello.js

hello = function(){
 
var xmlrpc=null;
 
try{
     
var xmlrpc = importModule("xmlrpc");
 }
catch(e){
     reportException(e);
     
throw "importing of xmlrpc module failed.";
 }
 
var addr = "http://localhost:8080/Rpc/RpcServer";
 
var methods = ["HelloService.sayHello"];
 
var rslt;
 
 
try{
        
var service = new xmlrpc.ServiceProxy(addr, methods);
        rslt 
= service.HelloService.sayHello("MTY");
    }
catch(e){
        
var em;
        
if(e.toTraceString){
            em 
= e.toTraceString();
        }
else{
            em 
= e.message;
        }
        rslt 
= "Error trace: \n\n" + em;
    }
 document.getElementById(
"result").value=rslt;
}
add 
= function(){
 
var xmlrpc=null;
 
var a = document.getElementById("a").value;
 
var b = document.getElementById("b").value;
 
var params = new Array();
 params[
0= a;
 params[
1= b;
 
try{
     
var xmlrpc = importModule("xmlrpc");
 }
catch(e){
     reportException(e);
     
throw "importing of xmlrpc module failed.";
 }
 
var addr = "http://localhost:8080/Rpc/RpcServer";
 
var methods = ["HelloService.sayHello","MathService.add"];
 
var rslt;
 
 
try{
        
var service = new xmlrpc.ServiceProxy(addr, methods);
        rslt 
= service.MathService.add(params);
    }
catch(e){
        
var em;
        
if(e.toTraceString){
            em 
= e.toTraceString();
        }
else{
            em 
= e.message;
        }
        rslt 
= "Error trace: \n\n" + em;
    }
 document.getElementById(
"result").value=rslt;
}


這個(gè)js文件中有兩個(gè)函數(shù),一個(gè)負(fù)責(zé)從sayhello,一個(gè)負(fù)責(zé)加法運(yùn)算。
這里需要一些解釋的地方:
1、
 var xmlrpc=null;
 try{
     var xmlrpc = importModule("xmlrpc");
 }catch(e){
     reportException(e);
     throw "importing of xmlrpc module failed.";
 }
這里是把xmlrpc模塊引進(jìn)來(lái),你也就這么寫吧,我也不知道為什么。
2、
 var addr = "http://localhost:8080/Rpc/RpcServer";
 var methods = ["HelloService.sayHello"];
定義服務(wù)地址和要用的方法名。規(guī)則大概你也能看懂:Handler名.方法名。這里的Handler名就是你在xmlrpcServer中注冊(cè)名,就是我上面讓你記住的那個(gè)。方法名就是那個(gè)類自己的方法名。注意,methods是一個(gè)數(shù)組,所以可以寫多個(gè)方法,如第二個(gè)例子。var methods = ["HelloService.sayHello","MathService.add"];
3、
    try{
        var service = new xmlrpc.ServiceProxy(addr, methods);
        rslt = service.HelloService.sayHello("MTY");
    }catch(e){
        var em;
        if(e.toTraceString){
            em = e.toTraceString();
        }else{
            em = e.message;
        }
        rslt = "Error trace: \n\n" + em;
    }
通過(guò)new xmlrpc.ServiceProxy(addr, methods);得到服務(wù)代理。
然后調(diào)用服務(wù)的方法就行了,方法就是代理.Handler名.方法名(參數(shù))。好像參數(shù)只能有一個(gè),在第二個(gè)例子中我開始有兩個(gè)參數(shù)a,b會(huì)發(fā)生錯(cuò)誤。怎么辦?沒(méi)辦法,在javascript用Array傳參數(shù),在java用Vector接參數(shù)(為什么用Vector,因?yàn)閤ml-rpc規(guī)范中的Array,apache使用Vector實(shí)現(xiàn)的,為什么javascript不用Vector,因?yàn)閖s沒(méi)有Vector,且js的的Array是可變長(zhǎng)的)。當(dāng)然這就需要很多java端類型轉(zhuǎn)換工作,js是弱類型的就不用轉(zhuǎn)換了。