今天在TSS上發(fā)現(xiàn)了XML-RPC的帖子,就粗略的看了些資料,感覺這種輕量級(jí)的跨平臺(tái)遠(yuǎn)程調(diào)用很有意思啊。用起來簡(jiǎn)單,據(jù)說速度也很快(自己沒有試過)。

下面貼一些資料:

 XML-RPC 是工作在 Internet 上的遠(yuǎn)程過程調(diào)用協(xié)議。通俗點(diǎn)講,就是使用 HTTP 協(xié)議交互,交互的載體是 XML 文件。XML-RPC 具體的規(guī)范說 明請(qǐng)參考這里


圖片來自XML-RPC官方網(wǎng)站

XML-RPC 規(guī)范定義了六種數(shù)據(jù)類型,下表是這六種數(shù)據(jù)類型與 Java 的數(shù)據(jù)類型對(duì)應(yīng)表。

XML-RPC Java
<i4> 或 <int> int
<boolean> boolean
<string> java.lang.String
<double> double
<dateTime.iso8601> java.util.Date
<struct> java.util.Hashtable
<array> java.util.Vector
<base64> byte[ ]

XML-RPC 規(guī)范的各種平臺(tái)都有具體實(shí)現(xiàn),XML-RPC 規(guī)范的 Java 實(shí)現(xiàn)都有好幾種,這里我們選擇了 Apache XML-RPC

XML-RPC 服務(wù)端實(shí)現(xiàn)
先定義一個(gè)簡(jiǎn)單業(yè)務(wù)對(duì)象 MyHandler,遠(yuǎn)程客戶端將調(diào)用該對(duì)象的方法,具體代碼如下:

package net.sentom.xmlrpc;

public class MyHandler {
	
	public String sayHello(String str){
		return "Hello," + str;
	}
}

然后定義一個(gè) Servlet 名叫 MyXmlRpcServer,遠(yuǎn)程客戶端通過 HTTP-POST 訪問該 Servlet。

package net.sentom.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.xmlrpc.XmlRpcServer;

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

需要特別說明是:

xmlrpc.addHandler("myHandler", new MyHandler());

為了便于理解,這里可以看成普通的:

MyHandler myHandler = new MyHandler();

最后在web.xml文件中加入以下幾行:

<servlet>
    	<servlet-name>MyXmlRpcServer</servlet-name>
    	<servlet-class>net.sentom.xmlrpc.MyXmlRpcServer</servlet-class>
</servlet>
<servlet-mapping>
    	<servlet-name>MyXmlRpcServer</servlet-name>
    	<url-pattern>/MyXmlRpcServer</url-pattern>
</servlet-mapping>
XML-RPC 客戶端實(shí)現(xiàn)
客戶端相對(duì)簡(jiǎn)單一些,先來一個(gè) Java 客戶端實(shí)現(xiàn) MyXmlRpcClient:

package net.sentom.xmlrpc;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

