Java RMI - Пример распределенных объектов

Изображение://wp-content/uploads/2017/01/distributed object communication.png[distributed object communication]

__Image Source:

В ссылке://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 следующим образом:

java-rmi- распределенные объекты-пример-1

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 КБ)

Рекомендации

пример], https://en.wikipedia.org/wiki/Java remote method__invocation[Wikipedia

Распределенные объекты]

ссылка://тег/распределенный объект/[распределенный объект]ссылка://тег/rmi/[rmi]