\r\n\r\n
RMIはRemote Method Invocationの略で、その名の通り、Javaプログラムが他のコンピュータで動作しているオブジェクトのメソッドを呼び出すためのプロトコルである。あるプログラム(サーバーと呼ぶ)からオブジェクトをエクスポートし、別のプログラム(クライアントと呼ぶ)からそのオブジェクトのメソッドを呼び出すためのAPI(Application Programming Interface)を提供し、おそらく別のコンピュータで実行されている。
javarmiレジストリはjavarmiシステムの重要なコンポーネントで、サーバーがサービスを登録し、クライアントがそれらのサービスを見つけるための一元化されたディレクトリを提供します。今回は、オブジェクトを公開するサーバーの実装方法と、サーバー上のメソッドを呼び出すクライアントの実装方法、およびRMIレジストリへのサービスの登録と検索方法について説明します。
javarmiの仕組みの複雑さを理解するために、名前を受け取って挨拶を返すメソッドを提供する簡単なサーバオブジェクトを実装してみましょう。以下に、オブジェクトインタフェースの定義を示す。
import java.rmi.Remote;
java.rmi.RemoteExceptionをインポートしてください。
public interface Greeting extends Remote.
{
public String greet(String name) throws RemoteException;
}
このインターフェイスの名前は greet と呼ばれ,名前を受け取って適切な挨拶を返す greet() というメソッドを提供する.
このインターフェイスをエクスポート可能なものとしてマークするには、java.rmi.Remoteファイルインターフェイスを拡張する必要があります。このメソッドは、アプリケーション固有の例外に加えて、java.rmi.RemoteException例外を列挙するthrows節も宣言する必要があります。これにより、クライアントコードは、ホストが見つからない、接続失敗などのリモートメソッド呼び出しエラーを処理(または伝播)することができます。
クライアント側で使用する)インターフェースを宣言した後、図のようにサーバー側のオブジェクトを実装し、greet()メソッドを提供します。挨拶文の書式設定には、簡単な書式文字列を使用します。
public class GreetingObject implements Greeting
{
private String fmtString = "こんにちは、%s";
public String greet(String name)
{
return String.format(this.fmtString, name);
}
}
では、これらのピースを組み合わせて、サーバーのmain()メソッドを実装してみましょう。
完全マスター方式。
import java.rmi.registry.LocateRegistry;
java.rmi.registryをインポートします。
java.rmi.server.UnicastRemoteObject.Import java.rmi.server.UnicastRemoteObject.Inc;
public class Main
{
static public void main(String[] args) throws Exception
{
if ( args.length == 0 ) {.
System.err.println("usage: java Main port#");
System.exit(1);
}
int index = 0;
int port = Integer.parseInt(args[index++])とする。
文字列名 = "挨拶";
Greeting greeting = new GreetingObject();
Greeting stub = (Greeting)UnicastRemoteObject.exportObject(greeting, 0);
レジストリ registry = LocateRegistry.getRegistry(port);
registry.rebind(name, stub);
System.out.println("Greeting bound to \" + name + "˶ˆ꒳ˆ˵")。
}
}
では、サーバーを構築する方法を説明します。簡単のために、LinuxではMavenのようなビルドツールではなく、コマンドラインでのビルドを使用することにします。
以下は、ソースファイルをターゲットディレクトリにあるクラスファイルにコンパイルするものです。
rm -rf target
mkdir ターゲット
javac -d ターゲット src/server/*.java
クラスファイルをJARファイルに集めて実行する。
jar cvf target/rmi-server.jar -C target server
また、クライアントをライブラリJARにコンパイルするために必要なインターフェイスファイルも収集しています。
jar cvf target/rmi-lib.jar -C target server/Greeting.class
では、サーバーオブジェクトのメソッドを呼び出すために使用されるクライアントをどのように実装するか見てみましょう。
フルクライアントコード
package client;
java.rmi.registry.LocateRegistry をインポートします。
java.rmi.registryをインポートします。
インポートサーバー
public class Client
{
static public void main(String[] args) throws Exception
{
if ( args.length != 3 ) {.
System.err.println("usage: java Client host port myName");
System.exit(1);
}
int index = 0;
文字列ホスト = args[index++];
int port = Integer.parseInt(args[index++])とする。
文字列 myName = args[index++];
文字列名 = "挨拶";
レジストリ registry = LocateRegistry.getRegistry(host, port);
Greeting greeting = (Greeting) registry.lookup(name);
System.out.println(name + " reported:" + greeting.greet(myName));
}
}
では、サーバープログラムを実行して、リクエストの処理を開始させましょう。
java -cp target/rmi-server.jar server.Main 1099
# throws
スレッド「main」での例外 java.rmi.ConnectException:ホスト: xxx への接続が拒否されました。
java.net.ConnectException: 接続が拒否されました。
その例外とは?
この例外が発生する理由は、サーバーのコードから、ポート1099でローカルレジストリに接続しようとすることに注目してください。失敗すると、このような例外が発生します。
解決策は、RMIレジストリと呼ばれるJava仮想マシンに付属するプログラムを実行することです。Java Virtual Machineのインストール先のbinディレクトリにあるはずです。実行はとても簡単です。
/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry
デフォルトでは、レジストリは1099番ポートをリッスンします。
/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100
指定したポートにリスナーが存在するかどうかは、netstatコマンドで確認します。
netstat -an -t tcp -p | grep LISTEN
...
tcp6 0 0 :::1100 :::* LISTEN 23450/rmiregistry
では、もう一度サーバーを動かしてみましょう。
java -cp target/rmi-server.jar server.Main 1100
# throws
java.rmi.UnmarshalException: error unmarshall arguments.
...
原因:java.lang.ClassNotFoundException: server.
...
今回も例外!?
サーバーはインターフェイスクラスサーバーをロードすることができませんでした。ごあいさつこれは、RMIレジストリが必要なクラスを読み込むことができなかったためです。そのため、必要なクラスの場所を指定する必要があります。環境変数CLASSPATHを指定するのも一つの方法です。
CLASSPATH=../../junk/target/rmi-lib.jar /usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100
再度サーバーを起動しようとすると、以下のようになりました。
java -cp target/rmi-server.jar server.Main 1100
# prints
"Greeting "にバインドされている
これでサーバーが起動しました。
すべてのパーツを組み立てて実行した後、クライアントを実行するのは簡単です。実行するためには、適切なジャーが必要です。これには、main()メソッドを含むクラスとインターフェースクラスが含まれます。RMIレジストリを実行する場所と、挨拶文の名前を示すパラメータを受け取ります。
java -cp target/rmi-client.jar:target/rmi-lib.jar client.Client localhost 1100 Peter
# prints
ごあいさつ:こんにちは、ピーターさん
javarmiは、リモートコードの実行を簡略化するためのAPIとツールを提供します。javarmiレジストリにサービスオブジェクトを登録するサーバーを実装することができます。クライアントはレジストリに問い合わせてサービスオブジェクトのスタブを取得し、サービスメソッドを呼び出すことができる。この例のように、全てはとてもシンプルです。
あなたのプロジェクトでjavarmiを使用していますか、あなたの経験は何ですか、代替手段をお持ちですか、以下のコメントでお知らせください。