Изображение://wp-content/uploads/2017/01/distributed object communication.png[distributed object communication]
__Image Source:
https://upload.wikimedia.org/wikipedia/commons/f/f7/Distributed object communication.png[Wikimedia.org]__
В ссылке://java/java-rmi-hello-world-example/[пример Java RMI Hello World]мы представили https://en.wikipedia.org/wiki/Java remote method invocation[Java[Java Remote Method Invocation]с очень простым Строковая связь между сервером и клиентом. В этом примере мы сделаем еще один маленький шаг и познакомимся с сервером и клиентом, используя https://en.wikipedia.org/wiki/Distributed object[Distributed Objects].
1. Удаленный интерфейс
Сначала мы разработаем «Удаленный интерфейс», который содержит все методы, которые реализует Сервер.
Интерфейс
всегда должен быть` public` и расширять
Remote
. Все методы, описанные в «Remote Interface», должны указывать «RemoteException» в своем предложении throws.
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
, которым обмениваются Сервер и Клиент, и он должен реализовывать« Сериализуемый интерфейс ». Также чрезвычайно важно, чтобы этот класс объявлял явное значение
serialVersionUID
, чтобы гарантировать согласованность между различными реализациями компилятора Java.
Если мы проигнорируем это или если класс Распределенного объекта Сервера объявит другой
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`. В основном методе мы привязываем сервер на локальном хосте с именем «MyBookstore». Для простоты вместо использования базы данных или
File
мы создали метод` initializeList ()
, который заполняет
List`
объектами типа книги
, которые представляют книги, которые есть в нашем книжном магазине (…
да только 5. Но 5 классных книг!).
Нам также нужно добавить
serialVersionUID
для Сервера, но поскольку Сервер, который мы разработали в этом примере, намеревается существовать только на одной машине, нам не нужно думать об этом дважды, мы можем просто установить` default 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 После того, как вы создадите четыре файла Java с вашей любимой IDE или загрузите приведенный ниже код, перейдите к исходной папке, как показано ниже.
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-2.png[Java-RMI-распределенные-объекты-пример-2]
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. Подтвердите, что ваши источники были скомпилированы, открыв соответствующие каталоги:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-3.png[Java-RMI-распределенные-объекты-пример-3]
5.4 Далее нам нужно начать rmiregistry. Снова либо запустите
2. startServer.bat
или откройте командное окно и запустите:
Терминал
$ cd src $ start rmiregistry $ java com.mkyong.rmiserver.Bookstore
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-4.png[Java-RMI-распределенные-объекты-пример-4]
5.5 Если RmiRegistry запустился успешно, появится другое окно, которое выглядит так:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-5.png[Java-RMI-распределенные-объекты-пример-5]
5.6 Теперь мы готовы запустить нашего Клиента:
Откройте новое окно командной строки (или запустите
3. runClient.bat
из загруженных файлов) и запустите:
Терминал
$ cd src $ java com.mkyong.rmiclient.Customer
5.6.1. Клиентский класс запускается и предлагает нам выполнить действие
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-6.png[Java-RMI-распределенные-объекты-пример-6]
5.6.2 Когда мы нажимаем кнопку «Показать все»:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-7.png[Java-RMI-распределенные-объекты-пример-7]
5.6.3 После нажатия кнопки «ОК»:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-8.png[Java-RMI-распределенные-объекты-пример-8]
5.6.4 Мы нажимаем кнопку «Нет», так как не хотим выходить, и появляется следующее диалоговое окно. Мы набираем ISBN (например, «978-0596009205») и нажимаем «ОК».
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-9.png[Java-RMI-распределенные-объекты-пример-9]
5.6.5 Если книга была найдена в списке Сервера:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-10.png[Java-RMI-распределенные-объекты-пример-10]
5.6.6 Если он не был найден:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-11.png[Java-RMI-распределенные-объекты-пример-11]
5.6.7 Программа будет продолжена, спросив нас:
изображение://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-8.png[Java-RMI-распределенные-объекты-пример-8]
Если мы нажмем кнопку «Да», программа закроется. Если мы нажмем «Нет», это вернет нас в главное меню для выбора действия, как показано в 5.6.1.
Сервер продолжит работать, пока мы не закроем его окно. Даже после закрытия Клиента мы можем открыть нового или даже нескольких Клиентов, которые работают одновременно.
ссылка://wp-content/uploads/2017/01/java-rmi-distributed-objects-example-12.png[Изображение://WP-содержание/добавления/2017/01/Java-RMI-РОС-объекты- example-12.png[java-rmi- распределенные объекты-пример-12]]
Скачать исходный код
Загрузить - ссылка://wp-content/uploads/2017/01/RMIObjects.zip[RMIObjects.zip](5 КБ)
Рекомендации
Интерфейс - 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]