Все о реестре Java RMI и как его использовать

RMI расшифровывается как удаленный вызов метода и, как видно из названия, является протоколом для Java-программы для вызова метода объекта, запущенного на другом компьютере. Предоставляет API

(Интерфейс прикладного программирования) для экспорта объекта из одной программы (называемой сервером) и вызова методов этого объекта из другой программы (называемой клиентом), возможно, работающих на другом компьютере.

Ява Реестр RMI является ключевым компонентом системы Java RMI и предоставляет централизованный каталог для серверов для регистрации служб и для клиентов для поиска этих служб. В этой статье мы узнаем, как реализовать сервер для предоставления объекта и клиента для вызова метода на сервере, а также для регистрации и поиска службы в реестре RMI.

как работает реестр Java RMI

Объявление интерфейса сервера

Чтобы узнать тонкости работы системы Java RMI, давайте реализуем простой серверный объект, предоставляющий метод для принятия имени и возврата приветствия. Вот определение интерфейса объекта:

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Greeting extends Remote
{
public String greet(String name) throws RemoteException;
}

Название интерфейса называется Приветствие. Он предоставляет единственный метод, называемый greet (), который принимает имя и возвращает подходящее приветствие.

Чтобы пометить этот интерфейс как экспортируемый, необходимо расширить java.rmi.Remote интерфейс. Также метод должен объявить листинг предложения throws java.rmi.RemoteException в дополнение к любым исключениям конкретного приложения

, Это делается для того, чтобы клиентский код мог обрабатывать (или распространять) ошибки вызова удаленных методов, такие как хост-не найден, сбой соединения и т. Д.

Реализация объекта сервера

После объявления интерфейса (который используется клиентами) мы реализуем объект на стороне сервера и предоставляем метод greet (), как показано. Для форматирования приветствия используется простая строка формата.

public class GreetingObject implements Greeting
{
private String fmtString = "Hello, %s";
public String greet(String name)
{
return String.format(this.fmtString, name);
}
}

Основной метод сервера

Давайте теперь соберем все эти части вместе и реализуем метод main () сервера. Давайте пройдемся по каждому из соответствующих шагов.

  • Первым шагом является создание реализации объекта сервера.
    Greeting greeting = new GreetingObject();
    
  • Затем мы получаем заглушку для объекта сервера из среды выполнения RMI. Заглушка реализует тот же интерфейс, что и объект сервера. Однако метод реализует необходимую связь с объектом удаленного сервера. Эта заглушка используется клиентом для прозрачного вызова метода на объекте сервера.
    Greeting stub = (Greeting)UnicastRemoteObject.exportObject(greeting, 0);
    
  • Как только заглушка получена, мы передаем эту заглушку в реестр RMI для привязки к указанной именованной службе. Когда клиент запрашивает реализацию этой службы, он получает заглушку, которая знает, как связаться с объектом сервера. В дальнейшем статический метод LocateRegistry.getRegistry () используется для получения ссылки на локальный реестр. Затем метод rebind () используется для привязки имени к заглушке.
    String name = "Greeting";
    Registry registry = LocateRegistry.getRegistry(port);
    registry.rebind(name, stub);
    

Полный основной метод.

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class Main
{
static public void main(String[] args) throws Exception
{
if ( args.length == 0 ) {
System.err.println("usage: java Main port#");
System.exit(1);
}
int index = 0;
int port = Integer.parseInt(args[index++]);
String name = "Greeting";
Greeting greeting = new GreetingObject();
Greeting stub = (Greeting)UnicastRemoteObject.exportObject(greeting, 0);
Registry registry = LocateRegistry.getRegistry(port);
registry.rebind(name, stub);
System.out.println("Greeting bound to \"" + name + "\"");
}
}

Сборка сервера

Давайте теперь посмотрим на создание сервера. Для простоты мы строим с помощью командной строки в Linux, а не с помощью инструмента сборки, такого как Maven.

Следующее компилирует исходные файлы в файлы классов в целевом каталоге.

