日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RMI原理及开发实例

發布時間:2024/9/30 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RMI原理及开发实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.sina.com.cn/s/blog_492dbb6b0100faot.html

一、RMI原理簡介

1、RMI定義和功能

RMI是Remote Method Invocation的簡稱,是J2SE的一部分,能夠讓程序員開發出基于Java的分布式應用。一個RMI對象是一個遠 程Java對象,可以從另一個Java虛擬機上(甚至跨過網絡)調用它的方法,可以像調用本地Java對象的方法一樣調用遠程對象的方法,使分布在不同的JVM中的對象的外表和行為都 像本地對象一樣。

2、Stub和Skeleton介紹

在學習RMI的時,我們不能不討論stub和skeleton作用和相關問題。他們是我們理解RMI原理的關鍵。我做個比方說明這兩個概念。假如你是A,你想借D的工具,但是又不認識D的管家C,所以你找來B來幫你,B認識C。B在這時就是一個代理,代理你的請求,依靠自己的話語去借。C呢他負責D家東西收回和借出 ,但是要有D的批準。在得到D的批準以后,C再把東西給B,B呢再轉給A。stub和skeleton在RMI中就是角色就是B和C,他們都是代理角色,在現實開發中隱藏系統和網絡的的差異,這一部分的功能在RMI開發中對程序員是透明的。Stub為客戶端編碼遠程命令并把他們發送到服務器。而Skeleton則是把遠程命令解碼,調用服務端的遠程對象的方法,把結果在編碼發給stub,然后stub再解碼返回調用結果給客戶端。

從JDK5.0以后,這兩個類就不需要rmic來產生了,而是有JVM自動處理,實際上他們還是存在的。Stub存在于客戶端,作為客戶端的代理,讓我們總是認為客戶端產生了stub,接口沒有作用。實際上stub類是通過Java動態類下載 機制下載的(具體內容請參考:Java RMI實現代碼動態下載),它是由服 務端產生,然后根據需要動態的加載到客戶端,如果下次再運行這個客戶端該存根類存在于classpath中,它就不需要再下載了,而是直接加載。(具體的內部細節,需要參考Sun 的Rmi - Java Remote Method Invocation – Specification)。總的來說,stub是在服務端產生的,如果服務端的stub內容改變,那么客戶端的也是需要同步更新。

3、Rmiregistry介紹

Rmiregistry需要在提供遠程對象服務端啟動,它提供了一個環境,說白了就是在內存中,開辟了一片空間,用來接受服務端服務程序的注冊,產生一個類似于數據庫,提供存儲檢索遠程對象功能的注冊表。這個RMI注冊表,就是我們常聽到的RMI名字服務。遠程客戶端,就是依靠它獲得存根,調用遠程方法。說到 這里有一個端口的問題,如果你在啟動rmiregistry時,設定了非默認端口,那么需要在服務端和客戶端統一使用該端口,否則就會有RemoteException的異常拋出,rmiregistry提 供的服務是針對特定的端口號的,不然在同一臺機器上也是無法提供服務。

二、RMI實例開發

????在本例中我們實現一個求加法的遠程服務,下面我們通過具體的例子,建立一個簡單的遠程計算服務和使用它的客戶程序:  
一個正常工作的RMI系統由下面幾個部分組成:
 ● 遠程服務的接口定義
 ● 遠程服務接口的具體實現
 ● 樁(Stub)和框架(Skeleton)文件
 ● 一個運行遠程服務的服務器
 ● 一個RMI命名服務,它答應客戶端去發現這個遠程服務
 ● 類文件的提供者(一個HTTP或者FTP服務器)
 ● 一個需要這個遠程服務的客戶端程序
 下面我們一步一步建立一個簡單的RMI系統。首先在你的機器里建立一個新的文件夾,以便放置我們創建的文件,為了簡單起見,我們只使用一個文件夾存放客戶端和服務端代碼,并且在同一個目錄下運行服務端和客戶端。
  假如所有的RMI文件都已經設計好了,那么你需要下面的幾個步驟去生成你的系統:
1、編寫并且編譯接口的Java代碼
package lib.idc;

public interface Calculator extends Remote

{

????public long add(long a, long b)?

????????throws java.rmi.RemoteException;

}

用命令編譯Calculator.java

>>javac?lib/idc/Calculator.java

2、編寫并且編譯接口實現的Java代碼

package lib.idc;
import java.rmi.server.UnicastRemoteObject;

