Опубликован: 10.10.2010 | Доступ: свободный | Студентов: 3208 / 299 | Оценка: 4.14 / 3.32 | Длительность: 13:16:00
ISBN: 978-5-9963-0444-8
Специальности: Системный архитектор
Лекция 5:

Использование Java RMI

< Лекция 4 || Лекция 5: 12345 || Лекция 6 >

Реализация удаленного интерфейса

Следующим этапом является определение реализации удаленного объекта. В нашем случае класс реализации удаленного объекта имеет то же имя, что и удаленный интерфейс, но заканчивается на Impl.

Класс UnicastRemoteObject (пакет java.rmi.server ) представляет базовые функциональные возможности, которые необходимы удаленным объектам для обслуживания удаленных запросов.

Конструкторы и методы класса UnicastRemoteObject возбуждают контролируемое исключение RemoteException,поэтому подклассы класса UnicastRemoteObject должны определять конструкторы, которые также возбуждают исключение RemoteException.

Конструктор класса UnicastRemoteObject экспортирует объект, чтобы сделать его доступным для приема удаленных вызовов. Экспорт объекта дает возможность удаленному объекту ожидать соединений с клиентами на анонимном порте (т.е. порте, выбираемом компьютером, на котором выполняется удаленный объект). Это дает возможность объекту осуществлять однонаправленное взаимодействие (взаимодействие "точка-точка" между двумя объектами посредством вызовов методов) с использованием стандартных соединений через сокеты. Классам удаленных объектов не нужно расширять этот класс, если эти классы применяют статический метод exportObject класса UnicastRemoteObject для экспорта удаленных объектов. Предполагается, что клиенты RMI должны осуществлять соединение на порте 1099 при попытке найти удаленный объект в реестре RMI. Перегруженный конструктор для класса UnicastRemoteObject дает возможность задавать дополнительную информацию, такую как номер порта для экспорта удаленного объекта. Для этого необходимо определить URL, который клиент может использовать для получения удаленной ссылки на объект. Эта ссылка применяется для вызова методов удаленного объекта. URL обычно имеет форму

rmi://хост:порт/ИмяУдаленногоОбъекта,

где хост представляет собой имя компьютера, который выполняет сервер реестра ( rmiregistry ) для удаленных объектов (он также является компьютером, на котором выполняется удаленный объект), порт представляет собой номер порта, на котором выполняется сервер реестра на хост-компьютере, а ИмяУдаленногоОбъекта - имя, которое клиент будет предоставлять при попытках обнаружить удаленный объект в реестре. Утилита rmi-registry обслуживает реестр удаленных объектов и является составной частью J2SE. Номер порта реестра RMI по умолчанию - 1099.

Для связывания удаленного объекта с реестром используются методы bind или rebind.Метод rebind гарантирует, что если объект уже был зарегистрирован под заданным именем, новый удаленный объект заменит ранее зарегистрированный объект. Это может быть важно, если регистрируется новая версия существующего удаленного объекта.

Класс BillingServiceImpl (пример 5.2) представляет собой удаленный объект, который реализует удаленный интерфейс BillingService.Клиент взаимодействует с объектом класса BillingServiceImpl,вызывая методы addNewCard, addMoney, subMoney, getCardBalance интерфейса BillingService для обработки информации по пластиковым картам. Класс BillingServiceImpl хранит сведения о картах в хэш-таблице (Hashtable),содержащей баланс пластиковой карты с именем посетителя (personName) и номером пластиковой карты ( card ), где номер карты является ключом таблицы.

1  // BillingServicelmpl.java
2  // BillingServiceImpl реализует удаленный интерфейс BillingService
  для
3  // предоставления удаленного объекта BillingService
4  package com.asw.rmi.ex1;
5
6  // Набор базовых пакетов Java
7  import java.rmi.*;
8  import java.util.*;
9  import java.rmi.server.*; 
10
11  public class BillingServiceImpl extends UnicastRemoteObject
12  implements BillingService {
13
14  private   Hashtable hash;   // хэш-таблица для хранения карт
15  // инициализация сервера
16  public BillingServiceImpl() throws RemoteException{
17  super();
18  hash = new Hashtable();
19  }
20
21  // реализация метода addNewCard интерфейса BillingService
22  public void addNewCard(String personName, String card)
23  throws RemoteException {
24
25  hash.put(card, new Double(0.0));
26  }
27
28  // реализация метода addMoney интерфейса BillingService
29  public void addMoney(String card, double money) throws RemoteException {
30  Double d = (Double)hash.get(card);
31
32  if (d!=null) hash.put(card,new Double(d.doubleValue()+money));
33  else throw new NotExistsCardOperation();
34  }
35
36  // реализация метода subMoney интерфейса BillingService
37  public void subMoney(String card, double money) throws RemoteException {
38  Double d = (Double)hash.get(card);
39
40  if (d!=null) hash.put(card,new Double(d.doubleValue()-money));
41  else throw new NotExistsCardOperation();
42  }
43
44  // реализация метода getCardBalance интерфейса BillingService
45  public double getCardBalance(String card) throws RemoteException {
46  Double d = (Double)hash.get(card);
47  if (d!=null) return d.doubleValue();
48  else throw new NotExistsCardOperation();
49  };
50
51  // запуск удаленного объекта BillingService
52  public static void main (String[] args) throws Exception {
53  System.out.println("Initializing BillingService...");
54
55  // создание удаленного объекта
56  BillingService service = new BillingServiceImpl();
57
58  //задание имени удаленного объекта
59  String serviceName = "rmi://localhost/BillingService";
60  // регистрация удаленного объекта BillingService в реестре rmiregistry
61  Naming.rebind(serviceName, service);
62  }
63
64  }
Листинг 5.2. Класс BillingServiceImpl реализует удаленный интерфейс BillingService