rm -rf target
mkdir target
javac -d target src/server/*.java

Соберите файлы классов в файл JAR для выполнения.

jar cvf target/rmi-server.jar -C target server

Мы также собираем файлы интерфейса, необходимые для компиляции клиента в библиотеку JAR.

jar cvf target/rmi-lib.jar -C target server/Greeting.class

Реализация клиента

Теперь давайте рассмотрим реализацию клиента, используемого для вызова методов объекта сервера.

  • Как и на сервере, получите ссылку на реестр, указав имя хоста, на котором работает реестр, и номер порта.
    Registry registry = LocateRegistry.getRegistry(host, port);
    
  • Далее ищем сервис в реестре. Метод lookup () возвращает заглушку, которую можно использовать для вызова служб.
    Greeting greeting = (Greeting) registry.lookup(name);
    
  • И вызвать метод, передавая необходимые аргументы. Здесь мы получаем приветствие, передавая имя и распечатывая его.
    System.out.println(name + " reported: " + greeting.greet(myName));
    

Полный код клиента:

package client;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import server.Greeting;
public class Client
{
static public void main(String[] args) throws Exception
{
if ( args.length != 3 ) {
System.err.println("usage: java Client host port myName");
System.exit(1);
}
int index = 0;
String host = args[index++];
int port = Integer.parseInt(args[index++]);
String myName = args[index++];
String name = "Greeting";
Registry registry = LocateRegistry.getRegistry(host, port);
Greeting greeting = (Greeting) registry.lookup(name);
System.out.println(name + " reported: " + greeting.greet(myName));
}
}

Реестр RMI

Давайте теперь запустим серверную программу, чтобы она могла начать обслуживать запросы.

java -cp target/rmi-server.jar server.Main 1099
# throws
Exception in thread "main" java.rmi.ConnectException: Connection refused to host: xxx; nested exception is:
java.net.ConnectException: Connection refused

Что это за исключение

? В соединении отказано.

Причина, по которой вы получаете это исключение, заключается в следующем: обратите внимание, что из кода сервера он пытается подключиться к локальному реестру через порт 1099. В случае сбоя вы получите это исключение.

Решение состоит в том, чтобы запустить Реестр RMI. Реестр RMI — это программа, поставляемая с виртуальной машиной Java, которая называется rmiregistry. Он должен находиться в каталоге bin установки Java Virtual Machine. Запуск это так же просто, как:

/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry

По умолчанию реестр прослушивает порт 1099. Чтобы прослушивать другой порт, укажите номер порта следующим образом:

/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100

Убедитесь, что на указанном порту действительно есть прослушиватель с помощью команды netstat

:

netstat -an -t tcp -p | grep LISTEN
...
tcp6 0 0 :::1100 :::* LISTEN 23450/rmiregistry

Запуск сервера

Давайте теперь попробуем снова запустить сервер.

java -cp target/rmi-server.jar server.Main 1100
# throws
java.rmi.UnmarshalException: error unmarshalling arguments
...
Caused by: java.lang.ClassNotFoundException: server.Greeting
...

Снова исключение! Что на этот раз?

Сервер не может загрузить интерфейсный класс server.Greeting. Это происходит потому, что реестр RMI не может загрузить требуемый класс. Таким образом, вам нужно указать расположение необходимых классов. Один из способов сделать это — указать переменную среды CLASSPATH:

CLASSPATH=../../junk/target/rmi-lib.jar /usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100

Попытка запустить сервер снова дает:

java -cp target/rmi-server.jar server.Main 1100
# prints
Greeting bound to "Greeting"

Теперь сервер работает.

Запуск клиента

После того, как все части собраны и выполнены, запустить клиент просто. Для выполнения необходимы соответствующие JAR-файлы. К ним относятся класс, содержащий метод main (), и класс интерфейса. Он принимает аргументы, указывающие, где работает реестр RMI, и имя для приветствия.

java -cp target/rmi-client.jar:target/rmi-lib.jar client.Client localhost 1100 Peter
# prints
Greeting reported: Hello, Peter

Резюме

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

Вы используете Java RMI в своем проекте? Каким был ваш опыт? Есть ли альтернативы, которые вы исследовали? Пожалуйста, дайте нам знать в комментариях ниже.

Ссылка на основную публикацию