public class CalculatorImpl extends UnicastRemoteObject implements Calculator{?

//這個實現必須有一個顯式的構造函數,并且要拋出一個RemoteException異常

????public CalculatorImpl()?

????????throws java.rmi.RemoteException {?

????????super();?

????}?

?

????public long add(long a, long b) throws java.rmi.RemoteException {?

????????return a + b;?

}?

}

同樣按照以上步驟編譯CalculatorImpl.java

>>javac?lib/idc/ CalculatorImpl.java

3、從接口實現類中生成樁(Stub)和框架(Skeleton)類文件

>>rmic lib.idc.CalculatorImpl
 在你的目錄下運行上面的命令,成功執行完上面的命令你可以發現一個Calculator_stub.class文件,假如你是使用的Java2SDK,那么你還可以發現Calculator_Skel.class文件。(我的沒有)

4、編寫遠程服務的主運行程序
 遠程RMI服務必須是在一個服務器中運行的。CalculatorServer類是一個非常簡單的服務器。
package lib.idc;
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();
   }
}
建立這個服務器程序,然后保存到你的目錄下。

5、編寫RMI的客戶端程序

package lib.idc;

import java.rmi.Naming;?

import java.rmi.RemoteException;?

import java.net.MalformedURLException;?

import java.rmi.NotBoundException;?

import java.rmi.RMISecurityManager;

public class CalculatorClient {?

??public static void main(String[] args) {

????????if(System.getSecurityManager()==null)

??????????????System.setSecurityManager(new RMISecurityManager());

??

????????try {?

????????????Calculator c = (Calculator)

???????????????????????????Naming.lookup(

?????????????????"rmi://localhost/CalculatorService");?

????????????????System.out.println( c.add(4, 5) );

} catch (MalformedURLException murle) {?

??????????????System.out.println("MalformedURLException");?

????????????}?

???????????????catch (RemoteException re) {?

??????????????System.out.println("RemoteException");?

??????????}?

}
6、運行RMI系統

????完成以上步驟后,運行啟動服務注冊命令:

>>rmiregistry(注意所有命令的運行都是在lib/idc的上級目錄,即. /lib/idc)

此命令執行后,將啟動注冊服務程序,然后打開新的控制臺窗口(如果在應用程序中啟動服務端程序,也必須先生成樁和框架類文件和運行rmiregistry命令)。同樣進入目錄. /lib/idc,執行啟動服務端程序。因為RMI的安全機制將在服務端發生作用,所以你必須增加一條安全策略:?
grant?{
permission?java.security.AllPermission?"",?"";
};并將其添加到\..\jre\lib\security\ java.policy文件之后,該文件位于指定的jre路徑下。

>> javac lib/idc/CalculatorServer.java

>> java??lib.idc. CalculatorServer

這一步完成后打開第三個控制臺窗口,進入目錄. /lib/idc,執行

命令啟動客戶端程序

>> javac lib/idc/ CalculatorClient.java

>> java??lib.idc. CalculatorClient

至此完成RMI系統的運行。

三、常見錯誤

1、error unmarshalling return; nested exception is:

????????java.lang.ClassNotFoundException: rmi.RmiInterfaceImp_Stub (no security manager: RMI class loader disabled)

解決方法:在客戶端添加以上紅色部分代碼。

2、Exception in thread "main" java.security.AccessControlException: access denied (

java.net.SocketPermission 211.69.205.250:1099 connect,resolve)

解決方法:新建文件如policy.txt 內容為:

grant?{
permission?java.security.AllPermission?"",?"";
};并保存在客戶端程序目錄下,然后執行

>>java??-Djava.security.policy=policy.txt lib.idc.CalculatorClient

3、>>rmic RmiInterfaceImp

error: 未找到類 RmiInterfaceImp。1 個錯誤

解決方法:出現此問題一般是RmiInterfaceImp的路徑問題,如在此處改為lib.idc.snatch.RmiInterfaceImp,表示RmiInterfaceImp所在的包。

4、error unmarshalling return; nested exception is:

????????java.lang.ClassNotFoundException: lib.idc.snatch.RmiInterfaceImp_Stub

解決方法:出現此類問題的原因是找不到RmiInterfaceImp_Stub,但是在同樣的目錄下有時可以找到,有時又找不到了,真是活見鬼了!這個問題還沒徹底解決,如果哪位兄弟解決了,還請不忘相告一聲。


總結

以上是生活随笔為你收集整理的RMI原理及开发实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。