RPC應用的java實現

一、RPC介紹

  什麼是RPCRemote 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服務器端提供的服務實際上是特定對象的某個方法,限制了服務器端的開發 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章