前些天無(wú)意中發(fā)現(xiàn)了XML-RPC(不過(guò)笑我才發(fā)現(xiàn)啊
),總想找個(gè)機(jī)會(huì)擺弄擺弄。畢業(yè)論文基本上弄完了,所以決定今天把它弄明白。
XML-RPC的最大用處,我首先想到的是瀏覽器在不刷新頁(yè)面的情況下與服務(wù)器通信,請(qǐng)求數(shù)據(jù)。下面我就說(shuō)一下我用XML-RPC是怎么實(shí)現(xiàn)的。
第一步:選擇XML-RPC實(shí)現(xiàn)。
XML-RPC的一個(gè)很大優(yōu)勢(shì)就是 它是一個(gè)標(biāo)準(zhǔn),并且各種開(kāi)發(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ú)開(kāi)個(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的引用嗎?就這么寫吧。可別把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è)例子中我開(kāi)始有兩個(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)換了。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元


?