Начало работы с Java RMI

Начало работы с Java RMI

1. обзор

Когда две JVM должны общаться, Java RMI - это один из вариантов, который нам нужен для этого. В этой статье мы рассмотрим простой пример, демонстрирующий технологию Java RMI.

2. Создание сервера

Для создания RMI-сервера необходимо выполнить два шага:

  1. Создайте интерфейс, определяющий контракт клиент / сервер.

  2. Создайте реализацию этого интерфейса.

2.1. Определение контракта

Прежде всего, создадим интерфейс для удаленного объекта. Этот интерфейс расширяет интерфейс маркераjava.rmi.Remote.

Кроме того, каждый метод, объявленный в интерфейсе, выдаетjava.rmi.RemoteException:

public interface MessengerService extends Remote {
    String sendMessage(String clientMessage) throws RemoteException;
}

Однако обратите внимание, что RMI поддерживает полную спецификацию Java для сигнатур методов, если типы Java реализуютjava.io.Serializable.

В следующих разделах мы увидим, как и клиент, и сервер будут использовать этот интерфейс.

Для сервера мы создадим реализацию, которую часто называютRemote Object.

Для клиентаthe RMI library will dynamically create an implementation called a Stub.

2.2. Реализация

Кроме того, давайте реализуем удаленный интерфейс, снова называемыйRemote Object:

public class MessengerServiceImpl implements MessengerService {

    @Override
    public String sendMessage(String clientMessage) {
        return "Client Message".equals(clientMessage) ? "Server Message" : null;
    }

    public String unexposedMethod() { /* code */ }
}

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

Было бы необычно, если бы наш удаленный объект выдалRemoteException, поскольку это исключение обычно зарезервировано для библиотеки RMI, чтобы вызывать ошибки связи с клиентом.

Отказ от этого также имеет преимущество в том, что наша реализация не зависит от RMI.

Такжеany additional methods defined in the remote object, but not in the interface, remain invisible for the client.

3. Регистрация Сервиса

После создания удаленной реализации нам нужно привязать удаленный объект к реестру RMI.

3.1. Создание заглушки

Сначала нам нужно создать заглушку нашего удаленного объекта:

MessengerService server = new MessengerServiceImpl();
MessengerService stub = (MessengerService) UnicastRemoteObject
  .exportObject((MessengerService) server, 0);

Мы используем статический методUnicastRemoteObject.exportObject для создания нашей реализации-заглушки. The stub is what does the magic of communicating with the server over the underlying RMI protocol.

Первый аргументexportObject - это объект удаленного сервера.

Второй аргумент - это порт, которыйexportObject использует для экспорта удаленного объекта в реестр.

Нулевое значение указывает на то, что нам все равно, какой портexportObject использует, что является типичным и поэтому выбирается динамически.

К сожалению, методexportObject() без номера порта устарел.

3.2 Creating a Registry

Мы можем создать реестр локально для нашего сервера или как отдельную отдельную службу.

Для простоты мы создадим локальный по отношению к нашему серверу:

Registry registry = LocateRegistry.createRegistry(1099);

Это создает реестр, к которому заглушки могут быть привязаны серверами и обнаружены клиентами.

Кроме того, мы использовали методcreateRegistry, поскольку мы создаем реестр локально для сервера.

По умолчанию реестр RMI работает на порту 1099. Скорее, другой порт также можно указать в фабричном методеcreateRegistry.

Но в автономном случае мы вызываемgetRegistry, передавая имя хоста и номер порта в качестве параметров.

3.3 Binding the Stub

Следовательно, привяжем нашу заглушку к реестру. Реестр RMI - это средство именования, такое как JNDI и т. Д. Здесь мы можем следовать аналогичной схеме, привязывая нашу заглушку к уникальному ключу:

registry.rebind("MessengerService", stub);

В результате удаленный объект теперь доступен любому клиенту, который может найти реестр.

4. Создание клиента

Наконец, давайте напишем клиенту для вызова удаленных методов.

Для этого сначала нужно найти реестр RMI. Кроме того, мы будем искать заглушку удаленного объекта, используя ограниченный уникальный ключ.

И наконец, вызовем методsendMessage:

Registry registry = LocateRegistry.getRegistry();
MessengerService server = (MessengerService) registry
  .lookup("MessengerService");
String responseMessage = server.sendMessage("Client Message");
String expectedMessage = "Server Message";

assertEquals(expectedMessage, responseMessage);

Поскольку мы запускаем реестр RMI на локальном компьютере и порт по умолчанию 1099, мы не передаем никаких параметров вgetRegistry.

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

Как только мы ищем объект-заглушку с помощью реестра, мы можем вызвать методы на удаленном сервере.

5. Заключение

В этом руководстве мы получили краткое представление о Java RMI и о том, как оно может стать основой для клиент-серверных приложений. Следите за новостями о некоторых уникальных функциях RMI!

Исходный код этого руководства находится вon GitHub.