|
Прохожу курс "Построение распределенных систем на Java" в третьей лекции где описывается TCPServer вылетает эта ошибка
"Connection cannot be resolved to a type" Java version 1.7.0_05 |
Использование Java RMI
Второй пример
В предыдущем примере мы создали серверный объект, который принимает от клиента (методы изменения баланса) и возвращает клиенту (метод запроса значения баланса) переменные простых типов. Однако с помощью RMI могут создаваться приложения, обмен в которых осуществляется посредством передачи сложных типов - классов, определенных пользователем. Для того чтобы проиллюстрировать эту технику, изменим наш пример. Предположим, что операции начисления и списания наличных с карт передаются на сервер не по одной, а пакетом, т.е. массивом. Предположим также, что у сервера вместо метода запроса баланса должен быть реализован метод запроса карты по ее идентификатору. Карта - класс, который кроме номера содержит также имя владельца, баланс и дату заведения.
Определение удаленного интерфейса
В отличие от предыдущего варианта интерфейс BillingService (пример 5.7) имеет не четыре, а три метода. Метод addNewCard (строка 11) заводит новую карту с указанными параметрами. Метод processOperations (строка 13) производит изменение баланса карт с указанными параметрами. В предыдущей реализации изменение баланса карты производилось двумя методами, один из которых увеличивал текущий баланс карты, другой - уменьшал, а величина изменения в любом случае была положительной. В данном случае величина изменения баланса может быть любой - как положительной, так и отрицательной; в первом случае это означает поступление денежных средств на баланс карты, во втором - списание денежных средств. Метод getCard (строка 15) по номеру карты возвращает экземпляр класса Card.
1 // BillingService.java
2 // Интерфейс BillingService объявляет методы для работы
3 // с пластиковыми картами
4 package com.asw.rmi.ex2;
5
6 // Набор базовых пакетов Java
7 import java.rmi.*;
8
9 public interface BillingService extends Remote {
10 // определение новой карты
11 public void addNewCard(Card card) throws RemoteException;
12 // изменение баланса карты
13 public void processOperations(CardOperation[] operations) throws RemoteException;
14 // получение баланса карты
15 public Card getCard(String card) throws RemoteException;
16 }
Листинг
5.7.
Интерфейс BillingService
Как уже говорилось ранее, RMI использует механизм сериализации по умолчанию Java для передачи параметров методу и возврата значений через сеть. Поэтому все классы, используемые в качестве параметров метода и возвращаемых значений, должны иметь описатель Serializable.
Тип Card (пример 5.8) несет информацию об имени посетителя ( person ), дате получения карты (createDate),номере карты (cardNumber) и балансе (balance).
1 // Card.java
2 // описание типа переменных Card
3 package com.asw.rmi.ex2;
4
5 // Набор базовых пакетов Java
6 import java.io.Serializable;
7 import java.util.*;
8
9 public class Card implements Serializable{
10 public Card(String person, Date createDate, String cardNumber, double balance)]
11 this.person = person;
12 this.createDate = createDate;
13 this.cardNumber = cardNumber;
14 this.balance = balance;
15 }
16 public String person;
17 public Date createDate;
18 public String cardNumber;
19 double balance;
20 public String toString(){
21 return "Card: cardNumber="+cardNumber+"\tBalance="+balance+
22 +"\tPerson="+person+"\tCreateDate="+createDate+"";
23 }
24 }
Листинг
5.8.
Описание типа Card
Тип CardOperation (пример 5.9) представляет собой одну операцию изменения баланса карты и несет информацию о номере карты (card),величине изменения баланса карты ( amount ) и дате операции (operationDate).
1 // CardOperation.java
2 // описание типа переменных CardOperation
3 package com.asw.rmi.ex2;
4
5 // Набор базовых пакетов Java
6 import java.util.*;
7 import java.io.*;
8
9 public class CardOperation implements Serializable {
10 public CardOperation(String card,double amount,Date operationDate){
11 this.card = card;
12 this.amount = amount;
13 this.operationDate = operationDate;
14 }
15 public String card;
16 public double amount;
17 public Date operationDate;
18 }
Листинг
5.9.
Описание типа CardOperation
Реализация удаленного интерфейса
Класс BillingServiceImpl (пример 5.10) является удаленным объектом, который реализует удаленный интерфейс BillingService.Класс BillingServiceImpl реализует методы addNewCard (строки 22-25), processOperations (строки 28-36), getCard (строки 39-42) интерфейса BillingService,чтобы отвечать на удаленные запросы. Класс BillingServiceImpl хранит сведения о картах в хэш-таблице (Hashtable),содержащей карты (Card),где номер карты (cardNumber) является ключом таблицы.
1 // BillingServicelmpl.java
2 // BillingServiceImpl реализует удаленный интерфейс BillingService
3 // для предоставления удаленного объекта BillingService
4 package com.asw.rmi.ex2;
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(Card card) throws RemoteException {
23
24 hash.put(card.cardNumber, card);
25 }
26
27 // реализация метода processOperations интерфейса BillingService
28 public void processOperations(CardOperation[] operations)
29 throws RemoteException {
30 for (int i=0;i<operations.length;i++){
31 Card c = (Card)hash.get(operations[i].card);
32 if (c==null) throw new NotExistsCardOperation();
33 c.balance+=operations[i].amount;
34 hash.put(operations[i].card,c);
35 }
36 }
37
38 // реализация метода getCard интерфейса BillingService
39 public Card getCard(String card) throws RemoteException{
40 Card c = (Card)hash.get(card);
41 return c;
42 };
43
44 // запуск удаленного объекта BillingService
45 public static void main (String[] args) throws Exception {
46 System.out.println("Initializing BillingService...");
47
48 // создание удаленного объекта
49 BillingService service = new BillingServiceImpl();
50
51 //задание имени удаленного объекта
52 String serviceName = "rmi://localhost/BillingService";
53 // регистрация удаленного объекта BillingService в реестре rmiregistry
54 Naming.rebind(serviceName, service);
55 }
56
57 }
Листинг
5.10.
Класс BillingServiceImpl реализует удаленный интерфейс BillingService
Метод main (строки 45-55) создает удаленный объект BillingServiceImpl.В строке 52 определяется URL, который клиент может применить для получения удаленной ссылки на объект для вызова методов удаленного объекта.
В этой программе URL удаленного объекта имеет вид rmi://localhost/BillingService, т.е. реестр RMI выполняется на машине localhost (т.е. на локальном компьютере), а для обнаружения клиентом сервиса должно использоваться имя BillingService.Имя localhost является синонимом IP -адреса 127.0.0.1.
В строке 54 вызывается статический метод rebind класса Naming (пакет java.rmi) для связывания удаленного объекта service класса BillingServiceImpl в реестре RMI с URL rmi://localhost/BillingService.
Класс NotExistsCardOperation (пример 5.11) расширяет класс RemoteException.
1 // NotExistsCardOperation.java
2 package com.asw.rmi.ex2;
3
4 // Набор базовых пакетов Java
5 import java.rmi.RemoteException;
6
7 public class NotExistsCardOperation extends RemoteException {
8
9 }
Листинг
5.11.
Класс NotExistsCardOperation реализует обработку исключений