Java RMI: Java リモート メソッド呼び出し、または Java RMI (Java Remote Method Invocation) は、Java プログラミング言語でリモート プロシージャ コールを実装するために使用されるアプリケーション プログラミング インターフェイスです。
これにより、クライアント上で実行されているプログラムがリモート サーバー上のオブジェクトを呼び出すことができるようになります。リモート メソッド呼び出し機能を使用すると、Java プログラマはネットワーク環境で操作を分散できます。 RMI の全体の目的は、リモート インターフェイス オブジェクトの使用を可能な限り簡素化することです。
リモート プロシージャ コール (RPC) を使用すると、あるプロセスが別のプロセス (おそらく別のリモート ホスト上) のプロセスを呼び出すことができ、それによってプロセス分散機能が提供されることがわかっています。 Java の RMI は、RPC に基づいてさらに一歩前進し、分散オブジェクト間の通信を提供します。
RMI (リモート メソッド呼び出し) は、リモート メソッド呼び出しです。これにより、ある Java 仮想マシン上で実行されているオブジェクトが、別の Java 仮想マシン上で実行されているオブジェクトのメソッドを呼び出すことができます。
2 つの仮想マシンは、同じコンピュータ上の異なるプロセスで実行することも、ネットワーク上の異なるコンピュータで実行することもできます。
【JavaRMI】
1. 動作原理
RMI を使用すると、Java プログラムがネットワーク上の別のコンピュータを呼び出すことができます。コンピュータの Java オブジェクトのメソッドを呼び出した場合、それを呼び出した場合の効果は、ローカル マシン上で呼び出した場合と同じになります。平たく言えば、マシン A にクラスがあり、マシン B はリモート呼び出しを通じてこのクラスのメソッドを呼び出します。
RMI、リモート メソッド呼び出し (リモート メソッド呼び出し) は、Enterprise JavaBeans のバックボーンであり、分散 Java アプリケーションを構築する便利な方法です。 RMI は非常に使いやすいですが、非常に強力です。
RMI の基礎はインターフェイスです。RMI アーキテクチャは、インターフェイスの定義とインターフェイスの特定の実装の定義は分離されているという重要な原則に基づいています。以下では、具体的な例を使用して、単純なリモート コンピューティング サービスとそれを使用するクライアント プログラムを構築します
2. RMI には次のものが含まれます:
1. リモート サービス インターフェイスの定義
2. リモート サービス インターフェイスの特定の実装
3. スタブ ファイルとスケルトン ファイル
4. リモート サービスを実行するサーバー
5. RMI の命名
6. クラス ファイルのプロバイダー (HTTP または FTP サーバー)
7. このリモート サービス クライアント プログラムを必要とするもの
3. RMI の目的は何ですか?
RMI の目的は、分散 Java アプリケーション間のリモート通信のためのサービスを提供し、分散サービスを提供することです。
現在、主要なアプリケーションは Spring、EJB などのさまざまな J2EE プロジェクト フレームワークにカプセル化されています (Spring と EJB は両方とも RMI テクノロジをカプセル化します)
Spring で RMI を実装します:
① サーバー側でサービス インターフェイスを定義し、これらのインターフェイスを実装するための特定のクラスを定義します;
② サーバー側で org.springframework.remoting.rmi.RmiServiceExporter クラスを使用してサービスを登録します;
③クライアントは org.springframework.remoting.rmi.RmiProxyFactoryBean を使用してリモートサービスのプロキシ機能を実装します。
④クライアント上でサーバーと同じサービスインターフェースにアクセスするクラスを定義します
4 、RMI の制限は何ですか? JRMP は Java リモート オブジェクト用に特別に開発されたプロトコルです。JRMP は Java オブジェクト用に特別に開発されたため、RMI は非 Java 言語で開発されたアプリケーション システムを十分にサポートしていません。
Java 以外の言語で書かれたオブジェクトとは通信できません (つまり、クライアントとサーバーの両方が Java プログラムであるコードによるリモート呼び出しのみがサポートされます)。5. RMI を使用する場合の制限は何ですか?
クライアントとサーバーの両方が Java で書かれているため、プラットフォームの互換性の唯一の要件は、両方の者が次のことを行うことです。バージョン互換性のある Java 仮想マシン上で実行します。
6. リモート メソッドへの RMI 呼び出しのパラメータと戻り値
リモート オブジェクトのメソッドを呼び出すとき、クライアントは元の型のデータをパラメータとして使用できるだけではありませんさらに、戻り値に対応するオブジェクトをパラメータとして渡すこともでき、プリミティブ型またはオブジェクトを返すことができ、これらはすべて Java のオブジェクト シリアル化 (シリアル化) テクノロジによって実装されます。 (言い換えると、パラメータまたは戻り値がオブジェクトの場合、Serializable インターフェイスを実装する必要があります)
7. RMI アプリケーションの基本モデル
8. RMI アーキテクチャ
スタブ/フレームワーク (スタブ/スケルトン) 層: クライアント側のスタブとサーバー側のフレームワーク;
リモート参照層: リモート参照動作の処理
トランスポート層: 接続の確立と管理、およびリモート オブジェクトの追跡
9. RMI クラスとインターフェイス (完了するために必要なクラス)単純な RMI)。
#(1) リモート インターフェース: メソッドを定義しないタグ付きインターフェースです。パブリック インターフェース リモート{}In RMI では、リモート インターフェイスは、リモート Java 仮想マシンから呼び出すことができるメソッドのセットを宣言します。リモート インターフェイスは次の要件を満たします: 1. リモート インターフェイスは、Java.rmi.Remote インターフェイスを直接または間接的に拡張する必要があり、クライアントとリモート インターフェイスが同じにない限り、パブリックとして宣言する必要があります。 package 2. リモート インターフェイスでメソッドを宣言する場合、アプリケーションに関連するメソッドをスローするだけでなく、RemoteException (またはそのスーパークラス、IOExcepion または Exception) 例外 も含める必要があります。 3. リモートメソッド宣言では、パラメータまたは戻り値として宣言されるリモートオブジェクトは、インタフェースの実装クラスとしてではなく、リモートインタフェースとして宣言する必要があります。 (2) RemoteObject 抽象クラスは、Remote インターフェイスと Serializable インターフェイスを実装しており、そのサブクラスは RMI サーバー機能を提供します。 (3) LocateRegistry Final() クラスは、特定のホストのブート リモート オブジェクト登録サーバー プログラムへの参照を取得する (つまり、スタブを作成する) か、リモート オブジェクト登録サービスを作成するために使用されます。特定のポートで通話を受信できるプログラム。 サーバー側: リモート オブジェクト サービスを他のクライアントに提供するSomeService servcie=……;//远程对象服务1. レジストリ registry=LocateRegisty.getRegistry(); //レジストリはインターフェイスであり、リモートを継承し、このメソッドはローカルを返します。デフォルトのレジストリ ポート 1099 上のリモート オブジェクト レジストリへのホストの参照。 2. getRegistry(int port) は、指定されたポート上のリモート オブジェクト レジストリへのローカル ホストの参照を返します; 3. getRegistry(String host) は、デフォルトの指定されたホストを返しますレジストリ ポート 1099 リモート オブジェクト レジストリへの参照;4.getRegistry(String host, int port) は、指定されたホストおよびポート5.レジストリ上のリモート オブジェクト レジストリへの参照を返します。 bind(“Iserve”,service);//bind(String name,Remote obj) リモート参照をこのレジストリで指定された名前にバインドします。 name: リモート参照に関連する名前 obj: リモート オブジェクト (通常はスタブ) への参照 6, unbind (文字列名) は、レジストリ内の指定された名前のバインドを削除します。 7. Rebind (String name, Remote obj) を再バインドします。名前がすでに存在するが、リモートが異なる場合は、それを置き換えます。リモートが同じ場合は、既存のバインドを破棄します。 8. lookup(String name) レジストリ内の指定された名前にバインドされたリモート参照を返します。Remote9 を返します。String[] list() このレジストリ内にバインドされた名前の配列を返します。この配列には、このメソッドが呼び出されたときにバインドされたこのレジストリ内の名前のスナップショットが含まれます。 クライアント側: 対応するサービスリクエストをサーバーに提供します。 レジストリ registry=LocateRegisty.getRegistry();
SomeService servcie=(SomeService)registry.lookup(「私はサービスします」);
Servcie.requestService();
#(4) ネーミングクラスはレジストリクラスと同様です。
クライアント:
Naming.lookup(String url) url 格式如下"rmi://localhost/"+远程对象引用
サーバー:
Registry registry=LocateRegistry.createRegistry(int port); Naming.rebind(“service”,service);
(5) RMISecurityManager クラス
RMI リファレンス プログラムでは、セキュリティ マネージャーが設定されていない場合、スタブとクラスはローカル クラスパスからのみロードできるため、リモート メソッド呼び出しによってダウンロードされたコードによってアプリケーションが侵害されることはありません。
リモート ホストからコードをダウンロードする前に、次のコードを実行して RMISecurityManager をインストールする必要があります。 :
System.setSecurityManager(new RMISecurityManager());
10. デモ開発デモを作成するために、次のことに分かれます。 2 つの部分、1 つの部分はサーバー側コードの一部であり、クライアント側コードです。クライアント側コードは主にサーバー側コードを使用するためのものです。もちろん、このコードは問題を説明するためだけに非常に単純ですが、実際の使用はさらに複雑になります。
(1) 目的
リモート側のコードを含むサーバー側の Java プロジェクトを構築し、インターフェイスを定義し、インターフェイスの実装を定義して、クライアント側の Java プロジェクトを作成します。エンドサービスの RMI メソッドを介してリモート側を使用します。
(2) コード構造
#(3) リモートサービスコード
1. リモートサービスインターフェース定義
最初のステップは、サービス インターフェイスの Java コードを作成してコンパイルすることです。このインターフェイスは、リモート サービスを提供するすべての機能を定義します。ソース プログラムは次のとおりです:
UserManagerInterface.java
package cn.com.tt.rmiserver.stub; import java.rmi.Remote; import java.rmi.RemoteException; import cn.com.tt.rmiserver.bean.Account; public interface UserManagerInterface extends Remote{ public String getUserName() throws RemoteException; public Account getAdminAccount() throws RemoteException; }
インターフェイスは Remote クラスを継承する必要があり、定義された各メソッドは RemoteException をスローする必要があります例外オブジェクト。
2. インターフェイスの具体的な実装
2 番目のステップは、上記のインターフェイスを実装することです:
UserManagerImp.java
package cn.com.tt.rmiserver; import java.rmi.RemoteException; import cn.com.tt.rmiserver.stub.UserManagerInterface; import cn.com.tt.rmiserver.bean.Account; public class UserManagerImp implements UserManagerInterface { public UserManagerImp() throws RemoteException { } private static final long serialVersionUID = -3111492742628447261L; public String getUserName() throws RemoteException{ return "TT"; } public Account getAdminAccount() throws RemoteException{ Account account=new Account(); account.setUsername("TT"); account.setPassword("123456"); return account; } }
3. Bean を定義します。 、Serializable シリアル化インターフェイスを実装します。つまり、クライアントとサーバー間で送信できるシリアル化可能なオブジェクトです。
Account.java
package cn.com.tt.rmiserver.bean; import java.io.Serializable; public class Account implements Serializable,Cloneable{ private static final long serialVersionUID = -1858518369668584532L; private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
4. サーバー側でメイン プログラム エントリを定義します。
Entry.java
package cn.com.tt.rmiserver.entry; import java.rmi.AlreadyBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import cn.com.tt.rmiserver.UserManagerImp; import cn.com.tt.rmiserver.stub.UserManagerInterface; public class Entry { public static void main(String []args) throws AlreadyBoundException, RemoteException{ UserManagerImp userManager=new UserManagerImp(); UserManagerInterface userManagerI=(UserManagerInterface)UnicastRemoteObject.exportObject(userManager,0); // Bind the remote object's stub in the registry Registry registry = LocateRegistry.createRegistry(2002); registry.rebind("userManager", userManagerI); System.out.println("server is ready"); } }
(4) クライアント側のコード
1、把Server端的Account类和接口UserManagerInterface 导出Export成jar包,命名为:RmiServerInterface.jar。导入到client中。
2、项目——右键——Export——java——jar file——next——选择Account类和接口UserManagerInterface——命名为:RmiServerInterface.jar如下图:
3. 新建一个java Project,导入jar包,编写客户端代码。
4. 代码
ClientEntry.java
package weiblog.rmi; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import cn.com.tt.rmiserver.stub.UserManagerInterface; public class ClientEntry { public static void main(String []args){ try { Registry registry = LocateRegistry.getRegistry("localhost",2004); UserManagerInterface userManager = (UserManagerInterface)registry.lookup("userManager"); System.out.println("用户名是"+userManager.getAdminAccount().getUsername() +"密码"+userManager.getAdminAccount().getPassword()); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NotBoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
5. 先运行服务器端代码, 然后运行客户端代码,就会显示运行结果,客户端可以运行多次,每次都可以取得服务器端的对象。如果要再次运行客户端代码就需要更改端口号,如果不更改就会显示端口号被占用。
更多java知识请关注java基础教程栏目。
以上がJava RMI の詳細な図解説明 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。