一、RPC介紹
什麼是RPC?Remote Procedure Call,遠程過程調用。也就是說,調用過程代碼並不是在調用者本地運行,而是要實現調用者與被調用者二地之間的連接與通信。比較嚴格的定義是:Remote procedure call (RPC) is aprotocol that allows a computer program running on one computer to cause a subroutine on another computer to be executed without the programmer explicitly coding the details for this interaction. When the software in question is written usingobject-oriented principles, RPC may be referred to as remote invocation or remote method invocation. 這樣一講,容易聯想到C/S模式的程序設計,我想是對的。RPC的基本通信模型是基於Client/Server進程間相互通信模型的一種同步通信形式;它對Client提供了遠程服務的過程抽象,其底層消息傳遞操作對Client是透明的。在RPC中,Client即是請求服務的調用者(Caller),而Server則是執行Client的請求而被調用的程序 (Callee)。
下圖是RPC調用協議圖:
首先是建立RPC服務,約定底層的RPC傳輸通道(UDP或是TCP)。客戶端的調用參數根據傳輸前所提供的目的地址及RPC 上層應用程序號,通過底層的RPC傳輸通道轉至相應的服務器,即RPC Application Porgramme Server。客戶端隨即處於等待狀態,以服務器等待應答或Time Out超時信號。當服務器端獲得了請求消息,會根據註冊RPC時告訴RPC系統的程序入口地址執行相應的操作,並將結果返回至客戶端。當一次RPC調用結束後,相應線程發送相應的信號,客戶端程序便繼續運行。
二、基於xml-rpc的應用簡單實現
下載xml-rpc jar包 http://ws.apache.org/xmlrpc/download.html 當前版本:3.1.3
1、業務處理接口
package com.flyoung.xmlrpc; public interface ServicesHandler { public String execute(String str); }
2、業務接口實現
package com.flyoung.xmlrpc; public class HelloHandler implements ServicesHandler { public String execute(String str) { return "hello "+str+"!"; } }
3、客戶端
package com.flyoung.xmlrpc; import java.net.MalformedURLException; import java.net.URL; import java.util.Vector; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; public class TestClient { /** * @param args */ public static void main(String[] args) { try { //配置客戶端 XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); //設置服務器端地址 config.setServerURL(new URL("http://localhost:8080/Rpc/HelloHandler")); //創建XmlRpc客戶端 XmlRpcClient client = new XmlRpcClient(); //綁定以上設置 client.setConfig(config); //創建參數列表 Vector<String> params = new Vector<String>(); params.addElement("flyoung"); //執行XML-RPC 請求 String result =(String) client.execute("HelloHandler.execute", params); System.out.println("result:"+result); } catch (MalformedURLException e) { e.printStackTrace(); } catch (XmlRpcException e) { e.printStackTrace(); } } }
4、服務器端
package com.flyoung.xmlrpc; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcServerConfigImpl; import org.apache.xmlrpc.webserver.XmlRpcServletServer; import com.flyoung.xmlrpc.HelloHandler; public class XmlRpcServicesServlet extends HttpServlet { private XmlRpcServletServer server; @Override public void init(ServletConfig config) throws ServletException { super.init(config); try { //創建XmlRpcServletServer對象 server = new XmlRpcServletServer(); //set up handler mapping of XmlRpcServletServer object PropertyHandlerMapping pmp = new PropertyHandlerMapping(); pmp.addHandler("HelloHandler", HelloHandler.class); server.setHandlerMapping(pmp); //more config of XmlRpcServletServer object XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl)server.getConfig(); serverConfig.setEnabledForExtensions(true); serverConfig.setContentLengthOptional(false); } catch (XmlRpcException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { server.execute(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { server.execute(req, resp); } }
5、xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>XmlRpcServer</servlet-name> <servlet-class>com.flyoung.xmlrpc.XmlRpcServicesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>XmlRpcServer</servlet-name> <url-pattern>/HelloHandler</url-pattern> </servlet-mapping> </web-app>
6、測試結果
result:hello flyoung!
在RPC中,當一個請求到達RPC服務器時,這個請求就包含了一個參數集和一個文本值,通常形成“classname.methodname”的形式。這就向RPC服務器表明,被請求的方法在爲“classname”的類中,名叫“methodname”。然後RPC服務器就去搜索與之相匹配的類和方法,並把它作爲那種方法參數類型的輸入。這裏的參數類型是與RPC請求中的類型是匹配的。一旦匹配成功,這個方法就被調用了,其結果被編碼後返回客戶方。
缺點:
1)XML-RPC的消息系統過於簡單,沒有完整意義上的消息模型
2)XML-RPC調用服務的方式要求直接指定對象和方法,稱不上完整的面向服務的體系
3)XML-RPC服務器端提供的服務實際上是特定對象的某個方法,限制了服務器端的開發