<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    一 .RMI概述
    RMI(Remote Method Invocation)
        RMI是分布式對象軟件包,它簡化了在多臺計算機上的JAVA應(yīng)用之間的通信。必須在jdk1.1以上

    RMI用到的類
         java.rmi.Remote                   所有可以被遠程調(diào)用的對象都必須實現(xiàn)該接口
         java.rmi.server.UnicastRemoteObject  所有可以被遠程調(diào)用的對象都必須擴展該類
     
    什么是RMI
        遠程方法調(diào)用是一種計算機之間對象互相調(diào)用對方函數(shù),啟動對方進程的一種機制,
    使用這種機制,某一臺計算機上的對象在調(diào)用另外一臺計算機上的方法時,使用的程
    序語法規(guī)則和在本地機上對象間的方法調(diào)用的語法規(guī)則一樣。

    優(yōu)點
    這種機制給分布計算的系統(tǒng)設(shè)計、編程都帶來了極大的方便。
    只要按照RMI規(guī)則設(shè)計程序,可以不必再過問在RMI之下的網(wǎng)絡(luò)細節(jié)了,如:TCP和Socket等等。
    任意兩臺計算機之間的通訊完全由RMI負責(zé)。調(diào)用遠程計算機上的對象就像本地對象一樣方便。
     
    1、面向?qū)ο螅?br /> RMI可將完整的對象作為參數(shù)和返回值進行傳遞,而不僅僅是預(yù)定義的數(shù)據(jù)類型。
    也就是說,可以將類似Java哈西表這樣的復(fù)雜類型作為一個參數(shù)進行傳遞。
     
    2、可移動屬性:
    RMI可將屬性從客戶機移動到服務(wù)器,或者從服務(wù)器移動到客戶機。
     
    3、設(shè)計方式:
    對象傳遞功能使您可以在分布式計算中充分利用面向?qū)ο蠹夹g(shù)的強大功能,如二層和三層結(jié)構(gòu)系統(tǒng)。
    如果用戶能夠傳遞屬性,那么就可以在自己的解決方案中使用面向?qū)ο蟮脑O(shè)計方式。
    所有面向?qū)ο蟮脑O(shè)計方式無不依靠不同的屬性來發(fā)揮功能,如果不能傳遞完整的對象——包括實現(xiàn)和類型
    ——就會失去設(shè)計方式上所提供的優(yōu)點。
     
    4、安全性:
    RMI使用Java內(nèi)置的安全機制保證下載執(zhí)行程序時用戶系統(tǒng)的安全。
    RMI使用專門為保護系統(tǒng)免遭惡意小程序侵害而設(shè)計的安全管理程序。
    5、便于編寫和使用
    RMI使得Java遠程服務(wù)程序和訪問這些服務(wù)程序的Java客戶程序的編寫工作變得輕松、簡單。
    遠程接口實際上就是Java接口。
    為了實現(xiàn)RMI的功能必須創(chuàng)建遠程對象任何可以被遠程調(diào)用的對象必須實現(xiàn)遠程接口。但遠程
    接口本身并不包含任何方法。因而需要創(chuàng)建一個新的接口來擴展遠程接口。
    新接口將包含所有可以遠程調(diào)用的方法。遠程對象必須實現(xiàn)這個新接口,由于新的接口擴展了
    遠程接口,實現(xiàn)了新接口,就滿足了遠程對象對實現(xiàn)遠程接口的要求,所實現(xiàn)的每個對象都將
    作為遠程對象引用。
     
    個人總結(jié):
        RMI說白了,就是提供了一種遠程的方法調(diào)用。 這種調(diào)用簡單方便,可以傳遞復(fù)雜java對象。現(xiàn)在流行的j2ee中的EJB的底層實現(xiàn)技術(shù)就是RMI,EJB的調(diào)用就是經(jīng)過封裝的,更高級的RMI調(diào)用。


    下面我們就來寫一個RMI的程序:
     
    一.創(chuàng)建RMI程序的6個步驟:
    1、定義一個遠程接口的接口,該接口中的每一個方法必須聲明它將產(chǎn)生一個RemoteException異常。
    2、定義一個實現(xiàn)該接口的類。
    3、使用RMIC程序生成遠程實現(xiàn)所需的殘根和框架。
    4、創(chuàng)建一個服務(wù)器,用于發(fā)布2中寫好的類。
    5. 創(chuàng)建一個客戶程序進行RMI調(diào)用。
    6、啟動rmiRegistry并運行自己的遠程服務(wù)器和客戶程序。
     
    二. 程序詳細說明
     
    1.定義一個遠程接口的接口,該接口中的每一個方法必須聲明它將產(chǎn)生一個RemoteException異常。
     
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    public interface I_Hello extends java.rmi.Remote   //需要從Remote繼承
    {
           public String SayHello() throws RemoteException;   //需要拋出remote異常
    }

       上面例子我們定義一個返回字符串的遠程方法 SayHello(),這個遠程接口 I_Hello必須是public的 ,它必須從java.rmi.Remote繼承而來,接口中的每一個方法都必須拋出遠程異常java.rmi.RemoteException。

    拋出這個異常的原因
    由于任何遠程方法調(diào)用實際上要進行許多低級網(wǎng)絡(luò)操作,因此網(wǎng)絡(luò)錯誤可能在調(diào)用過程中隨時發(fā)生。
    因此,所有的RMI操作都應(yīng)放到try-catch塊中。
      
    2、定義一個實現(xiàn)該接口的類。
     
     import java.io.PrintStream;
    import java.rmi.*;
    import java.rmi.server.UnicastRemoteObject;
     
    public class Hello extends UnicastRemoteObject   //必須從UnicastRemoteObject  繼承
                       implements I_Hello
    {
            public Hello() throws RemoteException     //需要一個拋出Remote異常的默認初始化方法
            {
            }
     
            public String SayHello()     //這個是實現(xiàn)I_Hello接口的方法
            {
               return "Hello world !!";
            }
    }
     
    實現(xiàn)接口的類必須繼承UnicastRemoteObject類。
    擴展java.rmi.server.UnicastRemoteObject
    UnicastRemoteObject顧名思義,是讓客戶機與服務(wù)器對象實例建立一對一的連接。
     
    3、使用RMIC程序生成遠程實現(xiàn)所需的殘根Stub 和 框架。
       2中的Hello 編譯好以后,我們就可以用RMIC命令來生成殘根Stub
       在Dos窗口里,到Hello.class 所在目錄,運行以下命令:
       rmic Hello
       
       命令執(zhí)行完以后,將會在當(dāng)前目錄生成一個 Hello_Stub.class 這個就是我們遠程調(diào)用時需要的類
     
    參考:
    在RMI中,客戶機上生成的調(diào)動調(diào)用參數(shù)和反調(diào)動返回值的代碼稱為殘根。有的書上稱這部分代碼為“主干”。
    服務(wù)器上生成的反調(diào)動調(diào)用參數(shù)和進行實際方法調(diào)用調(diào)動返回值的代碼稱為框架。
    生成殘根和框架的工具
    Rmic命令行工具(RMI Compiler)
    格式:
    Rmic classname
     
    4、創(chuàng)建一個服務(wù)器,用于發(fā)布2中寫好的類。
     
        import java.rmi.*;
    public class RMI_Server
    {
        public static void main(String[] args)
        {
            try
            {
                Hello hello = new Hello();                //實例化要發(fā)布的類
                Naming.rebind("RMI_Hello", hello);      //綁定RMI名稱 進行發(fā)布
                System.out.println("=== Hello server Ready === ");
            }
            catch(Exception exception)
            {
                exception.printStackTrace();
            }
        }
    }
     
    5. 創(chuàng)建一個客戶程序進行RMI調(diào)用。
     
    import java.rmi.*;
    public class RMI_Client {
        public static void main(String[] args) {
            try
            {
               I_Hello hello = (I_Hello) Naming.lookup("RMI_Hello");  //通過RMI名稱查找遠程對象
                System.out.println(hello.SayHello());                        //調(diào)用遠程對象的方法
            } catch (Exception e)
            {
              e.printStackTrace();
            }
        }

    }

    Naming.lookup("RMI_Hello") 其中的參數(shù)“RMI_Hello”只是針對本機的RMI查找,如果是異地的RMI調(diào)用請參照  rmi://127.0.0.1:1099/RMI_Hello       端口1099是默認的RMI端口,如果你啟動 rmiregistry 的時候(見第6點)沒有指定特殊的端口號,默認就是1099
     
    到此 我們 所有的代碼編寫都完成了,不過不要急著去運行,請跟隨第6點去運行,因為rmi 調(diào)用還會遇到一些特別的情況,偶花了牛勁,才找到原因的,許多剛用RMI的人,常常被這些問題搞得吐血
     
    6、啟動rmiRegistry并運行自己的遠程服務(wù)器和客戶程序。
     1)服務(wù)器的運行
        先在DOS下運行 rmiregistry     這個命令是開啟RMI的注冊服務(wù),開啟以后我們的server程序才能調(diào)用rebing方法發(fā)布我們的類
     
        然后,運行我們的server程序  RMI_Server    這里是最容易出錯的,參見下面注意事項。
         注意:
             如果提示找不到Stub類,這個需要用下面的命令來運行
     java.exe -Djava.rmi.server.codebase=file:/E:\MIS_Interface\momo\TestEasy\classes/  RMI_Server
     
    藍字部分指定了stub類的路徑。
     
      有人會問,我已經(jīng)把stub 通過-classpath 加到類路徑里面了,為什么還沒有提示這個錯誤呢?原因是這樣的: 這里提示的找不到stub類,不是由你寫的RMI_Server這個程序引起的,是由rmi注冊服務(wù)器報告的異常,也就是我們前面啟動的 rmiregistry ,因為你寫的RMI_Server 要求RMI注冊服務(wù)器注冊一個新的類,自然RMI服務(wù)器必須知道你的類放在哪里,所以我們通過  -Djava.rmi.server.codebase 這個運行參數(shù)來指定
      你也可以通過修改操作系統(tǒng)的classpath 環(huán)境變量 來指定stub的位置,只不過太麻煩
     
    2) 客戶端的運行
          直接運行RMI_Client  即可  注意 把 Stub 和 接口 I_Hello 加到類路徑里
      
        通常第一次運行 客戶端都會報一個錯誤:   Access  XXXX 不記得具體的了,反正就是“訪問權(quán)限限制”, 這是因為RMI的服務(wù)需要授權(quán),外部程序才能訪問,所以我們要改動 jre的安全配置文件,來開放權(quán)限,  具體如下:
     
       打開你的jdk目錄下的這個文件 C:\Program Files\Java\jdk1.5.0_04\jre\lib\security\java.policy
    在文件最后加入下面代碼:
     grant {
               permission java.net.SocketPermission "*:1024-65535",
                    "connect,accept";
               permission java.net.SocketPermission "*:80","connect";
            };
    此代碼,開放了端口的connect訪問權(quán)限
     
    注意 你應(yīng)該修改服務(wù)器那臺機子的安全配置文件,也就是你運行 rmiregistry 和 RMI_Server的機子
    另外,很多人修改完以后,仍然報這個錯誤,多數(shù)情況是由于你沒有修改到正確的jdk 下的文件,而是修改到其他jdk的文件, 我們安裝oracle , Weblogic等等軟件的時候都會自帶一個 jdk,他們會自動在操作系統(tǒng)的環(huán)境變量里面 加入jdk的路徑,所以,你先要確定你運行服務(wù)器端程序是用哪個jdk,再修改這個jdk下的配置文件,確定當(dāng)前jdk的路徑很簡單  開始 -》運行-》rmiregistry 看看這個DOS窗口標(biāo)題 的路徑,就是你當(dāng)前系統(tǒng)默認jdk的路徑了
     
    客戶端正常運行以后,就會出現(xiàn)以下結(jié)果:
    Hello world !!

    這些字符是通過RMI調(diào)用遠程服務(wù)器的類返回的結(jié)果 

    RMI 實例

     

    Calculator.java

    import java.rmi.Remote;

    public interface Calculator  extends Remote 


     
        
    public long add(long a, long b)  throws java.rmi.RemoteException ;
     
        
    public long sub(long a, long b)  throws java.rmi.RemoteException ; 
       
        
    public long mul(long a, long b)  throws java.rmi.RemoteException ; 
        
        
    public long div(long a, long b)  throws java.rmi.RemoteException ; 
      
    }
     

    CalculatorClient.java:

    import java.rmi.Naming; 
    import java.rmi.RemoteException; 
    import java.net.MalformedURLException; 
    import java.rmi.NotBoundException; 

    public class CalculatorClient 

        
    public static void main(String[] args) 
            
    try 
             Calculator c 
    = (Calculator)
                               Naming.lookup(
                     
    "rmi://localhost/CalculatorService"); 
                System.out.println( c.sub(
    43) ); 
                System.out.println( c.add(
    45) ); 
                System.out.println( c.mul(
    36) ); 
                System.out.println( c.div(
    93) ); 
            }
     
            
    catch (MalformedURLException murle) 
                System.out.println(); 
                System.out.println(
                  
    "MalformedURLException"); 
                System.out.println(murle); 
            }
     
            
    catch (RemoteException re) 
                System.out.println(); 
                System.out.println(
                            
    "RemoteException"); 
                System.out.println(re); 
            }
     
            
    catch (NotBoundException nbe) 
                System.out.println(); 
                System.out.println(
                           
    "NotBoundException"); 
                System.out.println(nbe); 
            }
     
            
    catch (
                java.lang.ArithmeticException
                                          ae) 

                System.out.println(); 
                System.out.println(
                 
    "java.lang.ArithmeticException"); 
                System.out.println(ae); 
            }
     
        }
     
    }
     


    CalculatorImpl.java:

    import java.rmi.server.UnicastRemoteObject;

    public class CalculatorImpl extends UnicastRemoteObject implements Calculator


        
    // 這個實現(xiàn)必須有一個顯式的構(gòu)造函數(shù),并且要拋出一個RemoteException異常 
        public CalculatorImpl() 
            
    throws java.rmi.RemoteException 
            
    super(); 
        }
     

        
    public long add(long a, long b) 
            
    throws java.rmi.RemoteException 
            
    return a + b; 
        }
     

        
    public long sub(long a, long b) 
            
    throws java.rmi.RemoteException 
            
    return a - b; 
        }
     

        
    public long mul(long a, long b) 
            
    throws java.rmi.RemoteException 
            
    return a * b; 
        }
     

        
    public long div(long a, long b) 
            
    throws java.rmi.RemoteException 
            
    return a / b; 
        }
     
    }
     


    CalculatorRemoteClient.java:


    import java.rmi.Naming; 
    import java.rmi.RemoteException; 
    import java.net.MalformedURLException; 
    import java.rmi.NotBoundException; 

    public class CalculatorRemoteClient 

        
    public static void main(String[] args) 
            
    try 
                Calculator c 
    = (Calculator)
                               Naming.lookup(
                     
    "rmi://10.10.11.209/CalculatorService"); 
                System.out.println( c.sub(
    43) ); 
                System.out.println( c.add(
    45) ); 
                System.out.println( c.mul(
    36) ); 
                System.out.println( c.div(
    93) ); 
            }
     
            
    catch (MalformedURLException murle) 
                System.out.println(); 
                System.out.println(
                  
    "MalformedURLException"); 
                System.out.println(murle); 
            }
     
            
    catch (RemoteException re) 
                System.out.println(); 
                System.out.println(
                            
    "RemoteException"); 
                System.out.println(re); 
            }
     
            
    catch (NotBoundException nbe) 
                System.out.println(); 
                System.out.println(
                           
    "NotBoundException"); 
                System.out.println(nbe); 
            }
     
            
    catch (
                java.lang.ArithmeticException
                                          ae) 

                System.out.println(); 
                System.out.println(
                 
    "java.lang.ArithmeticException"); 
                System.out.println(ae); 
            }
     
        }
     
    }
     


    CalculatorServer.java:

    import java.rmi.Naming;

    public class CalculatorServer {

       
    public CalculatorServer() {
         
    try {
           Calculator c 
    = new CalculatorImpl();
           Naming.rebind(
    "rmi://localhost:1099/CalculatorService", c);
         }
     catch (Exception e) {
           System.out.println(
    "Trouble: " + e);
         }

       }


       
    public static void main(String args[]) {
         
    new CalculatorServer();
       }

    }


     

    第二個

    服務(wù)端代碼

    Multi.java
    import java.rmi.*;

    public interface Multi extends Remote {
        
    int multi(int a, int b) throws RemoteException;
    }



    Plus.java
    import java.rmi.*;

    public interface Plus extends Remote{
        
    int plus(int a, int b) throws RemoteException;
    }


    MultiImpl.java
    import java.rmi.*;
    import java.rmi.server.UnicastRemoteObject;

    public class MultiImpl extends UnicastRemoteObject implements Multi{
        
    private String name;
        
    public MultiImpl(String s) throws Exception{
            
    super();
            name 
    = s;
        }

        
        
    public int multi(int a, int b) throws RemoteException {
            System.out.println(
    "Invoke the multiply");
            
    return (a * b);
        }

    }


    PlusImpl.java
    import java.rmi.*;
    import java.rmi.server.UnicastRemoteObject;

    public class PlusImpl extends UnicastRemoteObject implements Plus {
        
    private String name;
        
    public PlusImpl (String s) throws RemoteException {
            
    super();
            name 
    = s;
        }

        
        
    public int plus(int a, int b) throws RemoteException {
            System.out.println(
    "Invoke the add");
            
    return (a + b);
        }

    }


    CMSServer.java
    import java.rmi.*;

    public class CMSServer {
        
    public CMSServer(){
            
    super();
        }

        
        
    public static void main (String[] args) {
            
    //SYstem.setSecurityManager(new RMISecurityManager());
            try{
                
    new CMSServer();
                MultiImpl mI 
    = new MultiImpl("MultiServer");
                PlusImpl pI 
    = new PlusImpl("PlusServer");
                
                Naming.rebind(
    "pluscxx",pI);
                Naming.rebind(
    "multicxx",mI);
                System.out.println(
    "pluscxx and multicxx bound in registry");
            
            }
     catch(Exception e) {
                System.out.println(
    "pluscxx and multicxx err: " + e.getMessage());
            }

        }

    }


    客戶端代碼

    Multi.java
    import java.rmi.*;

    public interface Multi extends Remote {
        
    int multi(int a, int b) throws RemoteException;
    }


    Plus.java
    import java.rmi.*;

    public interface Plus extends Remote{
        
    int plus(int a, int b) throws RemoteException;
    }


    Frame1.java
    import java.awt.*;
    import java.rmi.*;
    import java.awt.event.*;
    import javax.swing.*;


    public class Frame1 extends JFrame {
        Container container;
        
        
    private JTextField jTextFields[];
        
    private JLabel jLabels[];
        
    private JButton jButton;
        
    private String[] labelsName = {"    Num1""    Num2""    Num3" ,"    plus then multiply" };
        
        
        
    public Frame1() {
            
    super("sigle client multi server");
            
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
    //enableEvents(AWTEvent.WINDOW_EVENT_MASK);
            container = getContentPane();
            container.setLayout(
    new GridLayout(5,2,10,10));
            jLabels 
    = new JLabel[4];
            jTextFields 
    = new JTextField[4];
            
    int i = 0;
            
    for(i = 0; i < 4; i++{
                jLabels[i] 
    = new JLabel(labelsName[i]);
                jTextFields[i] 
    = new JTextField("jTextField" + i);
                
    //jTextFields[i].addActionListener(new Handler());
                container.add(jLabels[i]);
                container.add(jTextFields[i]);
            }

            jButton 
    = new JButton("Compute");
            container.add(jButton);
            jButton.addActionListener(
    new Handler());
            
            
    this.setSize(new Dimension(400300));
            
    this.setVisible(true);
        }

        
        
    private class Handler implements ActionListener{
            
    public void actionPerformed(ActionEvent ae) {
                
    if(ae.getActionCommand().equals("Compute")) {
                    
    int[] num = new int [3];
                    
    int i = 0;
                    
    for(i = 0; i < 3; i++{
                        num[i] 
    = Integer.parseInt(jTextFields[i].getText());
                    }

                    
    try{
                        Plus p 
    = (Plus)Naming.lookup("pluscxx");
                        System.out.println(
    "Found plus object");    
                        
    int sum = p.plus(num[0], num[1]);
                        System.out.println(
    "Add the first two number");
                        Multi m 
    = (Multi)Naming.lookup("multicxx");
                        System.out.println(
    "Found multi object");
                        
    int multiply2 = m.multi(sum, num [2]);
                        System.out.println(
    "Multi with the last number");
                        System.out.println(
    "result is:" + multiply2);
                        jTextFields[
    3].setText("" + multiply2);
                        
    //container.validate();
                        System.out.println("OK");
                    }
     catch(Exception ex) {
                        System.out.println(ex.getMessage());
                    }

                }

            }
            
        }

        
        
    public static void main(String[] args) {
            
    new Frame1();
        }

    }



    引用地址:http://blog.csdn.net/tgeh23/archive/2008/03/14/2183746.aspx 

     

    posted on 2008-04-03 13:32 SIMONE 閱讀(1183) 評論(2)  編輯  收藏 所屬分類: rmi

    FeedBack:
    # re: java RMI 相關(guān)
    2011-12-02 15:56 | 勞資
    你這里好像有點小問題,我自己解決了,不錯。  回復(fù)  更多評論
      
    # re: java RMI 相關(guān)
    2013-08-22 16:32 | ekkny
    @勞資
    服務(wù)端和客戶端分離,怎么通信 ?  回復(fù)  更多評論
      

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产亚洲综合视频| 亚洲国产成人精品无码区在线秒播 | 亚洲AⅤ优女AV综合久久久| 亚洲第一页日韩专区| 精品亚洲综合在线第一区| 久久久久亚洲Av片无码v| 91亚洲自偷在线观看国产馆| 亚洲成AV人影片在线观看| 国产成人无码精品久久久免费| 日本免费久久久久久久网站| 91久久成人免费| 在线观看免费精品国产| 亚洲无线观看国产精品| 亚洲人成电影在线观看青青| 日韩电影免费在线观看网址| 久久99青青精品免费观看| 天天干在线免费视频| 色久悠悠婷婷综合在线亚洲| 久久精品国产亚洲AV忘忧草18| 亚洲AV无码成人网站在线观看| 中文字幕久无码免费久久| 99国产精品永久免费视频| 亚洲VA综合VA国产产VA中| 91久久亚洲国产成人精品性色| 亚洲av无码无线在线观看| a毛片免费在线观看| 性感美女视频免费网站午夜| 亚洲无线码在线一区观看| 亚洲色大情网站www| 免费毛片在线看不用播放器| 妞干网在线免费观看| 亚洲AV永久精品爱情岛论坛 | 精品亚洲麻豆1区2区3区| 亚洲大码熟女在线观看| 一级毛片aaaaaa免费看| 国产区卡一卡二卡三乱码免费| 亚洲欧洲一区二区| 四虎永久在线精品免费一区二区| 曰曰鲁夜夜免费播放视频| 亚洲日产无码中文字幕| 亚洲AV无码XXX麻豆艾秋|