Рубрики
Без рубрики

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

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

Источник изображения: Источник изображения:

В примере Java RMI Hello World мы представили Вызов удаленного метода Java с очень простой строковой связью между Сервером и Клиентом. В этом примере мы сделаем еще один небольшой шаг вперед и представим связь между сервером и клиентом с использованием Распределенных объектов .

1. Удаленный Интерфейс

Сначала мы разработаем Удаленный интерфейс , который содержит все методы, реализуемые Сервером. Интерфейс всегда должен быть общедоступным и расширить Удаленный . Все методы, описанные в Удаленном интерфейсе должны быть перечислены RemoteException в их предложении throws.

package com.mkyong.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 allBooks() throws RemoteException;

}

2. Класс распределенных объектов

Это класс Объекта , которым будут обмениваться Сервер и Клиент, и он должен реализовать Сериализуемый интерфейс . Также чрезвычайно важно, чтобы этот класс объявлял явное значение serialVersionUID , чтобы гарантировать согласованность между различными реализациями компилятора java.

Если мы проигнорируем это или если класс распределенных объектов Сервера объявит другой serialVersionUID , чем класс распределенных объектов Клиента, то процесс десериализации приведет к исключению InvalidClassException .

В среде IDE Eclipse вы можете создать идентификатор serialVersionUID следующим образом:

package com.mkyong.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. Сервер

Сервер расширяет одноадресный объект/| и реализует Интерфейс RMI . В основном методе мы привязываем сервер на локальном хосте с именем "Мой книжный магазин". Для простоты вместо использования базы данных или Файла мы создали метод инициализировать список() , который заполняет Список Объектами типа Книги , которые представляют книги, имеющиеся в нашем книжном магазине (...да только 5. Но 5 потрясающих книг!).

Нам также нужно добавить serialVersionUID для Сервера, но поскольку Сервер, который мы разработали в этом примере, будет существовать только на одной машине, нам не нужно думать об этом дважды, мы можем просто установить serialVersionUID по умолчанию . Однако, если бы класс сервера также был распространен, нам пришлось бы убедиться, что serialVersionUID ибо класс был одинаковым на всех платформах, которые его реализовали.

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 bookList;

    protected Bookstore(List 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 predicate = x -> x.getIsbn().equals(book.getIsbn());
        return bookList.stream().filter(predicate).findFirst().get();
    }

    @Override
    public List allBooks() throws RemoteException {
        return bookList;
    }

    private static List initializeList() {
        List 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. клиент

Клиент “находит” Сервер через объект интерфейса RMI , который “ищет” ссылку на удаленный объект, связанный с именем, которое мы передаем в качестве параметра. То, что мы только что описали, – это то, что Называние.поиск ("//локальный хост/Мой книжный магазин"); делает.

Остальная часть кода для клиента предназначена только для создания рабочего примера, с которым вы, надеюсь, могли бы поэкспериментировать.

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 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 или загрузки приведенного ниже кода перейдите в исходную папку, как показано ниже.

5.2 Первое, что нам нужно сделать, это собрать наши исходные тексты. Выполнить 1. Выполнить 1.

$ 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. запустите Client.bat из загруженных файлов) и запустите это:

$ cd src
$ java com.mkyong.rmiclient.Customer

5.6.1 Класс Customer запускается и предлагает нам действовать:

5.6.2 Когда мы нажимаем кнопку “Показать все”:

5.6.3 После нажатия кнопки “ОК”:

5.6.4 Мы нажимаем кнопку “Нет”, так как мы еще не хотим выходить, и появляется следующее диалоговое окно. Мы вводим ISBN (например, “978-0596009205”) и нажимаем “ОК”.

5.6.5 Если книга была найдена в списке Сервера:

5.6.6 Если он не был найден:

5.6.7 Программа будет продолжена, если вы спросите нас:

Если мы нажмем кнопку “Да”, программа выйдет. Если мы нажмем “Нет”, это вернет нас в главное меню, чтобы выбрать действие, как показано в 5.6.1.

Сервер будет продолжать работать до тех пор, пока мы не закроем его окно. Даже после закрытия Клиента мы можем открыть новый или даже несколько клиентов, которые работают одновременно.

Скачать Исходный Код

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

  1. Сериализуемый интерфейс – Java API
  2. Дистанционный – Java API
  3. Одноадресный объект – Java API
  4. Пример Java RMI Hello World
  5. Википедия – Удаленный вызов метода Java
  6. Википедия – Распределенные объекты

Оригинал: “https://mkyong.com/java/java-rmi-distributed-objects-example/”