Класс BillingServiceImpl реализует методы addNewCard (строки 22-26), addMoney (строки 29-34), subMoney (строки 37-42), getCardBalance (строки 45-49) интерфейса BillingService,чтобы отвечать на удаленные запросы.

Метод main (строки 52-62) создает удаленный объект BillingServiceImpl.Когда конструктор выполняется, он экспортирует удаленный объект, чтобы прослушивать удаленные запросы. В строке 59 определяется URL, который клиент может применить для получения удаленной ссылки на объект для вызова методов удаленного объекта.

В этой программе URL удаленного объекта имеет вид rmi://localhost/BillingService. Из этого следует, что реестр RMI выполняется на машине localhost (т.е. на локальном компьютере), а для обнаружения клиентом сервиса нужно использовать имя BillingService.Имя localhost является синонимом IP -адреса 127.0.0.1 ( loopback ).

В строке 61 вызывается статический метод rebind класса Naming (пакет java.rmi) для связывания удаленного объекта service класса BillingServiceImpl в реестре RMI с URL rmi://localhost/BillingService.

Класс NotExistsCardOperation (пример 5.3) расширяет класс RemoteException.

1  // NotExistsCardOperation.java
2  package com.asw.rmi.ex1;
3
4  // Набор базовых пакетов Java
5  import java.rmi.RemoteException;
6
7  public class NotExistsCardOperation extends RemoteException {
8
9  }
Листинг 5.3. Класс NotExistsCardOperation реализует обработку исключений

Далее мы определяем клиентское приложение, которое будет обрабатывать запросы к пластиковым картам и пересылать их серверу. Для работы клиентского приложения необходимо знать URL вызываемого им удаленного объекта. Статический метод lookup класса Naming применяется для получения объектной ссылки на удаленный объект с заданным URL. Метод lookup осуществляет соединение с реестром RMI и возвращает удаленную ссылку на удаленный объект. Клиент может использовать эту удаленную ссылку, если она обращается к локальному объекту, выполняющемуся на той же виртуальной машине. Эта удаленная ссылка обращается к объекту-заглушке на клиенте. Заглушки дают возможность клиентам вызывать методы удаленного объекта. Объекты-заглушки принимают удаленные вызовы метода и передают эти вызовы RMI, который выполняет сетевые соединения, позволяющие клиентам взаимодействовать с удаленным объектом. Уровень RMI отвечает за сетевые соединения с удаленными объектами, поэтому обращения к удаленным объектам являются прозрачными для пользователя. RMI обслуживает соединение с удаленным объектом, передачу параметров и возврат значений.

Архитектура RMI

Рис. 5.1. Архитектура RMI

Класс BillingClient (пример 5.4) является клиентским приложением, которое вызывает удаленные методы addNewCard, addMoney и getCardBa-lance интерфейса BillingService для работы с пластиковыми картами посетителей через RMI. В нашем примере мы не реализуем реальную работу касс столовых с пластиковыми картами. Для иллюстрации определения и работы клиентского приложения нам достаточно произвести несколько операций с несколькими картами, используя удаленные методы удаленного объекта. В данном случае клиент в цикле заносит денежные средства на три пластиковые карты и в конце печатает результирующий баланс по этим пластиковым картам. При первом проходе цикла в случае отсутствия карт с заданными номерами клиент их создает.

1  // BillingClient.java
2  // BillingClient использует удаленный объект BillingService для
3  // работы с информацией на пластиковых картах
4  package com.asw.rmi.ex1;
5
6  // Набор базовых пакетов Java
7  import java.rmi.*;
8
9  public class BillingClient {
10  // выполнение BillingClient
11  public static void main(String[] args) throws Exception]
12  // создание строки, содержащей URL удаленного объекта
13  String objectName = "rmi://"+args[0]+"/BillingService";
14  System.out.println("Starting...\n");
15  // соединение с реестром RMI и получение удаленной ссылки
16  // на удаленный объект
17  BillingService bs = (BillingService)Naming.lookup(objectName);
18  System.out.println("done");
19
20  // начисление денежных средств на пластиковые карты
21  for (int i = 0; i < 10000;  i++) {
22  try {
23  bs.addMoney("1", 1);
24  } catch (RemoteException   e) {
25  bs.addNewCard("Piter", "1");
26  } 
27
28  try {
29  bs.addMoney("2", 1);
30  } catch (RemoteException   e) {
31  bs.addNewCard("Stefan", "2");
32  } 
33
34  try {
35  bs.addMoney("3", 1);
36  } catch (RemoteException   e) {
37  bs.addNewCard("Nataly", "3");
38  }
39  }
40  // печать текущего баланса обработанных карт
41  System.out.println("1:"+bs.getCardBalance("1"));
42  System.out.println("2:"+bs.getCardBalance("2"));
43  System.out.println("3:"+bs.getCardBalance("3"));
44  }
45  }
Листинг 5.4. Клиентское приложение BillingClient для удаленного объекта BillingService

Метод main (строки 11-44) принимает в качестве параметра имя компьютера, на котором выполняется удаленный объект BillingService.В строке 13 создается строка objectName,которая содержит URL для нашего удаленного объекта. В строке 17 вызывается метод lookup класса Naming для получения удаленной ссылки на удаленный объект BillingService с заданным URL. В строках 21-38 производится добавление денежных средств на карты, а в строках 41-43 - печать текущего баланса этих карт.

< Лекция 4 || Лекция 5: 12345 || Лекция 6 >
Алмаз Мурзабеков
Алмаз Мурзабеков
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type"


Java version 1.7.0_05