今天在TSS上發現了XML-RPC的帖子,就粗略的看了些資料,感覺這種輕量級的跨平臺遠程調用很有意思啊。用起來簡單,據說速度也很快(自己沒有試過)。

下面貼一些資料:

 XML-RPC 是工作在 Internet 上的遠程過程調用協議。通俗點講,就是使用 HTTP 協議交互,交互的載體是 XML 文件。XML-RPC 具體的規范說 明請參考這里


圖片來自XML-RPC官方網站

XML-RPC 規范定義了六種數據類型,下表是這六種數據類型與 Java 的數據類型對應表。

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 規范的各種平臺都有具體實現,XML-RPC 規范的 Java 實現都有好幾種,這里我們選擇了 Apache XML-RPC

XML-RPC 服務端實現
先定義一個簡單業務對象 MyHandler,遠程客戶端將調用該對象的方法,具體代碼如下:

package net.sentom.xmlrpc;

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

然后定義一個 Servlet 名叫 MyXmlRpcServer,遠程客戶端通過 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 客戶端實現
客戶端相對簡單一些,先來一個 Java 客戶端實現 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);

再來一個 Python 客戶端實現

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


[原創]xml-rpc入門例程及一個通用服務器
一,準備過程

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

將以上所有的jar包放到開發環境的classpath中。

二,Hello World

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

1.WEB Server.

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

2.編寫處理類

處理類相當RMI中的遠程類,只不過在這里更輕量類,無須任何接口.

在這個類中包含一個或多個公有方法以供遠程的客戶端來調用。

public class HelloHandler {

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


}


3.服務器

負責調用以上代碼來啟動用服務器,同時還要將遠程對象綁定到該服務器上。

import java.io.IOException;
//引入必須的包,當然你的xml-rpc的包應該在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上啟動服務器
            System.out.println("Starting XML-RPC Server...");
            WebServer server = new WebServer(Integer.parseInt("8989"));     
            server.start();     
           
            // 將HelloHandler類的實例編定到WEB SERVER上,hello是該處理類的標識,在客戶端調用時要用得到
            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.客戶端
根據“標識名.方法名“來定位遠程的處理方法。

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

//導入必須的包
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");
           
            // 定位遠程服務器,http://主機地址:端口號, 8989是上文服務器啟動時用的端口
            XmlRpcClient client =
                new XmlRpcClient("http://localhost:8989/"); 
               
            // 創建調用請求,方法的參數列表如果一個Vector對象來存儲。
            Vector params = new Vector();           
            params.addElement(yourname);
           
            // 發出請求,并返回結果,execute需要兩個參數,第一個參數用“標識名.方法名”,第二參數是一個 剛剛建立的向量對象


            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開發包的jar文件在classpath中。

運行服務器

   java  HelloServer

運行客戶端

  java HelloClient

 

6.一個通用的XML服務器

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

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

名字:config.properties

類文件的根目錄中,如果你類是默認包,那么就是同一個目錄;如果類的包名是com.hello,那么該文件應該與com目錄放在同一級中。

內容:

#標識名=類名
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;
    }
    //啟動服務器
    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);
     //調用注冊函數
     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編譯并運行之后,該服務器會在配置文件中加載該處理器


然后可以直接執行HelloClient

java HelloClient