
Интернет технологии / ЛР_8_МП
.docЛАБОРАТОРНАЯ РАБОТА №8
По курсу «Интернет-программирование»
Работа с удаленными объектами по технологии RMI Java
Цель работы.
Ознакомиться с технологией RMI.
Приобретаемые компетенции:
-
Понимание принципов создания интернет-приложений c использованием технологий удаленного вызова методов
-
Организация вызова удаленного метода для решения практической задачи
-
Принципы технологии RMI Java
-
RMI
RMI (Remote Method Invocation) — технология удаленного использования Java объектов для организации распределенных систем на базе сети компьютеров-узлов.
Пусть на удаленном компьютере есть метод Calculate, который для обработки получает объект пользовательского типа DateMassiv и после обработки возвращает объект пользовательского типа Result.
Тогда имеем следующую схему работы:
При вызове удаленных методов сервера клиентом вызывается (локально) метод класса-заглушки (stubs). Клиент не хранит копии вызываемых объектов сервера, а хранит ссылки на объекты-заглушки.
Метод класса заглушки производит:
-
Развертывание параметров (marshalling)
-
Передачу данных на сервер
-
Объект получатель выполняет:
-
Свертывание параметров
-
Поиск вызыванного объекта
-
Вызов данного метода
-
Извлечение возвращаемого значения или исключения
-
Передачу пакета клиенту
Типы удаленных объектов (на сервере) описываются на клиенте в виде интерфейса.
Листинг 1. Описание интерфейса с двумя методами: getData и makeCalculate
package miet;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMI extends Remote {
public String getData(String text) throws RemoteException;
public Result makeCalculate(BigData bd) throws RemoteException;
}
Поскольку интерфейс удаленных объектов потребуются как на клиенте, так и на сервере,
удобно делать интерфейс клиента в виде jar-архива, который загружается и на клиент и сервер.
Для удаленных объектов удобно делать интерфейс в виде jar-архива, который загружается и на клиент и сервер. Тогда, в случае обновления, собирается один новый jar и устанавливается на всех серверах и клиентах
Если удаленные объекты используют пользовательские типы данных (классы) то их также целесообразно описывать отдельно и импортировать в клиент, сервер и интерфейс.
Для иллюстрации работы RMI рассмотрим пример, разработанный в среде NetBeance. Идея примера: посылаем в удаленный метод объект, выполняем обработку, получаем в качестве ответа другой объект.
Пример содержит:
JavaMietLib – проект с библиотекой общих кастомных классов
RMIInterfase – проект с классами общих интерфейсов
RMIClient – проект с классами клиента
RMIServer – проект с классами сервера
Листинг 2. Класс интерфесов RMIInterface содержит объявления методов
package miet;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMI extends Remote {
//Обявлем простой метод возвращающий строку
public String getData(String text) throws RemoteException;
//Обявлем метод принимающий и возвращающий кастомный объект
public Result makeCalculate(BigData bd) throws RemoteException;
}
Пользовательских объектов в примере два: BigData и Result (см. Листинг 2). Опишем их в отдельном проекте JavaMietLib. Класс BigData хранит в себе коллекцию ArrayList, которая будет заполняться вещественными числами (float). Класс Result будет содержать сумму этих чисел во внутренней переменной Supremum, значение которой будет рассчитано в удаленном методе makeCalculate, которому будет передан объект BigData.
Листинг 3. Класс BigData
package miet;
import java.io.Serializable;
import java.util.ArrayList;
public class BigData implements Serializable {
//класс BigData будет содержать коллекцию ArrayList
private ArrayList data;
public void BigData( ArrayList temp ) {
this.data = temp;
}
public ArrayList getdata() {
return this.data;
}
public void setdata(ArrayList temp ) {
this.data = temp;
}
}
Листинг 4. Класс Result.
package miet;
import java.io.Serializable;
public class Result implements Serializable {
/*
класс Result будет хранить число типа float,
которое является результатом некоего расчета
*/
private float Supremum;
public float getSupremum() {
return this.Supremum;
}
public void setSupremum(float temp) {
this.Supremum = temp;
}
}
Клиент для работы с RMI в самом простом виде состоит из одного класса, реализующего метод main. Логично выделять метод работы с сервером отдельно и вызывать его в main. В примере этот метод называется connectServer().
Метод connectServer должен:
-
Подключиться к серверу
-
Войти в нужное пространство имен
-
Вызвать нужный метод в пространстве имен
В листинге 5 эти операции выделены жирным шрифтом.
Пространство имен определяет конкретный класс на удаленном сервере с которым будем работать т.к. на сервере может быть несколько классов, предназначенных для удаленной работы.
Поскольку и клиент и сервер в рамках нашего теста находятся на одной машине, IP адрес определяем как 127.0.0.1. Порт указываем 1099 (может быть любым не занятым) и такой-же порт надо будет указать в соответствующем месте класса сервера. Перед вызовом удаленного объекта makeCalculate cоздаем, передаваемый в него, объект BigData и заполняем его данными.
Листинг 5. Класс RMIClient.
package miet;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
public class RMIClient {
public static void main(String args[]) {
RMIClient client = new RMIClient(); //создаем экземпляр самого себя
System.out.println("Client created");
client.connectServer(); //вызываем метод работы с сервером
}
private void connectServer() {
try {
//1. Подключение к серверу
//получить ссылку на реестр удаленного объекта начальной
//загрузки на определенном узле (включая локальный узел)
Registry reg = LocateRegistry.getRegistry("127.0.0.1", 1099);
//2. Входим в нужное пространство имен
//создаем экземпляр объекта класса - заглушки
//с удаленного сервера MIETServer
RMI rmi = (RMI) reg.lookup("MIETServer");
System.out.println("Connect to server");
//Создаем объект BigData и заполняем его данными
ArrayList temp = new ArrayList();
temp.add(1.0F); temp.add(2.0F); temp.add(3.0F);
BigData bd = new BigData();
bd.setdata(temp);
System.out.println("--------------------------------------");
//3. Вызываем нужный метод в пространстве имен
Result rr = rmi.makeCalculate(bd); //выполняем метод на удал. объекте
System.out.println(rr.getSupremum()); //печатаем результат - 6
} catch(Exception e) { System.out.println(e); }
}
После разработки класса, разрабатываем класс сервера, который будет содержать (имплеминтировать) методы, к которым будут удаленно обращаться клиенты: getData и makeCalculate. Метод main сервера содержит регистрацию нашего сервера на веб-сервере в соответствующем пространстве имен, совпадающим с пространством имен клиента т.е. — MIETServer см. Листинг 6.
Листинг 6. Класс RMIServer.
package miet;
import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList; import miet.Result;
public class RMIServerImpl extends UnicastRemoteObject implements RMI {
public RMIServerImpl() throws RemoteException{ super(); }
public static void main(String args[]) {
try {
//Создает и экспортирует Registry экземпляр на локальном узле,
который принимает запросы на указанном port.
Registry reg = LocateRegistry.createRegistry(1099);
//Привязываем класс RMIServerImpl к имени MIETServer
reg.rebind("MIETServer", new RMIServerImpl());
System.out.println("Server started");
} catch(Exception e) {
System.out.println(e);
}
}
//Определяем метод getData
public String getData(String text) throws RemoteException {
text = "Stsrt "+text;
return text;
}
//Определяем метод makeCalculate
public Result makeCalculate(miet.BigData bd) throws RemoteException {
ArrayList bdArray = bd.getdata();
float suprm = 0;
Result r = new Result();
for(int i=0; i<bdArray.size(); i++) {
suprm += (float) bdArray.get(i);
}
r.setSupremum(suprm);
return r;
}
}
После разработки примера сначала запускаем сервер, а затем клиент, см рис. 1.
Рис. 1. Выполнение удаленных методов по технологии RMI
Задание на лабораторную работу
-
Реализовать работу удаленного метода по технологии RMI в соответствии с вариантом (при затруднении смотреть опорный пример из папки soft, файл rmi.zip)
-
Варианты:
1 |
Реализовать удаленный метод поиска наибольшего, наименьшего и среднего значений в коллекции содержащей вещественные числа. Длина коллекции до 1000 элементов. Коллекцию сформировать генератором случайных чисел. Тип коллекции — на усмотрение студента. Коллекцию передавать, а результат получать в виде объектов пользовательских классов. |
2 |
Реализовать удаленный метод сортировки по возрастанию коллекции содержащей строки. Длина коллекции до 100 элементов. Коллекцию сформировать генератором случайных чисел. Тип коллекции — на усмотрение студента. Коллекцию передавать, а результат получать в виде объектов пользовательских классов. |
3 |
Реализовать удаленный метод решения квадратного уравнения. Условие уравнения передавать, а результат получать в виде объектов пользовательских классов. |
Контрольные вопросы:
-
Что означает RMI?
-
Как работает технология RMI?
-
Что такое пространство имен в RMI?
-
Какие действия нужно выполнить, чтобы создать клиента?
-
Какие действия нужно выполнить, чтобы создать сервер?
-
Какие действия нужно выполнить, чтобы клиенту подключиться к серверу?
-
Какие действия нужно выполнить, чтобы сервер смог принимать запросы клиента?
-
Почему методы RMI описываются в виде интерфейса?
-
Как с помощью RMI организовать выполнение распределенных вычислений?
-
Какие задачи могут и не могут быть эффективно выполнены с помощью распределенных вычислений?