Java RMI – 分散オブジェクトの例
__イメージソース:
https://upload.wikimedia.org/wikipedia/commons/f/f7/Distributed
object
communication.png[Wikimedia.org]__
Java RMI Hello Worldの例
では、非常に基本的なhttps://en.wikipedia.org/wiki/Java
remote
method
invocation[Java Remote Method Invocation]を紹介しました。 Server-Client間の `String-based`通信です。この例では、もう少し詳しく説明し、https://en.wikipedia.org/wiki/Distributed
object[Distributed Objects]を使ってServer-Client通信を紹介します。
1.リモートインタフェース
最初に、サーバーが実装するすべてのメソッドを含む
Remote Interface`を開発します。 `Interface`は常に
public`で
Remote`を拡張する必要があります。 `Remote Interface`に記述された全てのメソッドは、それらのthrows節に
RemoteException`をリストしなければなりません。
RMIInterface.java
package com.techfou.rmiinterface; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.List; public interface RMIInterface extends Remote { Book findBook(Book b) throws RemoteException; List<Book> allBooks() throws RemoteException; }
2.分散オブジェクトクラス
これは、サーバとクライアントが交換する
Object`のクラスであり、
Serializable Interface`を実装する必要があります。また、このクラスが異なるJavaコンパイラの実装間で一貫性を保証するために明示的な `serialVersionUID`値を宣言することも非常に重要です。
それを無視するか、またはサーバのDistributed Objectクラスが、クライアントのDistributed Objectクラスとは異なる
serialVersionUID`を宣言している場合、逆直列化処理は
InvalidClassException`になります。
Eclipse IDEでは、次のようにserialVersionUIDを生成できます。
Book.java
package com.techfou.rmiinterface; import java.io.Serializable; public class Book implements Serializable { private static final long serialVersionUID = 1190476516911661470L; private String title; private String isbn; private double cost; public Book(String isbn) { this.isbn = isbn; } public Book(String title, String isbn, double cost) { this.title = title; this.isbn = isbn; this.cost = cost; } public String getTitle() { return title; } public String getIsbn() { return isbn; } public double getCost() { return cost; } public String toString() { return "> " + this.title + " ($" + this.cost + ")"; } }
3.サーバー
サーバは
UnicastRemoteObject`を拡張し、
RMIInterface`を実装します。 mainメソッドでは、ローカルホスト上のサーバーを “MyBookstore”という名前でバインドします。単純に、データベースや
File`を使うのではなく、Bookstoreが持っている本を表す
Book type Objects`で
List`を埋め込む
initializeList() `メソッドを作成しました。
はい、5つしかありません。
サーバー用のserialVersionUIDも追加する必要がありますが、この例で設計したServerは1台のマシンにしか存在しないため、2回考える必要はありません。デフォルトのserialVersionUIDを設定できます。しかし、サーバークラスも配布されていれば、そのクラスの `serialVersionUID`が実装されているすべてのプラットフォームで同じであることを確認する必要があります。
Bookstore.java
package com.mkyong.rmiserver; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import com.mkyong.rmiinterface.Book; import com.mkyong.rmiinterface.RMIInterface; public class Bookstore extends UnicastRemoteObject implements RMIInterface { private static final long serialVersionUID = 1L; private List<Book> bookList; protected Bookstore(List<Book> list) throws RemoteException { super(); this.bookList = list; } //The client sends a Book object with the isbn information on it //(note: it could be a string with the isbn too) //With this method the server searches in the List bookList //for any book that has that isbn and returns the whole object @Override public Book findBook(Book book) throws RemoteException { Predicate<Book> predicate = x -> x.getIsbn().equals(book.getIsbn()); return bookList.stream().filter(predicate).findFirst().get(); } @Override public List<Book> allBooks() throws RemoteException { return bookList; } private static List<Book> initializeList() { List<Book> list = new ArrayList<>(); list.add(new Book("Head First Java, 2nd Edition", "978-0596009205", 31.41)); list.add(new Book("Java In A Nutshell", "978-0596007737", 10.90)); list.add(new Book("Java: The Complete Reference", "978-0071808552", 40.18)); list.add(new Book("Head First Servlets and JSP", "978-0596516680", 35.41)); list.add(new Book("Java Puzzlers: Traps, Pitfalls, and Corner Cases", "978-0321336781", 39.99)); return list; } public static void main(String[]args) { try { Naming.rebind("//localhost/MyBookstore", new Bookstore(initializeList())); System.err.println("Server ready"); } catch (Exception e) { System.err.println("Server exception: " + e.getMessage()); } } }
4.クライアント
クライアントは、パラメータとして渡す名前に関連付けられたリモートオブジェクトへの参照を「調べる」RMIInterfaceオブジェクトを介してサーバーを「検出」します。私が先ほど説明したのは、 `Naming.lookup(”//localhost/MyBookstore “);`というものです。
クライアントのコードの残りの部分は、あなたがうまく試してみることができる実際の例を作ることに過ぎません。
Customer.java
package com.mkyong.rmiclient; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.util.List; import java.util.NoSuchElementException; import javax.swing.JOptionPane; import com.mkyong.rmiinterface.Book; import com.mkyong.rmiinterface.RMIInterface; public class Customer { private static RMIInterface look__up; public static void main(String[]args) throws MalformedURLException, RemoteException, NotBoundException { look__up = (RMIInterface) Naming.lookup("//localhost/MyBookstore"); boolean findmore; do { String[]options = {"Show All", "Find a book", "Exit"}; int choice = JOptionPane.showOptionDialog(null, "Choose an action", "Option dialog", JOptionPane.DEFAULT__OPTION, JOptionPane.INFORMATION__MESSAGE, null, options, options[0]); switch (choice) { case 0: List<Book> list = look__up.allBooks(); StringBuilder message = new StringBuilder(); list.forEach(x -> { message.append(x.toString() + "\n"); }); JOptionPane.showMessageDialog(null, new String(message)); break; case 1: String isbn = JOptionPane.showInputDialog("Type the isbn of the book you want to find."); try { Book response = look__up.findBook(new Book(isbn)); JOptionPane.showMessageDialog(null, "Title: " + response.getTitle() + "\n" + "Cost: $" + response.getCost(), response.getIsbn(), JOptionPane.INFORMATION__MESSAGE); } catch (NoSuchElementException ex) { JOptionPane.showMessageDialog(null, "Not found"); } break; default: System.exit(0); break; } findmore = (JOptionPane.showConfirmDialog(null, "Do you want to exit?", "Exit", JOptionPane.YES__NO__OPTION) == JOptionPane.NO__OPTION); } while (findmore); } }
5.それを実行する方法
5.1お気に入りのIDEで4つのJavaファイルを作成した後、または下のコードをダウンロードして、ソースフォルダに移動します。
5.2まず、ソースをコンパイルする必要があります。
1を実行します。以下のコードをダウンロードした場合、またはディレクトリにコマンドウィンドウを開いて実行した場合は、「compileEverything.bat
ターミナル
$ javac src/com/mkyong/rmiinterface/RMIInterface.java src/com/mkyong/rmiinterface/Book.java src/com/mkyong/rmiserver/Bookstore.java src/com/mkyong/rmiclient/Customer.java
5.3ソースがそれぞれのディレクトリにアクセスしてコンパイルされていることを確認します。
5.4次に、rmiregistryを開始する必要があります。もう一度 `2。 startServer.bat`を実行するか、コマンドウィンドウを開いて次のコマンドを実行します。
ターミナル
$ cd src $ start rmiregistry $ java com.mkyong.rmiserver.Bookstore
5.5 RmiRegistryが正常に起動した場合は、次のような別のウィンドウが表示されます。
5.6クライアントを実行する準備が整いました。
新しいコマンドプロンプトウィンドウを開くか(ダウンロードしたファイルから `3. runClient.bat`を実行してください)、これを実行してください:
ターミナル
$ cd src $ java com.mkyong.rmiclient.Customer
5.6.1 `Customer class`が実行され、私たちにアクションを促します:
5.6.2「すべて表示」ボタンをクリックすると:
5.6.3「OK」ボタンをクリックした後:
5.6.4「No」ボタンをクリックすると、まだ終了しないので、次のダイアログが表示されます。 ISBN(例:978-0596009205)を入力して「OK」をクリックします。
5.6.5サーバーのリストにブックが見つかった場合:
5.6.6見つからなかった場合:
5.6.7プログラムは私達に尋ねることによって続行されます:
「はい」ボタンをクリックすると、プログラムは終了します。 「いいえ」をクリックすると、メインメニューに戻り、5.6.1に示すようなアクションを選択します。
サーバーは、ウィンドウが閉じるまで実行を継続します。クライアントが終了した後でも、同時に実行する新しいクライアントまたは複数のクライアントを開くことができます。
リンク://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-12.png[
]
ソースコードをダウンロードする
ダウンロード:
RMIObjects.zip
(5 KB)
参考文献
インタフェース – Java API]。
https://docs.oracle.com/javase/8/docs/api/java/rmi/Remote.html
[Remote
例]。
https://en.wikipedia.org/wiki/Java
remote
method__invocation—Wikipedia
-
Javaリモートメソッド呼び出し]。
https://en.wikipedia.org/wiki/Distributed__object
[Wikipedia –
分散オブジェクト]
リンク://タグ/分散オブジェクト/[分散オブジェクト]リンク://タグ/rmi/[rmi]