public class MyXmlRpcClient {
	public static void main(String[] args) {
		try {
			XmlRpcClient xmlrpc = new XmlRpcClient("http://localhost:8080/XMLRPC/MyXmlRpcServer");
			Vector params = new Vector();
			params.addElement("Tom");
			String result = (String) xmlrpc.execute("myHandler.sayHello",params);
			System.out.println(result);
		} catch (MalformedURLException e) {
			System.out.println(e.toString());
		} catch (XmlRpcException e) {
			System.out.println(e.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

http://localhost:8080/XMLRPC/MyXmlRpcServer 為 MyXmlRpcServer 的訪問URL。

String result = (String) xmlrpc.execute("myHandler.sayHello",params);

再來一個(gè) Python 客戶端實(shí)現(xiàn)

import xmlrpclib
url = 'http://localhost:8080/XMLRPC/MyXmlRpcServer';
server = xmlrpclib.Server(url);
print server.myHandler.sayHello('Tom');
來源:http://www.sentom.net 


[原創(chuàng)]xml-rpc入門例程及一個(gè)通用服務(wù)器
一,準(zhǔn)備過程

遠(yuǎn)程過程調(diào)用RPC,基于XML的傳輸方式,當(dāng)然低層API,就不用我們操心了,但必須的軟件還是要有的,先給個(gè)列表清單
JDK1.4.2 不用說了
Xerces解析器  到http://xml.apache.org/上去下載吧,
XML-RPC開發(fā)包, http://ws.apache.org/xmlrpc/上可以下得到

將以上所有的jar包放到開發(fā)環(huán)境的classpath中。

二,Hello World

XML-RPC如果想跑起來,最后需要四個(gè)組件,WEB server, 服務(wù)器類,處理類,客戶類

1.WEB Server.

在我們已經(jīng)下載的XML-RPC包中就有一個(gè)輕型級(jí)的WEB SERVER。
在程序中,我們只需要簡(jiǎn)單的用以下語句就可以啟動(dòng)。
//建立一個(gè)對(duì)象,傳輸一個(gè)端口
WebServer server = new WebServer(Integer.parseInt("8989"));     
//啟動(dòng)
server.start();

2.編寫處理類

處理類相當(dāng)RMI中的遠(yuǎn)程類,只不過在這里更輕量類,無須任何接口.

在這個(gè)類中包含一個(gè)或多個(gè)公有方法以供遠(yuǎn)程的客戶端來調(diào)用。

public class HelloHandler {

public String sayHello(String name) {
return "Hello " + name;
}


}


3.服務(wù)器

負(fù)責(zé)調(diào)用以上代碼來啟動(dòng)用服務(wù)器,同時(shí)還要將遠(yuǎn)程對(duì)象綁定到該服務(wù)器上。

import java.io.IOException;
//引入必須的包,當(dāng)然你的xml-rpc的包應(yīng)該在classpath中
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpc;
public class HelloServer {
 /**
主方法
     */
    public static void main(String[] args) {
   
        try {
            // 使用Xerces的XML解析器
            XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser");
            // 給出提示,并在端8989上啟動(dòng)服務(wù)器
            System.out.println("Starting XML-RPC Server...");
            WebServer server = new WebServer(Integer.parseInt("8989"));     
            server.start();     
           
            // 將HelloHandler類的實(shí)例編定到WEB SERVER上,hello是該處理類的標(biāo)識(shí),在客戶端調(diào)用時(shí)要用得到
            server.addHandler("hello", new HelloHandler());
            System.out.println(
                "Registered HelloHandler class to \"hello\"");        
              
         
                       
        } catch (ClassNotFoundException e) {
            System.out.println("Could not locate SAX Driver");
        } catch (Exception e) {
            System.out.println("Could not start server: " +
                e.getMessage());
        }                               
    }
}

4.客戶端
根據(jù)“標(biāo)識(shí)名.方法名“來定位遠(yuǎn)程的處理方法。

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;

//導(dǎo)入必須的包
import org.apache.xmlrpc.XmlRpc;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;


public class HelloClient {
 

    public static void main(String args[]) {
  
      String yourname="liu xiaobai";
        try {
            // 使用 Apache Xerces SAX 解析器
            XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser");
           
            // 定位遠(yuǎn)程服務(wù)器,http://主機(jī)地址:端口號(hào), 8989是上文服務(wù)器啟動(dòng)時(shí)用的端口
            XmlRpcClient client =
                new XmlRpcClient("http://localhost:8989/"); 
               
            // 創(chuàng)建調(diào)用請(qǐng)求,方法的參數(shù)列表如果一個(gè)Vector對(duì)象來存儲(chǔ)。
            Vector params = new Vector();           
            params.addElement(yourname);
           
            // 發(fā)出請(qǐng)求,并返回結(jié)果,execute需要兩個(gè)參數(shù),第一個(gè)參數(shù)用“標(biāo)識(shí)名.方法名”,第二參數(shù)是一個(gè) 剛剛建立的向量對(duì)象


            String result =
               (String)client.execute("hello.sayHello", params);
            System.out.println("Response from server: " + result);

       
         
        } catch (ClassNotFoundException e) {
            System.out.println("Could not locate SAX Driver");
        } catch (MalformedURLException e) {
            System.out.println(
                "Incorrect URL for XML-RPC server format: " +
                e.getMessage());
        } catch (XmlRpcException e) {
            System.out.println("XML-RPC Exception: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO Exception: " + e.getMessage());
        }       
    }
}

5,編譯以上代碼,要確保解析器,XMP-RPC開發(fā)包的jar文件在classpath中。

運(yùn)行服務(wù)器

   java  HelloServer

運(yùn)行客戶端

  java HelloClient

 

6.一個(gè)通用的XML服務(wù)器

功能描述:通過配置文件來配置要加載的處理器

1.配置文件的名稱及位置

名字:config.properties

類文件的根目錄中,如果你類是默認(rèn)包,那么就是同一個(gè)目錄;如果類的包名是com.hello,那么該文件應(yīng)該與com目錄放在同一級(jí)中。

內(nèi)容:

#標(biāo)識(shí)名=類名
hello=javaxml2.HelloHandler


2.通用的源代碼

import java.io.*;
import org.apache.xmlrpc.*;
import java.util.Properties;
import java.util.Enumeration;
import java.util.Hashtable;
public class MyLightXMLServer
{
   private WebServer server;
   private int port;
   private String configfile;
  
   public MyLightXMLServer(int port,String config)
   {
    this.port=port;
    this.configfile=config;
    }
    //啟動(dòng)服務(wù)器
    public void start() throws IOException,ClassNotFoundException,Exception
    {
     XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser");
     System.out.println("starting up xml-rpc server...");
     server=new WebServer(port);
     //調(diào)用注冊(cè)函數(shù)
     registerHandlers(this.getHandlers());
     server.start();
     }
    
    public void registerHandlers(Properties handlers) throws Exception
    {
     Enumeration enum=handlers.propertyNames();
     while(enum.hasMoreElements())
     {
      String temp=(String)enum.nextElement();
      String tempcls=(String)handlers.get(temp);
      Class cls=Class.forName(tempcls);
      server.addHandler(temp,cls.newInstance());
     
      }
     }
    
    public Properties getHandlers()
    {
     try
     {
       Properties properties=new Properties();
       properties.load(new FileInputStream(new File("config.properties")));
      
        return properties;
      }
     catch(Exception e)
     {
      e.printStackTrace();
      }
     return null;
     }
   
    public static void main(String args[])
    {
     String port="8989";
     String configfile="";
     MyLightXMLServer server=new MyLightXMLServer(Integer.parseInt(port),configfile);
     try
     {
      server.start();
      }
     catch(Exception e)
     {e.printStackTrace();}
     }
   
   
 }

將MyLightXMLServer .java編譯并運(yùn)行之后,該服務(wù)器會(huì)在配置文件中加載該處理器


然后可以直接執(zhí)行HelloClient

java HelloClient