Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type" Java version 1.7.0_05 |
Использование Java RMI
Далее мы определяем клиентское приложение, которое будет обрабатывать запросы к пластиковым картам.
Класс BillingClient (пример 5.12) является клиентским приложением, которое вызывает удаленные методы addNewCard, addMoney и getCardBalance интерфейса BillingService для работы с пластиковыми картами посетителей через RMI. Для иллюстрации работы клиентского приложения нам достаточно произвести несколько операций с несколькими картами, используя удаленные методы удаленного объекта. В данном случае, так же как и в первом примере, мы в цикле заносим денежные средства на три пластиковые карты, предварительно их создав, и в конце печатаем результирующий баланс по этим картам.
1 // BillingClient.java 2 // BillingClient использует удаленный объект BillingService для 3 // работы с информацией на пластиковых картах 4 package com.asw.rmi.ex2; 5 6 // Набор базовых пакетов Java 7 import java.rmi.*; 8 import java.util.Date; 9 10 public class BillingClient { 11 // выполнение BillingClient 12 public static void main(String[] args) throws Exception] 13 // создание строки, содержащей URL удаленного объекта 14 String objectName = "rmi://"+args[0]+"/BillingService"; 15 System.out.println("Starting...\n"); 16 // соединение с реестром RMI и получение удаленной ссылки 17 // на удаленный объект 18 BillingService bs = (BillingService)Naming.lookup(objectName); 19 System.out.println("done"); 20 21 // проверка на наличие карт с указанными номерами 22 // в случае отсутствия карты с указанными параметрами 23 // добавляем новую карту 24 Card c; 25 c = bs.getCard("1"); 26 if (c==null) { 27 c = new Card("Piter",new Date(),"1",0.0); 28 bs.addNewCard(c); 29 } 30 31 c = bs.getCard("2"); 32 if (c==null) { 33 c = new Card("Stefan",new Date(),"2",0.0); 34 bs.addNewCard(c); 35 } 36 37 c = bs.getCard("3"); 38 if (c==null) { 39 c = new Card("Nataly",new Date(),"3",0.0); 40 bs.addNewCard(c); 41 } 42 43 // определение массива операций по картам 44 System.err.println("begin...\n"); 45 int cnt = 30000; 46 CardOperation[] co = new CardOperation[cnt]; 47 for (int i = 0; i < i++;) { 48 switch (i%3){ 49 case 0: co[i] = new CardOperation("1",1,new Date());break; 50 case 1: co[i] = new CardOperation("2",1,new Date());break; 51 case 2: co[i] = new CardOperation("3",1,new Date());break; 52 } 53 } 54 // проведение указанных в массиве операций 55 bs.processOperations(co); 56 57 // печать текущего баланса обработанных карт 58 System.out.println(bs.getCard("1")); 59 System.out.println(bs.getCard("2")); 60 System.out.println(bs.getCard("3")); 61 } 62 }Листинг 5.12. Клиентское приложение BillingClient для удаленного объекта BillingService
Метод main (строки 12-61) принимает в качестве параметра имя компьютера, на котором выполняется удаленный объект BillingService.В строке 14 создается строка objectName,которая содержит URL для нашего удаленного объекта. В строке 18 вызывается метод lookup класса Naming для получения удаленной ссылки на удаленный объект BillingService с заданным URL. В строках 24-41 производится проверка наличия карт с номерами №1, №2, №3, в случае их отсутствия производится добавление новых карт с соответствующими параметрами. В строках 44-53 определяется массив операций по указанным картам. В цикле в массив заносятся операции по добавлению денежных средств на указанные карты и в указанном количестве. В строке 55 метод processOperations производит изменение балансов согласно полученному в качестве параметра массиву операций по картам. В строках 58-60 печатаем текущий баланс карт с номерами №1, №2, №3.
Компиляция и выполнение сервера и клиента
Компиляция и запуск аналогичны для первого примера. Для начала необходимо компилировать классы. Далее нужно компилировать класс удаленного объекта (...Impl).
Для нашего примера командная строка для компиляции класса удаленного объекта будет выглядеть следующим образом:
rmic -v1.2 com.asw.rmi.ex2.BillingServiceImpl
и она сгенерирует файл BillingServiceImplStub.class.
Следующий этап - запуск реестра RMI, который зарегистрирует удаленный объект. Командная строка
rmiregistry
запускает реестр RMI на локальной машине.
Для связывания объекта с именем в реестре RMI необходимо запустить серверное приложение из командной строки. В нашем случае командная строка выглядит следующим образом:
java com.asw.rmi.ex2.BillingServiceImpl
В результате отображается сообщение об инициализации BillingService.
Теперь клиентское приложение может соединиться с удаленным объектом, выполняющемся на локальной машине localhost.Команда
java com.asw.rmi.ex2.BillingClient localhost
соединит BillingClient с объектом BillingServiceImpl.
Сравнение двух реализаций
Несмотря на то, что два рассмотренных примера делают практически одно и то же, они все же достаточно сильно различаются. О первом отличии уже говорилось, однако нелишним будет еще раз акцентировать внимание на том, что во втором примере осуществлена передача пользовательских типов от клиента к серверу. И для того, чтобы это реализовать, нам не потребовалось предпринимать никаких действий, кроме объявления наших классов как сериализуемые. Абсолютно всю техническую работу сделала за нас RMI. Второе отличие заключается в скорости работы этих двух приложений - второе приложение работает гораздо быстрее. Связано это с тем, что вызов удаленного метода связан с довольно большими накладными расходами, заметную часть которых составляет время работы системной "обвязки" - чем меньше вызовов, тем этот вклад меньше. Свой вклад, безусловно, вносит и передача данных по сети - передача большого количества мелких пакетов опять же связана с большими накладными расходами, чем передача одного объемного.