Remote Method Invocation (RMI). Задачи распределенного программирования Получить некоторую информацию от одной удаленной машины и переслать ее другой.

Презентация:



Advertisements
Похожие презентации
Сериализация и RMI Java Advanced. 2Georgiy KorneevJava Advanced / Сериализация и RMI Содержание Сериализация Концепции RMI Применение RMI Заключение.
Advertisements

Сокеты TCP/IP Лекция Понятие сокета Если требуется получить доступ к сетевым операциям низкого уровня (класс URL обеспечивает выполнение только.
Синтаксис языка Java. Символы и синтаксис Перевод строчки эквивалентен пробелу Регистр в именах различается.
Test 6 Вопрос 1. Как можно уничтожить объект в Java? a)присвоить null всем ссылкам на объект b)вызвать Runtime.getRuntime().gc() c)вызвать метод finalize()
Web - сервисы. Веб-служба, веб-сервис (англ. web service) идентифицируемая веб-адресом программная система со стандартизированными интерфейсами.англ.веб-адресоминтерфейсами.
Изучение динамического определения типов. Класс Class. Динамическая загрузка и инстанцирование классов. В Java вся информация о классе хранится в специальном.
Программная инженерия Андрей Дмитриев ©
Платформа J2EE Сервис: Java Naming Directory (JNDI) – универсальный сервис хранения объектов в иерархической структуре имен (аналогично файловой системе)
Лекция 2 Наследование Наследование в Java имеет тот же смысл, что и в С++. Однако наследование в Java осуществляется при помощи ключевого слова extends.
Язык Java. JSP.. Java. Синтаксис. Перевод строчки эквивалентен пробелу Регистр в именах различается // Комментарии до конца строки /* Многострочные комментарии.
Обработка исключительных ситуаций Исключительная ситуация (исключение) – это ошибка, возникающая во время выполнения программы. Например, ошибка работы.
Рассматриваемые темы Технология EJB Типы EJB Вызов EJB Сборка и развертывание EJB- приложения 2-1.
Обработка исключительных ситуаций. Синтаксис try{ операторы0; } catch (ТипИсключения1 переменная1){ операторы1; } catch (ТипИсключения2 переменная2){
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Платформа J2EE Сервис: Java Naming Directory (JNDI) – универсальный сервис хранения объектов в иерархической структуре имен (аналогично файловой системе)
Низкоуровневые операции в ИС. Сокеты в C#. Понятие сокета Если требуется получить доступ к сетевым операциям низкого уровня, в программе следует использовать.
Практическое использование Java Макаревич Л. Г.. Инсталляция Java Документация в docs Прописать PATH (каталог bin в JSDK) Прописать CLASSPATH (путь к.
Saint Petersburg, 2011 Java Lecture #06 Exceptions.
Высокоуровневые методы информатики и программирования Лекция 10 События.
Транксрипт:

Remote Method Invocation (RMI)

Задачи распределенного программирования Получить некоторую информацию от одной удаленной машины и переслать ее другой удаленной машине. Это делается с помощью базового сетевого программирования. Подсоединиться к базе данных, которая может находиться в сети. Это задача решается с помощью интерфейса Java для баз данных (Java DataBase Connectivity, JDBC). Представить услуги на Web-сервере. С этой задачей хорошо справляются сервлеты(servlets) и серверные страницы Java( Java Server Pages,JSP). Незаметно выполнить методы объектов, находящихся на удаленных машинах, так, как будто эти объекты созданы и находятся на локальной машине. Для решения этой задачи предназначен механизм удаленного вызова методов Java (Remote Method Invocation, RMI). Использовать код, написанный на других языках и выполняющийся на других платформах. Это выполняется с помощью посреднической архитектуры запросов общих объектов (Common Object Request Broker Architecture,CORBA), которая поддерживается в языках Java. Изолировать бизнес-логику от вопросов соединения и поддержки связи, что особенно важно для соединений с базами данных, включая управление транзакциями и безопасность. Решить эту задачу помогает промышленная технология Enterprise JavaBeans (EJB). ЕJB не является распределенной архитектурой, но полученные с ее помощью приложения обычно используются в клиент-серверных системах.

Удаленный вызов методов - RMI Java RMI – одна из реализаций промежуточного программного обеспечения Входит в состав jdk Следовательно не требует инсталляции, настройки, …

RMI Встроенная реализация механизма вызова удаленных методов Пакеты java.rmi.* Предназначен для реализации распределенных приложений с использованием ТОЛЬКО Java Экстремально прост в использовании

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

Элементы технологии Прокси (клиентская заглушка), скелетон и диспетчер генерируются автоматически Реализация методов серверных объектов выполняется программистом

Используемые классы Интерфейс java.rmi.Remote – методов не содержит, cлужит для указания классов, являющихся серверными Класс java.rmi.server.UnicastRemoteObject – используется для экспорта серверных классов и получения клиентских заглушек Интерфейс java.rmi.registry.Registry – реализации этого интерфейса содержат методы получения/помещения удаленных объектных ссылок по имени Класс java.rmi.registry.LocateRegistry – используется для получения ссылки на Registry

Удаленный интерфейс Удаленный интерфейс должен быть открытым – public. В противном случае клиенты будут получать ошибку при попытке загрузки удаленного объекта, реализующего удаленный интерфейс. Удаленный интерфейс должен расширять интерфейс, java.rmi.Remote. Каждый метод удаленного интерфейса должен объявлять java.rmi.RemoteException в своем предложении throws вдобавок к любым другим исключениям. Удаленный объект, передаваемый как аргумент или возвращаемое значение, должен быть объявлен как удаленный интерфейс, а не как класс с реализацией. Ниже приведен простой удаленный интерфейс, представляющий сервис точного времени: import java.rmi.* ; interface IPerfectTime extends Remote { long getPerfectTime () throws RemoteException; }

Реализация удаленного интерфейса import java.rmi.* ; import java.rmi.server.* ; import java.rmi.registry.* ; import java.rmi.net.* ; public class PerfectTime extends UnicastRemoteObject implements IPerfectTime { // Реализация метода интерфейса: public long getPerfectTime () throws RemoteException { return System.currentTimeMillis (); } // Обязательно должен быть реализован конструктор // для выбрасывания RemoteException public PerfectTime () throw RemoteException { } // Регистрация для обслуживания RMI. Выбрасывает // исключения на консоль. public static void main (String [] args) throws Exception { System.setSecurityManager (new RMISecurityManager ()); PerfectTime pt = new PerfectTime (); Naming.bind (/*Регистрация в реестре*/); } Создать и установить менеджер безопасности, поддерживающий сервисы RMI. Создать один или несколько экземпляров удаленного объекта. Зарегистрировать удаленные объекты в реестре удаленных объектов RMI

Установка реестра Реестр должен быть запущен отдельным процессом на компьютере командой: start rmiregistry 1099 – порт по умолчанию для запуска его в качестве фонового процесса или start rmiregistry 2005 URL имеет форму //хост:порт/ИмяУдаленногоОбъекта Naming.bind (//peppy: 2005/PerfectTime, pt); Naming.bind("//peppy/PerfectTime", pt);// порт:1099 Naming.bind("PerfectTime", pt); //для локальной машины Если имя уже зарегистрировано - AlreadyBoundException. Для предотвращения этого можно использовать rebind(). Naming.unbind() – удаление объекта из реестра Запуск rmiregistry через программу: LocateRegistry.createRegistry(2005);

Создание заглушек и каркасов Заглушки и каркасы создаются для обеспечения сетевого соединения. Создаются инструментом rmic для откомпилированного кода. rmic PerfectTime Будут созданы два новых класса: PerfectTime_Stub.class PerfectTime_Skel.class В последних версиях jdk появилась возможность автоматической генерации прокси-классов в момент выполнения программы (без явного использования утилиты rmic)

Использование удаленных объектов import java.rmi.*; import java.rmi.registry.*; public class DisplayPerfectTime { public static void main (String [] args) throws Exception { System.setSecurityManager (new RMISecurityManager ()) ; IPerfectTime t = (IPerfectTime ) Naming. lookup ( "//peppy: 2005/PerfectTime") ; for(int i = 0; i < 10; i++) System. out. println ( "Perfect time = " + t.getPerfectTime ()); } } ;

public class RmiServer extends UnicastRemoteObject implements RmiServerIntf { public static final String MESSAGE = "Hello world"; public RmiServer() throws RemoteException { } public String getMessage() { return MESSAGE; } public static void main(String args[]) { if (System.getSecurityManager() == null) {// Create and install a security manager System.setSecurityManager(new RMISecurityManager()); System.out.println("Security manager installed."); } else { System.out.println("Security manager already exists."); } try { //special exception handler for registry creation LocateRegistry.createRegistry(1099); System.out.println("java RMI registry created."); } catch (RemoteException e) { System.out.println("java RMI registry already exists."); } try { RmiServer obj = new RmiServer(); Naming.rebind("//localhost/RmiServer", obj); // Bind this object instance to the name "RmiServer" System.out.println("PeerServer bound in registry"); } catch (Exception e) { System.err.println("RMI server exception:" + e); } }

public class RmiClient { RmiServerIntf obj = null; public String getMessage() { try { obj = (RmiServerIntf)Naming.lookup("//localhost/RmiServer"); return obj.getMessage(); } catch (Exception e) { System.err.println("RmiClient exception: " + e); return e.getMessage(); } public static void main(String args[]) { // Create and install a security manager if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } RmiClient cli = new RmiClient(); System.out.println(cli.getMessage()); }

Пример 2. Определение интерфейса import java.rmi.Remote; import java.rmi.RemoteException; public interface Hello extends Remote { String sayHello() throws RemoteException; } Импорт элементов пакета java.rmi Объявление публичного интерфейса Интерфейс должен быть унаследован от java.rmi.Remote Методы бросают исключения RemoteException

Реализация серверного класса import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class Server implements Hello { public Server() {} public String sayHello() {return "Hello, world!"; } public static void main(String args[]) { try { Server obj = new Server(); Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); Registry registry = LocateRegistry.getRegistry(); registry.bind("Hello", stub); System.out.println("Server ready"); } catch (Exception e) { e.printStackTrace();} } Импорт элементов пакета java.rmi Серверный класс реализует интерфейс (Hello) Реализуется метод, определенный в удаленном интерфейсе В методе main Создается экземпляр класса Вызывается статический метод exportObject класса UnicastRemoteObject – объект экспортируется и становится способным принимать удаленные вызовы Полученный интерфейс помещается в сервис имен под именем Hello Другой способ состоит в наследовании серверного класса от класса UnicastRemoteObject

Реализация клиента import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class Client { private Client() {} public static void main(String[] args) { String host = (args.length < 1) ? null : args[0]; try { Registry registry = LocateRegistry.getRegistry(host); Hello stub = (Hello) registry.lookup("Hello"); String response = stub.sayHello(); System.out.println("response: " + response); } catch (Exception e) { System.err.println(e.toString()); e.printStackTrace(); } Импорт элементов пакета java.rmi В методе main С помощью сервиса имен ищется удаленный объект по имени Получается объектная ссылка Осуществляется вызов удаленного метода

Выполнение примера

Пример 3 Реализация программы обслуживания сети столовых, с использованием технологии RMI: определяется интерфейс, содержащий методы, осуществляющие базовые единичные операции (передача простых типов данных)

Интерфейс BillingService package com.asw.rmi.ex1; import java.rmi.*; public interface BillingService extends Remote { public void addNewCard(String personName, String card) throws RemoteException; public void addMoney(String card, double money) throws RemoteException;; public void subMoney(String card, double money) throws RemoteException; public double getCardBalance(String card) throws RemoteException; }

Класс BillingServiceImpl import java.rmi.*; import java.util.*; import java.rmi.server.*; public class BillingServiceImpl extends UnicastRemoteObject implements BillingService { private Hashtable hash; public BillingServiceImpl() throws RemoteException{ super(); hash = new Hashtable(); } public void addNewCard(String personName, String card) throws RemoteException { hash.put(card, new Double(0.0)); } public void addMoney(String card, double money) throws RemoteException { Double d = (Double)hash.get(card); if (d!=null) hash.put(card,new Double(d.doubleValue()+money)); else throw new NotExistsCardOperation(); //расширяет RemoteException }

public void subMoney(String card, double money) throws RemoteException { Double d = (Double)hash.get(card); if (d!=null) hash.put(card,new Double(d.doubleValue()-money)); else throw new NotExistsCardOperation(); } public double getCardBalance(String card) throws RemoteException{ Double d = (Double)hash.get(card); if (d!=null) return d.doubleValue(); else throw new NotExistsCardOperation(); }; public static void main (String[] args) throws Exception { System.out.println("Initializing BillingService..."); BillingService service = new BillingServiceImpl(); String serviceName = "rmi://localhost/BillingService"; Naming.rebind(serviceName, service); }

Утилита rmic J2SE rmic -v1.2 -keep com.asw.rmi.ex1.BillingServiceImpl Генерируется класс BillingServiceImpl_Stub Исходный текст уничтожается после компиляции (если не указан параметр -keep) v1.2 – создание только заглушки

Класс BillingClient import java.rmi.*; public class BillingClient { public static void main(String[] args) throws Exception{ String objectName = "rmi://"+args[0]+"/BillingService"; // URL удаленного объекта BillingService bs = (BillingService)Naming.lookup(objectName); for (int i = 0; i < 10000; i++) { try {bs.addMoney("1", 1); } catch (RemoteException e) {bs.addNewCard("Piter", "1");} try {bs.addMoney("2", 1); } catch (RemoteException e) {bs.addNewCard("Stefan", "2");} try {bs.addMoney("3", 1); } catch (RemoteException e) {bs.addNewCard("Nataly", "3");} } System.out.println("1:"+bs.getCardBalance("1")); System.out.println("2:"+bs.getCardBalance("2")); System.out.println("3:"+bs.getCardBalance("3")); }

Компиляция и выполнение Генерация заглушек rmic –v1.2 com.asw.rmi.ex1.BillingServiceImpl Запуск сервиса имен (реестра) rmiregistry Запуск сервера java com.asw.rmi.ex1.BillingServiceImpl Запуск клиента java com.asw.rmi.ex1.BillingClient

Синхронизация 1 вариант public synchronized void addMoney(String card, double money) throws RemoteException { Double d = (Double)hash.get(card); if (d!=null) hash.put(card,new Double(d.doubleValue()+money)); else throw new NotExistsCardOperation(); } 2 вариант public void addMoney(String card, double money) throws RemoteException{ synchronized (hash) { Double d = (Double) hash.get(card); if (d != null) hash.put(card, new Double(d.doubleValue() + money)); else throw new NotExistsCardOperation(); }