Изображение://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]