Распределенные системы обработки информации
Недашковский Вячеслав Михайлович
Лекции 2006
Содержание
Литература
1. Язык программирования Java
1.1. История и предпосылки
1.2. Сопоставление с C++
1.3. Архитектура Java
1.4. Синтаксис Java
1.5. Простые типы в Java
1.6. Классы и объекты в Java.
1.7. Переменные, именованные константы, массивы, перечисления в Java.
1.8. Наследование и о классе Class.
1.9. Интерфейсы и обратные вызовы в Java.
1.10. Вложенные классы и интерфейсы.
1.11. Цикл for-each, аргументы переменной длины, настраиваемые типы в Java.
1.12. Многопоточность в Java: создание потоков.
1.13. Многопоточность в Java: синхронизация
1.14. Ввод-вывод в Java: общие сведения.
1.15. Форматированный ввод-вывод в Java (J2SE 1.5)
1.16. О программировании графики в Java.
1.17. Реализация технологии клиент-сервер на Java.
1.18. Апплеты в Java.
1.19. Технология RMI в Java.
1.20. Об интерфейсе JDBC.
1.21. Общие сведения о технологии CORBA.
2. Общие положения теории РСОИ
2.1. Понятие о РСОИ
2.2. Примеры РСОИ.
2.3. Нефункциональные требования к РСОИ
2.4. Прозрачность в РСОИ
2.5. Удаленный вызов процедуры: общие сведения
2.6. Передача параметров при удаленном вызове процедур.
2.7. Организация распределенных объектов
2.8. Передача параметров при обращении к удаленным объектам.
2.9. Серверы объектов.
2.10. Перенос кода в РСОИ
2.11. Модель клиент-сервер
2.12. Общие сведение об именовании объектов и службе именования
2.13. Общие сведения о синхронизации в РСОИ
2.14. Жизненный цикл распределенных объектов
3. Технология J2EE
3.1. Общие сведения
3.2. Архитектура J2EE
3.3. EJB – Enterprise Java Beans
1. Кен Арнолд, Джеймс Гослинг, Дэвид Холмс. Язык программирования Java, 3-е изд. пер. с. англ. –М: изд. дом «Вильямс», 2002.
2. Таренбаум Э. Распределенные системы. Принципы и парадигмы. –СПб: Питер, 2003 – 877с.
3. Эммерих В. Конструирование распределенных объектов. Методы и средства программирования интероперабельных объектов в архитектурах OMG/CORBA, Microsoft/Com и Java/RMI.
4. Изимбал А. А., Анишина М.Л. Технология создания распределенных систем для профессионалов – СПб:
Цель курса: привести основные сведения о языке Java а также общие сведения о РС, и технологиях создания РС; дать первичные навыки программирования на языке Java.
Язык программирования Java
1991г. Группа инжинеров SUN занялась разработкой языка, который можно было бы использовать в бытовых устройствах. Идея – создать язык, который бы не зависил ни от машины, ни от процессора. За основу был взять синтаксис С++. Язык не был востребован. Решили написать браузер с использованием этой технологии. 1 версия языка появилась в 1996 году. 1998 году вышла версия языка Java 1.2 – полноценный язык. Язык платформенно независим. Недостаток – быстродействие. Программы выполняются под виртуальной машиной. Компиляция программ происходит в т.н. байткод, которые потом интерпретируется средой исполнения. В среде исполнения, в свою очередь, присутствует менеджер безопасности. Оcобености:
1. Мобильный код – одна программа, много вычислительных платформ.
2. Безопасный код – встроенная в язык защита от несанкционированного доступа к ресурсам компьютера.
3. Устойчивый код - обнаружение ошибок возможно на ранних стадиях проектирования. Больше нет ошибок управления памятью.
Java написан на основе C++ – синтаксис очень похож.
C++
|
Java
|
Разедление на объявления и определения
|
нет
|
Const
|
нет, есть final
|
>> - нет разницы между логическим и арифметическим сдвигом
|
>> - арифметический
>>> - логический
|
0, 1
|
false, true
|
строки как таковые отсутствуют
|
ReadOnly, в памяти под новую строку формируется место, старая исчезает из области видимости
|
goto
|
нет goto, зато есть break <метка>
|
1.2 Архитектура Java
Промежуточный код – байт код – виртуальной машины Java. Управляемый код не может содержать указателей. Обязательно должен присутствовать сборщик мусора.
Простейшая программа:
class Hello { public static void main(String[] args) {
System.out.println(“Hello world!”); }}
Модификаторы и функция main нужны, чтобы класс был приложением. String[] – массив. Так как в метод main не передается адрес объекта, то он объявлен с модификатором static, а адрес объекта не передается, так как до вызова никакого объекта не создавалось, то передавать нечего.
class Fib {/** Вывод на экран последовательности чисел Фибоначчи, меньших 50 */ public static void main(String[] args) { int l = 1, ni = 1; System.out.println(l); while (ni < l) { System.out.println(ni); ni = l+ni; // новое значение ni l = ni-l; /* новое значение l */ } }}
Простые типы в Java
Обозначение типа
|
Размер (bit)
|
Примечание
|
byte
|
8
|
знаковый
|
short
|
16
|
знаковый
|
int
|
32
|
знаковый
|
long
|
64
|
знаковый
|
float
|
32
|
знаковый
|
double
|
64
|
знаковый
|
char
|
16
|
Unicode
|
1.4. Классы и объекты в Java.
Программа на языке Java – совокупность классов. Объявление класса:
{public, final|abstract} class ClassName
{
[constructors]
[variables]
[methods]
public static void main(String[] args) { … }
}
public – класс виден всем остальным классам (если не указан, класс виден только в своем пакете), final – от класса нельзя породить потомков, abstract – нельзя создать экземпляр класса. Функция main не обязательна, это точка входа в программу.
Классы организуются в пакеты (аналог пространств имен). В одном файле может быть только один public-класс.
Создание объекта:
new ClassName(параметры конструктора). Возвращает ссылку на объект.
Класс может содержать объявления конструкторов:
public ClassName(параметры...) { ... }
Если ни один конструктор не определен, неявно определяется конструктор без параметров, которые устанавливает все поля в значения по умолчанию (числа – в нуль, логические – в ложь, ссылки – в null).
В первой строке конструктора можно вызвать другой конструктор:
public MyClass(String a) { … }
public MyClass() { this(“default”); … }
Определение методов:
{public|private|protected} {тип возвр. значения | void} ИмяМетода(параметры метода) { тело метода }
public – метод доступен всем классам, private – только данному классу, protected – только данному классу и его наследникам, без указания спецификатора – метод доступен в пределах пакета.
Определение поля:
{public|private|protected} тип имя [= значение];
Инициализационный блок используется для установки начальных значений:
[static] { операторы присваивания... }
Статический инициализационный блок может инициализировать только статические переменные.
Порядок инициализации объекта:
1. Все поля инициализируются значениями по умолчанию.
2. Срабатывают инициализаторы полей и инициализационные блоки в порядке их следования в коде.
3. Если в первой строке конструктора вызывается другой конструктор, он выполняется.
4. Выполняется конструктор.
5. В классе можно определить метод finalize(), который будет выполняться при сборке мусора.
1.5 Переменные, именованные константы, массивы, перечисления в
Java
Переменные – простых типов и ссылочные. Простые непосредственно содержат значение, ссылочные – ссылку на объект. Ссылочным переменным можно присвоить null.
Простые типы: int, short, long, byte, float, double, char, boolean. Беззнаковых типов нет. Размерность типов не зависит от платформы. Char всегда 2 байта.
Для простых типов есть их объектные аналоги: Integer, Character и т.п.
Константы обозначаются ключевым словом final (например, final double MAX = 5; - требуется явная инициализация при объявлении).
Массив – объект, содержащий ссылки на другие объекты.
MyType[] array = new MyType[5];
array[3] = new MyType();
int size = array.length; // 5
int[] iarr = { 1, 2, 3 };
Изначально всем элементам массива присваиваются значения по умолчанию.
Класс java.util.Arrays содержит статические методы для работы с массивами: сравнение, сортировка, поиск и т.п.
Перечисление – тип объекта, который может принимать ограниченное множество значений. Раньше для этого использовались классы, унаследованные от интерфейса Enumeration (методы hasMoreElements() и nextElement()). В Java 5 появился enum, как в C++.
public enum MyEnum { FIRST, SECOND, THIRD };
Enum – это полноценный класс, его значения – экземпляры класса. Каждому значению можно сопоставить параметры конструктора:
public enum MyEnum {
FIRST(“first”), SECOND(“second”), THIRD(“third”);
MyEnum(String arg) {
text = arg;
}
String getText() { return text; }
private String text;
}
Можно перебрать все значения enum в цикле for:
for (MyEnum m : MyEnum.values())
doSomething(m);
Наследование:
class DerivedClass extends BaseClass {…}
Можно наследовать только один класс (нет множественного наследования), зато можно реализовывать несколько интерфейсов. Для обращения к полям и методам суперкласса в методе дочернего класс используется super. Также можно вызывать конструктор базового класса в конструкторе дочернего:
public DerivedClass() {
super(param1, param2);
…
}
Для переопределения метода достаточно еще раз описать его в дочернем классе, все методы подвержены полиморфизму (нет необходимости объявлять их виртуальными). Чтобы метод нельзя было переопределить, используется модификатор final. Также можно объявить final класс, тогда от него нельзя будет унаследовать другие классы.
Если объявить класс abstract, то нельзя создать его экземпляр, только унаследовать. Метод тоже может быть abstract – в этом случае его тело определяется не в этом классе, а в дочерних.
Дочерним классам доступны поля и методы уровня public и protected.
a instanceof B – возвращает true, если a – экземпляр класса B, в противном случае false.
Если наследуемый класс не указывается явно, то неявным базовым классом становится Object. Таким образом, каждый класс унаследован (возможно, косвенно) от Object. Переменную типа Object можно использовать как ссылку на любой объект. Простые типы не наследуются от Object. Object содержит ряд важных методов:
equals() – проверяет эквивалентность двух объектов. Изначально проверяет только равенство ссылок, поэтому должен переопределяться в дочерних классах.
getClass() – возвращает объект типа Class, описывающий тип данного объекта.
hashCode() – генерирует целое число на основе состояния конкретного объекта. Метод используется при включении объекта в хэш-таблицу. При переопределении equals() надо переопределять и hashCode() – у эквивалентных объектов хэш-коды должны совпадать.
toString() – возвращает строку, отражающую состояние объекта.
clone() – создает копию объекта. Без переопределения недоступен.
Class:
Обьект метаданных о каком либо классе. Позволяет узнать методы, поля, создать экземпляр другого класса. Обьект Class создается либо как жертва.getClass() или как Class.forName(“полное квалификационное имя”). Данный класс – основа отражения (reflection).
1.7 Интерфейсы и обратные вызовы в
Java
Интерфейс – спецификация требований к реализуемым классом методам:
public interface MyInterface {
int myMethod();
}
Все методы, объявленные в интерфейсе, считаются обьявлеными как public.
Класс может реализовать один или несколько интерфейсов:
class MyClass implements MyInterface { … }
class MyClass2 implements MyInterface, MyInterface2 { … }
Интерфейс – не класс, нельзя создать его экземпляр. Но интерфейсная переменная может ссылаться на объект класса, который реализует этот интерфейс. С помощью instanceof можно проверить, реализует ли объект заданный интерфейс.
В Java интерфейсы часто применяются вместо указателей на функции для организации механизма обратного вызова. Объекту, который будет выполнять обратный вызов, передается интерфейсная переменная, метод которой будет вызван. После этого первый объект сохраняет эту переменную и при необходимости вызывает один из ее методов. Например, таймер javax.swing.Timer требует интерфейс java.awt.event.ActionListener для периодического выполнения обратного вызова.
public class MoneyCounter implements ActionListener {
public void actionPerformed( ActionEvent e ) {
money += money * percent;
System.out.println( "Денег сейчас: " + money );
}
}
1.8
Вложенные классы и интерфейсы
Вложенный (inner) класс или интерфейс – класс или интерфейс, определенный внутри другого класса. Объект вложенного класса имеет доступ ко всем полям и методам содержащего его класса (включая закрытые). Его можно скрыть от других классов пакета. Можно создавать анонимные вложенные классы.
class MyClass {
...
private class MyInnerClass { … }
}
Обращение из вложенного класса к методам и полям внешнего: можно просто someMethod(), а можно так: MyClass.this.SomeMethod().
Создание экземпляра вложенного класса:
MyInnerClass obj = new MyInnerClass();
MyInnerClass obj = this.new MyInnerClass();
А если вне класса:
MyClass myobj = new MyClass();
MyClass.MyInnerClass obj = myobj.new MyInnerClass();
Вложенный класс можно определить даже внутри метода (локальный вложенный класс). Они объявляются без спецификаторов видимости.
Анонимные внутренние классы:
Чаще всего используется в обработчиках GUI:
MyInterface obj = new MyInterface() { … };
myButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
doSmth( );
}
} );
Вложенный класс можно объявить static, в этом случае он не будет иметь доступ к нестатическим полям и методам внешнего класса. Это полезно, если экземпляр вложенного класса создается в статическом метода внешнего класса.
Вложенные классы, определенные в интерфейсах, считаются по умолчанию статическими и публичными.
Цикл for each позволяет последовательно перебрать все элементы набора данных.
for (ElementType element : collection) { … }
Объект collection должен поддерживать интерфейс Iterable или быть массивом:
public interface Iterable<E> {
Iterator<E> iterator();
}
Метод с переменным числом параметров:
int sum(int… args);
void format(String fmt, Object… objs);
Многоточие здесь эквивалентно [], то есть args и objs – массивы аргументов указанного типа.
Настраиваемые типы (generics) – способ параметризации класса другим классом. Обычно применяется в коллекциях объектов.
Использование:
LinkedList<Integer> li = new LinkedList<Integer>();
li.add(new Integer(0));
Объявление:
class LinkedList<T> {
void add(T element) { … }
}
Ограничение:
class MyClass<T extends Exception> { … }
Здесь T – подтип класса Exception.
Можно использовать несколько параметров:
class MyClass<T, E, M> {…}
Можно параметризировать метод:
<T> void method(T[] a, Colletion<T> c) { … }
Параметр ? обозначает любой тип:
ArrayList<?> a = new ArrayList<Number>();
Можно также указать ограничения:
ArrayList<? extends Shape> a = new ArrayList<Triangle>(); /* Triangle – подкласс Shape */
ArrayList<? super Triangle> a = new ArrayList<Shape>(); /* Shape – базовый для Triangle */
Ограничения generics: нельзя использовать простые типы в качестве параметров, нельзя определять параметризированные массивы, нельзя использовать generic-типы в исключениях, нельзя использовать instanceof, нельзя задавать значения по умолчанию для параметров типов, нельзя использовать тип-параметр для создания объекта, нельзя клонировать объект, имеющий тип параметра. Механизм generics реализуется компилятором, на уровне виртуальной машины про это ничего не известно. При параметризации не создаются новые классы (ключевое отличие от templates в C++).
Класс, код которого будет выполняться в другом потоке, должен реализовывать интерфейс Runnable:
public interface Runnable {
void run();
}
Затем действуем так:
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
Можно также унаследовать свой класс от Thread (он реализует Runnable), так еще проще.
Поток завершает работу, когда метод run() возвращает управление. Можно также запросить прерывание потока, вызвав t.interrupt(). После этого поток может проверить статус прерывания:
if( Thread.currentThread( ).isInterrupted( ) ) { … }
Если interrupt() вызван для заблокированного потока, он завершается и выбрасывает исключение InterruptedException.
Поток блокируется, если для него вызван sleep(), если он выполняет блокирующий ввод-вывод, если он пытается заблокировать заблокированный объект, если он ожидает выполнения условия, если для него вызван метод suspend() (устаревший).
Синхронизация в многопоточном приложении требуется в ситуации гонки (race condition). В этом случае требуется ограничить выполнение фрагмента кода одним потоком.
Раньше использовалось ключевое слово synchronized, которым помечается метод класса. Этот метод будет выполняться только одним потоком одновременно. Достигается за счет неявного создания объекта блокировки.
Более гибкий способ – использование объектов блокировок: java.util.concurrent.locks.ReentrantLock.
myLock.lock(); // объект ReentrantLock
try { … }
finally { myLock.unlock(); }
Объект ReentrantLock может блокироваться одним потоком несколько раз, но потом должен быть столько же раз разблокирован.
С объектом блокировки можно связать объект условия (типа Condition):
myCondition = myLock.newCondition();
Для условия определены методы:
myCondition.await() // уступить объект блокировки.
myCondition.signalAll() /* все ожидающие потоки возобновят выполнение */
Обычно делают так:
while (!(можно продолжать))
myCondition.await();
Каждый объект может быть объектом блокировки. Для этого в классе Object есть методы notifyAll(), notify(), wait().
Синхронизированные блоки:
synchronized(obj) { … }
Здесь obj – любой объект, который выступает в качестве объекта блокировки.
Можно сделать проще – объявить переменную volatile, тогда синхронизация доступа к этой переменной будет происходить автоматически.
Блокирующие очереди – используются для ситуации читателей и писателей. Классы: LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue, DelayQueue. Такие очереди обеспечивают синхронизированный доступ к своим элементам и имеют методы: add (добавить элемент), remove (удалить из головы), element (возвратить из головы без извлечения), offer (добавляет элемент с проверкой переполнения), poll (удаляет из головы с проверкой пустоты), peek (возвращает из головы без извлечения с проверкой пустоты), put (блокирующее добавление элемента), take (блокирующее удаление из головы).
В Java ввод-вывод основывается на потоках (streams) и файлах (files).
Поток ввода – объект, из которого можно считывать последовательность байтов или символов, определяется абстрактным классом InputStream (определяет метод int read(), читающий один байт). Поток вывода – объект, в который можно записывать последовательность байтов или символов, определяется абстрактным классом OutputString (определяет метод void write(int b), записывающий один байт). Методы read и write могут блокировать поток. Есть и другие методы: int read(byte[] b), void write(byte[] b) и т.д.
Классы Reader и Writer аналогичны InputStream и OutputStream, но используются для Unicode-текстов.
Потоки ввода-вывода можно объединять в цепочки:
FileInputStream fin = new FileInputStream(“file.dat”);
DataInputStream din – new DataInputStream(fin);
double s = din.readDouble();
Консольный ввод-вывод осуществляется с помощью объектов System.in (типа InputStream) и System.out (типа PrintStream).
Класс Formatter – основа логики форматирования. Примеры опции форматирования - задание точности и ширины дробного числа (%7.4f), представлеие времени (%tT). Можно применять различные форматы для одного аргумента – в этом случае указываеться порядковый номер аргумента (%3$s для третьего). Общий вид параметра:
%[argument_index$][flags][width][.precision]conversion
Конструктору класса Formatter можно передать локаль желаемого языка. Само форматирование осуществляется методом format(). Подобно printf в него передается строка с шаблоном форматирования и аргументы. Можно использовать локаль, отличную от той, что использовалась в конструкторе:
public Formatter format(String format, Object... args)
public Formatter format(Locale l, String format, Object... args)
formatter.format("PI = %12.10f", Math.PI);
Классы PrintStream, PrintWriter позволяют перенаправить форматированный текст в поток. В стандартных потоках (System.out, System.err) есть методы, позволяющие сразу передавать в них форматированный текст. Кроме метода format() в классах, работающих с потоками, появляется printf(). Это синонимиы – ведут себя одинаково.
public PrintStream format(String format, Object... args)
public PrintStream format(Locale l, String format, Object... args)
System.out.format("Сегодня %1$tB %1$te, %1$tY.", Calendar.getInstance());
В классе String имеется метод format(). Работает так же, но возвращает String.
Можно использовать собственные объекты с Formatter – для этого применяется интерфейс Formattable. Реализовав метод formatTo() в своем классе, можно использовать класс в качестве аргумента при форматировании строк:
void formatTo(Formatter formatter, int flags, Integer width, Integer precision);
Класс Scanner – простой сканер, который может считывать простые типы и строки. Есть частичная поддержка регулярных выражений. Scanner разбивает ввод, используя образец разделителя (пробел по умолчанию). Из полученных лексем значения простых типов достаются nextХХХ() методами: nextBoolean(), nextFloat(),nextInt() и т.д. и т.п.
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
Методы hasNextXXX() (hasNextInt(), hasNextDouble(), …) проверяют – является ли очередная лексема значением указанного типа.
Сначала в Java появилась библиотека AWT (abstract window toolkit) (java.awt), которая использовала платформенно-зависимые средства для отображения элементов GUI. Позже появилась IFC (internet foundation classes), которая все элементы интерфейса рисовала в окне. Ее преемницей стала библиотека Swing (javax.swing), которая используется и сейчас. Swing не может работать самостоятельно, без опоры на AWT. Swing работает медленнее, чем AWT, но предоставляет более богатый набор средств, не зависит от платформы (меньше ошибок) и на всех платформах выглядит одинаково.
Окно верхнего уровня (не содержащееся внутри других окон) называется фреймом: классы Frame (AWT) и JFrame (Swing).
Отображать данные можно непосредственно на фрейме, но обычно он используется как контейнер для других GUI-компонентов. Фрейм состоит из нескольких слоев-областей (корневой области, область слоя, прозрачная область и область отображения). Компоненты размещаются на области отображения. Например, чтобы разместить компонент:
Container contentPane = frame.getContentPane();
Component c = …;
contentPane.add(c);
Для рисования на компоненте необходимо переопределить его метод void paintComponent(Graphics g). Graphics – набор настроек контекста для рисования. Метод paintComponent вызывается автоматически, когда требуется перерисовка компонента, но можно вызвать его принудительно с помощью метода repaint().
При обработке событий в библиотеке AWT события передаются от источников (например, кнопок) к обработчикам. Объект события – это объект подкласса java.util.EventObject, который несет в себе информацию о событии. Обработчик – это любой объект класса, реализующего специальный интерфейс.
Пример:
class MyListener implements ActionListener {
public void actionPerformed(ActionEvent event) {…}
}
…
ActionListener listener = new MyListener();
JButton button = new JButton(“OK”);
button.addActionListener(listener);
В качестве обработчиков часто используются вложенные классы.
Обмен данными между клиентом и сервером осуществляется посредством механизма сокетов. Для поключения к удаленному хосту используется класс Socket, конструктор которого принимает имя хоста и порт подключения. После подключения вызываются методы getInputStream() и getOutputStream() для получения входного и выходного потока сокета. Закрытие сокета осуществляет метод close().
Для создания сервера используется класс ServerSocket:
ServerSocket ss = new ServerSocket(1234); /* сокет для прослушивания порта */
Socket incoming = s.accept(); /* сокет для обмена данными с клиентом */
…
s.close();
Обычно сервер делают многопоточным с одним главным потоком, который принимает входящие соединения и распределяет их по потокам (например, с помощью блокирующих очередей).
Классы URL и URLConnection инкапсулируют подробности извлечения информации с удаленного узла.
URL url = new URL(“somehost”);
URLConnection con = url.openConnection();
// настроить подключение …
con.connect(); // запрос заголовка
// обработка полей заголовка …
InputStream is = con.getInputStream();
Для представления интернет-адресов используется класс java.net.InetAddress.
Апплеты – это программы на Java, загружаемые с веб-сервера и выполняемые в браузере. Апплет представляет собой GUI-программу, написанную с помощью AWT и/или Swing с той разницей, что в данном случае программа запускается не из функции main, а путем создания объекта класса, унаследованного от класса Applet (JApplet). Applet является потомком класса Panel.
После компиляции программы создается HTML-файл, содержащий фрагмент:
<applet code=”MyFile.class” … />
В классе, унаследованном от Applet, есть методы, связанные с жизненным циклом апплета:
init() – выполняется при инициализации апплета, аналог функции main(). Должен быть перегружен.
start() – выполняется при запуске апплета.
stop() – выполняется, когда пользователь покидает страницу с апплетом.
destroy() – выполняется при завершении работы браузера.
Хотя обычно апплет не требует создания фреймов и выполняется на панели, тем не менее, можно создать фрейм. Он будет отображен в отдельном окне вне браузера, но при этом не будет самостоятельным приложением.
Если в классе апплета, унаследованном от Applet, определить функцию main, можно добиться работы приложения как в виде апплета, так и в виде обособленного приложения.
Апплеты работают в обособленной «песочнице» (sandbox). При выполнении апплетов действуют строгие правила безопасности: нельзя запускать исполняемые файлы на компьютере пользователя, нельзя взаимодействовать ни с какими компьютерами, кроме сервера, нельзя обращаться к локальной файловой системе, нельзя получать информацию о локальном компьютере (за исключением минимальной). Нарушение этих правил ведет к генерации исключения SecurityException. Некоторые правила можно обойти, если подписать апплет электронной подписью.
RMI (remote method invocation) – технология удаленного вызова методов объектов, написанных на Java. Клиент – тот, кто вызывает метод. Сервер – тот, чей метод вызывается. На клиентской стороне представителем серверного объекта является заглушка (stub), метод которой фактически вызывает клиент. При вызове метода заглушка осуществляет сериализацию объектов, их кодирование (маршалинг), упаковывает их в блок вместе с информацией о вызываемом методе и передает серверу. На сервере объект-получатель (скелетон) выполняет обратные действия, осуществляет выполнение метода, и таким же образом передает результаты обратно клиенту.
Для удаленного вызова клиент использует интерфейсную переменную (которая на самом деле ссылается на заглушку).
При передаче объекта между виртуальными машинами обе машины должны иметь доступ к файлу класса.
Совместно используемый интерфейс должен расширять интерфейс java.rmi.Remote, а все методы интерфейса должны сообщать о том, что при их выполнении может возникнуть исключение RemoteException. Соответственно, при любом вызове удаленного метода надо перехватывать RemoteException. Серверный объект должен наследовать java.rmi.server.RemoteServer (абстрактный класс), но можно и конкретную реализацию – UnicastRemoteObject.
В JDK классы заглушки и каркасы (скелетоны) генерируются автоматически, раньше нужно было использовать утилиту rmic.
Для получения ссылки на заглушку на клиентской стороне используется служба регистрации самозагрузки (bootstrap registry service). Сервер регистрирует удаленный объект под определенным именем, а клиент его получает. Например:
// сервер
IfaceImpl pl = new IfaceImpl();
Context namingContext = new InitialContext();
namingContext.bind(“rmi:myobject”m pl);
// клиент
Iface p = (Iface)namingContext.lookup(“rmi://myserver.com/toaster”);
Служба регистрации автозагрузки должна быть запущена в операционной системе отдельно
Модель JDBC основана на ODBC: программа взаимодействует с диспетчером драйверов JDBC, который выбирает подходящий в данном случае драйвер (например, драйвер Oracle) или мост (например, мост JDBC/ODBC). Целью разработки JDBC была разработка модели, работающей одинаково независимо от платформы и от поставщика данных. Предполагалось, что вся работа с БД будет осуществляться с помощью SQL и Java. Классы JDBC располагаются в пакетах java.sql и javax.sql.
Подключение к БД:
Connection con = DriverManager.getConnection(url, username, password);
Выполнение запроса:
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(“SELECT …”);
ResultSet может быть сделан обновляемым (то есть вносимые изменения отражаются в БД), если указать особые параметры при создании Statement.
По умолчанию каждая SQL-команда выполняется в своей транзакции, но можно это отключить:
con.setAutoCommit(false);
con.commit();
con.rollback();
CORBA (common object request broker architecture) – технология удаленной работы с объектами. CORBA, в отличие от RMI, обеспечивает взаимодействие между объектами, написанными на разных языках. Для этого используется брокер объектных запросов (ORB), который работает и на клиенте, и на сервере.
Сначала описывается интерфейс на языке IDL. Потом это описание компилируется в классы-заглушки и вспомогательные классы на целевых языках. Затем реализуются и компилируются объекты-серверы, после чего они регистрируются в программе-сервере (наиболее удобны способ регистрации – использование службы имен CORBA, аналогичной реестру RMI). После этого уже можно создавать программу-клиент и запускать клиент и сервер.
2.
Общие положения теории РСОИ
РС содержит компоненты, которые распределены по разным компьютерам.
РС – набор независимых компьютеров, представляющихся их пользователям единой системой. Пользователи и приложения единообразно работают в РС, независимо от того, где и когда происходит их взаимодействие.
Хост – компьютер, на котором размещены компоненты вычислительной системы: аппаратура и сетевая ОС.
Взаимодействие РС
А – головная боль для программистов.
РС содержит несколько хостов и более одного компонента. Компоненты должны взаимодействовать друг с другом.
Взаимодействие компонентов:
Предоставляет доступ к своим службам
Компонент может запрашивать обслуживание у других компонентов
Для взаимодействия используется тот или иной вариант промежуточного уровня, который решает проблему неоднородности и распределения. Промежуточный слой располагается между компонентами и сетевой ОС
Промежуточный слой.
Хост – компьютер, на котором выполняются компоненты, составляющие часть распределенной системы.
Распределенная система – группа автономных хостов, соединенных при помощи компьютерных сетей.
На каждом хосте:
выполняются компоненты
функционирует промежуточный слой. Компоненты, которые координируют свои действия, таким образом, что пользователь воспринимает систему как единое интегрированное вычислительное средство.
Распределенная система вычислений от Google.
РС Nutch построен на основе Hadoop — это фреймворк, реализующий идею MapReduce. Термины map и reduce пришли из функционального программирования, где они означают следующее: reduce это функция типа α -> β, map — функция типа (α -> β) -> [α] -> [β]. То есть map применяет переданную ей первым аргументом функцию reduce к списку элементов типа α и на выходе получается список элементов типа β. Например, если мы определим функцию square x = x ∗ x, вызов map square[1,2,3] вернет [1,4,9]. Если reduce функция без побочных эффектов (то есть она не изменяет ничего за пределами своей области видимости), то применять ее можно одновременно к нескольким элементам входного списка. Гугловый фреймворк MapReduce позволяет прозрачно для программы разносить эти вычисления по многим машинам. Hadoop представляет собой open-source реализацию этой же идеи на Java.
Распределенная система синхронизация кода.
Отличие таких систем - отсутствие центрального репозитория, к которому обращаются клиентские программы; репозиториев может быть много и между ними существует возможность синхронизации. Такой механизм работы даёт больше свободы разработчику, вместо получения рабочей копии и её отправки обратно в центральный репозиторий разработчик может получить репозиторий в своё полное владение - вносить изменения на своё усмотрение и только отдельные изменения синхронизировать с основным репозиторием.
Распределенные системы обнаружения спама.
Сбор информации в различных репозитариях (параметры приходящей почты, сигнатуры), анализ информации (анализ технической информации сообщения, анализ тела сообщения (контентный анализ) методами лингвистики, либо статистики), на основании анализа публикация в репозитарии признаков спама и синхронизация этой информации с другими распределенными точками сбора информации.
Распределенная система управления сетями.
Сбор и анализ информации о сети. Управляющая станция со специальным ПО, центральная БД. Агенты на различных устройствах и службах – собирают информацию, сохраняют себе на лок. БД, отсылают информацию в определенные моменты управляющей станции.
Распределенная файловая система (Distributed File System – DFS) для OL Windows 2000 Server представляет собой одну из сетевых служб, которая упрощает поиск и администрирование данных в корпоративных сетях.
Когда вы пользуетесь распределенной файловой системой, ее реальная структура скрыта от вас и в действительности может иметь динамический характер. Так, можно создать иерархическую файловую структуру, корневой каталог которой будет находиться на NT-сервере, а все ее узлы будут распределены на различных носителях в сети. DFS представляет собой инструмент, позволяющий пользователям корпоративной информационной системы получить единообразное представление данных и файлов, распределенных по сети так, как будто все они находятся на его машине.
Требования бывают: функциональные и нефункциональные.
Функциональные – поддаются локализации при реализации
Нефункциональные – относятся к качеству системы – носят глобальный характер и оказывают существенное влияние на выбор общей архитектуры системы на этапе проектирования:
Масштабируемость
Способность системы адаптироваться к будущему росту нагрузки. Проблемы: узкие места по обслуживанию (один сервер для множества клиентов), по данным (один файл с общей информацией), по алгоритмам (централизованный алгоритм и перегрузка коммуникационной сети). Свойства децентрализованных алгоритмов:
· Никто не обладает полной информацией о системе
· Решения принимаются на основе лекальной информации
· Сбой в одном месте не вызывает нарушения работы алгоритма
· существования единого времени не требуется
· Прозрачность (в следующем билете)
Открытость
Систему можно легко расширять и модифицировать (интеграция новых компонентов, отвечающих новым функциональным требованиям => компоненты должны иметь четко определенные интерфейсы) Правильный интерфейс обеспечивает возможность правильной совместной работы одного процесса с другим, представляющим интерфейс. Самодостаточность и нейтральность. Переносимость характеризует, насколько приложение, сделанное для одной системы, может работать в составе другой. Способность к взаимодействию характеризует, насколько две разные реализации системы в состоянии работать совместно.
Гибкость – легкость конфигурирования системы, состоящей из различных компонентов, и легкость подключения новых компонентов.
Неоднородность
В распределенных системах, компоненты должны объявлять о предлагаемых услугах. Заявки могут быть синхронными/асинхронными. Клиент и сервер могут быть неоднородными. Причины неоднородности:
· Компоненты могут приобретаться в готовом виде
· При создании нового компонента, на него могут накладываться требования взаимодействия с существующими компонентами
· Компоненты создаются разными разработчиками
· Используются различные технологии
Разделение ресурсов
Ресурс – аппаратура, ПО, данные. Требуется определить, кому будет разрешен доступ к ресурсу => требуется вести учет пользователей. Менеджер ресурсов – компонент, предоставляющий доступ к разделяемым ресурсам.
Модели взаимодействия:
· Клиент-серверная (сервер предоставляет доступ к ресурсам)
· Концепция распределенных объектов, предоставляющих доступ к имеющимся у них ресурсам при обращении других компонентов
Отказоустойчивость
Система может продолжать работу даже в случае неисправности => избыточность => применение репликации (при отказе компонента, начинает работать его копия и обслуживание не прекращается)
Имеет несколько различных аспектов:
1. Прозрачность масштабируемости (обеспечивается 4, 5) - программист не должен знать, как достигается масштабируемость распределенной системы.
2. Прозрачность производительности (обеспечивается 4, 5) – пользователь и программист не знают, как поддерживается хорошая производительность.
3. Прозрачность отказа (обеспечивается 5, 6) - пользователям и программистам не требуется знать, как ВС справляется с отказами.
4. Прозрачность миграции (обеспечивается 7, 8) – перемещение компонентов незаметно для пользователей и без специальных действий со стороны разработчиков этих компонентов
5. Прозрачность репликации (обеспечивается 7, 8) – пользователям и разработчика не требуется знать, кто предоставляет услугу – реплика или основной компонент. Разработчики компоненты не должны учитывать возможность его репликации
6. Реплика – копия, которая остается синхронизированной с оригиналом
7. Прозрачность одновременного выполнения. Означает, что пользователи программы не знают, что компоненты запрашивают услуги одновременно. Несколько компонентов могут запрашивать обслуживание одновременно с сохранением его услов-ти. Пользователи и разработчики не видят, как организуется одновременно обслуживание.
8. Прозрачность доступа – одинаковость интерфейсов для локальной и удаленной связи (интерфейс заявки на обслуживание должен быть одним и тем же для связи между компонентами одного хоста и разных хостов)
9. Прозрачность местонахождения – способ вызова операции не зависит от местонахождения компонента (запрашивающему обслуживание объекту не требуется знать о физическом расположении компонента). Клиент не должен знать о местонахождении компонента или его реплики.
Есть машины: A и B. A вызывает процедуру, которая выполняется на B.
count = read(fd, buf, bytes);
Стек при вызове процедуры:
bytes
|
buf
|
fd
|
адрес возварата
|
локальные переменные
|
|
Передавать параметры по значению просто, а вот по ссылке – проблема. Вызов через клонирование восстановлением. Удаленный вызов выглядит как локальный, то есть RPC обеспечивает прозрачность для клиента. Сервер тоже не подозревает, что он выполняет удаленный вызов.
На сервере есть аналогичная заглушка; сервер выполняет запрос, возвращает результат. Проблема: передача по адресу. Решение: можно предавать копию буфера.
Последовательность передачи управления при RPC:
При удаленном вызове процедур процесс на 1 узле вызывает процедуру процесса на 2 узле. Сложность заключается в том, что процессы работают в разных адресных пространствах (АП). При передаче параметров по значению это неважно, т.к. значение не зависит от АП, а при передаче по ссылке возникает проблема. Здесь можно использовать другой вариант передачи параметров (отсутствует в С) – копирование-восстановление.
Передача параметров по значению.
· Формируется пакет, содержащий имя процедуры и ее параметры;
· Сообщение принимается заглушкой-сервером;
· Заглушка на сервере формирует вызов процедуры (как локальной).
Клиентский процесс приостанавливает свою работу и ждет возвращение результата. При получении результата он продолжает работу.
Передача параметров по ссылке (копирование-восстановление).
Пример: чтение удаленного файла в массив.
Передать копию ссылки не представляется возможным, так как ссылка – это указатель в АП клиента, бессмысленно передавать ее копию. Вариант решения: можно поступить так: взять массив, на который показывает указатель, и передать копию этого массива. Все это помещается в сообщение, передаваемое на сервер. На сервере выделяется место под массив, ссылка на массив в АП сервера. Заглушка передает параметры серверному процессу, и он по всем правилам обращается к ОС и помещает результат в массив в своем АП. Заглушка упаковывает массив в сообщение и передает его на клиентскую заглушку с помощью ОС. Клиентская заглушка распаковывает это сообщение и помещает значения в тот массив, который находится в АП клиента. Клиентский процесс получает результат, как будто он обратился локально. Эта удаленность прозрачна для обоих.
Заглушки должны использовать один протокол, по которому они будут представлять встроенные типы. Если заглушки работают по одному и тому же протоколу, они будут различаться только интерфейсами на машинах.
Чтобы облегчить работу по созданию заглушек, используется язык определения интерфейсов. IDL – Interface Definition Language.
Распределенный объект (РО) – такой объект, реализация которого располагается на сервере, а взаимодействие клиентов с ним происходит через определенный интерфейс.
В адресное пространство клиента загружается реализация этого интерфейса – заместитель (proxy). Клиент непосредственно взаимодействует именно с заместителем.
Процесс формирования интерфейса и заместителя – привязка клиента к РО. Системы с РО предоставляют ссылки на объекты, уникальные в пределах системы. Такие ссылки могут передаваться между процессами, запущенными на разных машинах. Виды привязки:
Неявная (автоматическая) – клиент прозрачно связывается с объектом в момент разрешения ссылки (это когда по имени объекта получаем ссылку на него).
Явная – клиент должен вызвать специальную функцию для привязки к объекту.
Адаптер объектов – механизм группирования объектов в соответствии с политикой их активизации. Контролирует один или несколько объектов.
Скелетон – образ клиента на сервере (заглушка сервера).
Клиент через заместителя вызывает определенный метод объекта и задает параметры этого метода. Заместитель формирует и упаковывает сообщение (маршалинг) и отправляет его на сервер. В этом сообщении содержится ссылка на объект, метод и значения параметров. Сервер получает сообщение, и передает его соответствующему скелетону. Скелетон распаковывает сообщение (демаршалинг) и непосредственно вызывает определенный метод объекта с заданными клиентом параметрами. Если предполагается, что метод что-нибудь возвращает, то скелетон упаковывает результат и отправляет его заместителю.
Сохранные и нерезидентные объекты
Сохранный – объект продолжает существовать, даже не находясь постоянно в адресном пространстве серверного процесса. То есть, объект всегда можно воссоздать из памяти независимо от наличия процесса.
Нерезидентный – существует, пока им управляет сервер. Когда сервер завершает работу, это объект прекращает существование.
Способы определения местонахождения РО
Именование – управление пространствами имен, представляющими собой наборы связей между именами объектов и ссылками на них.
Трейдинг – определение местонахождения объектов исходя из предоставляемых ими функций и качества обслуживания.
Статическое удаленное обращение к методам (RMI).
При статическом обращении интерфейс удаленного объекта описывается с помощью IDL, т.е. интерфейс известен на этапе компиляции.
Пример: Описание интерфейса футболиста.
interface Player: Object {
typedef struct Date {
short day; short month; short year;
}
attribute string name;
readonly attribute Date Dob;
};
interface PlayerStore: Object {
exception IDNotFound();
short save (in Player);
Player load(in short id) raises (IDNotFound);
void print(in Player p);
}
При использовании статического обращения интерфейсы должны быть уже известны и при изменении интерфейса нужна перекомпиляция.
Динамическое удаленное обращение к методам.
При динамическом обращении интерфейс удаленного объекта заранее не известен. Параметры обращения к методу собираются в процессе выполнения. Заранее неизвестно, к какому методу будет обращение.
invoke (object, method, input inparam, out outparam);
Передача параметров.
Используются ссылки на объекты как параметры, которые передаются при обращении к удаленному объекту. Объект, ссылка на который передается:
· находится в адресном пространстве клиента;
· находится удаленно.
Они реализуются по-разному. Ссылка передается только для удаленных объектов. Если объект локальный, то передается копия самого объекта.
При удаленном вызове клиентом на машине А сервера на машине С осуществляется копирование объекта O1 и передача ссылки на объект O2.
Серверы объектов (СО) – серверы, ориентированные на поддержку распределенных объектов. СО (в отличие от традиционных серверов) НЕ предоставляет конкретные службы, т.к. конкретные службы реализуются объектами, расположенными на сервере. СО предоставляет только средства обращения к объектам, основанные на запросах от удаленных клиентов.
Активизация объекта – перемещение объекта в адресное пространство сервера (например, десериализация). Правила обращения к объектам – политика активизации. Требуется механизм группировки объектов в соответствии с политикой активизации каждого из них. Этим механизмом является адаптер объектов. Чаще всего он скрыт в наборе средств построения СО. Каждый адаптер объектов контролирует 1 или несколько объектов. При получении запроса к одному из контролируемых объектов адаптер проверяет его состояние и при необходимости активизирует в соответствии с политикой активизации. После этого запрос передается к заглушке (скелетону) объекта, которая производит демаршаллинг (распаковку параметров) и осуществляет вызов метода. Адаптер ничего не знает об интерфейсах объектов.
Перенос кода необходим для:
· перераспределения нагрузки между узлами для повышения производительности;
· снижения трафика клиент-серверного взаимодействия.
У задачи выделяют следующие сегменты:
· сегмент кода – команды;
· сегмент исполнения – контекст задачи;
· сегмент ресурсов – ресурсы.
Модели переноса кода:
Минимальные требования для переноса кода предъявляет модель слабой мобильности – перенос только сегмента кода. Поэтому программа всегда выполняется из своего исходного состояния. Пример: Java Applet.
В модели сильной мобильности переносится сегмент кода и сегмент исполнения. Процесс приостанавливается, переносится и запускается на другом узле. Пример: мультиагентная платформа.
Типы связи процесса с ресурсом:
Процесс передает в точности тот ресурс, на который ссылаются аргументы (наиболее сильная связь);
Более слабая связь - процессу нужно только значение;
Наиболее слабая форма связи – процесс указывает лишь на использование ресурса определенного типа.
Программный агент.
Автономный процесс, способный реагировать на среду исполнения и вызывать в ней изменения, возможно в кооперации с другими агентами (кооперативные агенты) и пользователем. Агент может функционировать автономно, в том числе проявлять инициативу. В мультиагентной системе фигурируют кооперативные агенты, решающие общую задачу.
Серверы – процессы, реализующие службы и предоставляющие к ним доступ.
Клиенты – процессы, использующие эти службы.
Рассмотрим на примере доступа к БД:
При трехуровневой организации системы имеем следующие логические уровни:
· Пользовательский интерфейс (ПИ на рисунке).
· Обработки (О).
· Данных (непосредственная работа с БД).
Варианты физического разделения уровней между узлами:
На этом рисунке клиент «утолщается» слева направо.
Взаимодействие клиента с сервером происходит следующим образом:
2.12 Общие сведение об именовании объектов и службе именования
Именование – способ определения местонахождения распределенных объектов, при котором осуществляется управление пространствами имен, представляющими собой наборы связей между именами объектов и ссылками на них.
Контекст именования – последовательность простых имен, идентифицирующая объект. Например “UEFA”, “England”, “Premier”, “Chelsea”.
Операции:
Связывание – регистрация объекта-сервиса по имени и объектной ссылке. Используется при добавлении нового объекта в систему или при перемещении / копировании существующего объекта.
Разрешение – получение ссылки на объект по его имени. Используется клиентом для получения доступа к методам объекта.
Размещение мобильных сущностей.
Мобильные сущности – это те объекты, которые могут гулять по разным хостам. В этом случае пространство имен удобно разбить на 3 уровня:
· Глобальный
· Административный
· Управленческий
В 1 и 2 помещаются объекты, которые перемещаются относительно редко. Здесь эффективно кэширование путей.
В 3 объекты гуляют часто, и для них используется следующая система:
По имени объекта служба именования определяет его идентификатор, затем служба локализации по ид находит его физический адрес.
У каждого узла свой системный таймер. Возникает проблема синхронизации часов. Пусть у узла р время Ср(t), тогда:
где ρ – максимальная скорость дрейфа времени, t - UTC. Если требуется рассинхронизация не более δ, то через каждые
необходима синхронизация часов.
Алгоритм Кристиана.
Есть узел, принимающий сигналы точного времени – сервер времени. Остальные узлы через каждые
обращаются к серверу и получают значение времени. Здесь есть 2 момента:
Необходимо время на запрос и возврат результата. Решение: если время запрошено в момент Т0, а получено в момент Т1, то установить часы на полученное время + (Т1-Т0)/2.
Если часы отстают, то мы их доставляем. А если часы спешат, то мы их должны ставить назад. А это не допустимо. Тогда мы не одномоментно подстраиваем часы, а растягиваем это во времени, просто замедляя их ход.
Алгоритм Беркли.
Один узел – демон – периодически собирает времена остальных узлов, получает среднее и рассылает обратно.
Логические часы. Алгоритм Лампорта.
Есть ситуации, когда важно не точное время выполнения процесса, а точная последовательность выполнения. Для таких случаев используют достаточно часто алгоритм Лампорта синхронизации логических часов.
Лампорт определил отношение: «Происходит раньше». Оно обозначается: a - b. Это значит, что все процессы согласны с тем, что событие а происходит раньше b.
· Для одного процесса, если а раньше b, то отношение выполняется.
· Если а - посылка сообщения, а b – получение того же сообщения, то отношение тоже выполняется.
· Отношение транзитивно.
В алгоритме каждому событию a ставится метка времени C(a). Эта метка должна быть принята как достоверно правильная всеми процессами. То есть если действительно a - b, то C(a) < C(b). Каждому сообщению прикрепляется временная метка. Получатель сравнивает ее со своим временем. Если его время меньше метки, то оно устанавливается равным метка+1. Даже если 2 сообщения посланы почти одновременно, их метки различаются.
2.13.1 C
оздание объектов
Требуется создать объект в адресном пространстве (АП) сервера (конструктор создал бы в АП клиента). Для этого необходима фабрика. Чтобы найти фабрику, необходим искатель фабрик. Чтобы найти искатель фабрик, используется сервер именования или трейдинг.
2.13.2 М
играция объектов.
Объектная миграция – копирование или перемещение объекта сервера с 1 машины на другую. Чтобы объект позволял миграцию, необходим интерфейс, реализующий операции copy и move с параметром – искателем фабрик. Через фабрику создается объект на новом месте, в него копируется состояние исходного объекта. Далее в случае перемещения исходный объект удаляется. При копировании создается новая ссылка на объект (т.к. исходный объект остается).
При перемещении: Есть объект в каком-то адресном пространстве. При перемещении он оставляет заместителя, а в новом АП формируется скелетон. Такая схема прозрачна для клиента: он не знает, что происходили перемещения. При получении запроса ответ может пойти по прямой, если известно, кто запросил сервис этого удаленного объекта.
Если цепочка оборвалась (разрыв связи, зависание…), добраться до удаленного объекта больше невозможно. Бороться с этим можно с помощью базовой точки.
Машина, на которой создавался объект, называется базовой точкой. Требуется, чтобы эта машина всегда имела информацию о текущем местоположении созданного ею объекта. Тогда если не удается по цепочке указателей добраться до объекта, т.е. какой-то промежуточный процесс завис, то происходит обращение к базовой точке.
Чтобы объект позволял копирование, необходим интерфейс, реализующий операцию copy с параметром – искателем фабрик. Через фабрику создается объект на новом месте, в него копируется состояние исходного объекта. Создается новая ссылка на объект (т.к. исходный объект остается).
3. Технология
J2EE
Платформа J2EE – комплекс взаимодействующих технологий, базирующихся на спецификациях фирмы Sun и представляющих стандарт разработки серверных приложений (уровня предприятия).
Особенности:
· Независимость от платформы.
· Простота разработки приложений на основе компонентной технологии.
· Переносимость и расширяемость.
· Возможность разработки распределенных приложений.
· Возможность интеграции с другими платформами.
· Возможность интеграции с существующими информационными системами.
· Обеспечение надежной защиты информации.
J2EE – набор спецификаций, устанавливающих правила, которых следует придерживаться поставщикам конкретных реализаций J2EE, а также разработчикам приложений.
Поддерживаются разные типы клиентов: HTML – браузеры, апплеты, автономные java-приложения.
Уровень представления – часто реализуется в виде веб-уровня.
Уровень бизнес-логики – в виде уровня EJB (Enterprise Java Beans).
Уровень интеграции – уровень сервера БД – EIS (Enterprise Information Server). Это адаптеры ресурсов J2EE.
Сервер приложений – содержит контейнеры компонентов EJB.
Особенности:
· Доступ к инфраструктуре J2EE.
· Управление жизненным циклом компонентов EJB.
· Доступ к БД с использованием JDBC.
· Контейнер изолирует компонент от клиента. Все запросы перехватываются контейнером.
· У каждого компонента есть объект EJBContext, который является ссылкой на контейнер.
· Контейнер автоматически создает набор соединений с БД.
· Контейнер позволяет объединять несколько компонент внутри одной транзакции.
Аббревиатуры:
JMS – Java Messaging Service
JSP – Java Server Page
JTA – Java Transaction API
JAF – Java Beans Activation Framework
JAXP – Java API for XML Parser
JAAS – Java Authentication and Authorization Service
EJB – серверная java технология, основанная на транзакциях. Позволяет быстро и относительно просто разрабатывать распределенные, транзакционные, безопасные и портируемые Java приложения.
Компонент EJB представляет собой:
Remote – Расширенный интерфейс. Определяет методы компонента.
Remote Home – определяет методы жизненного цикла для создания, удаления, поиска компонент(интерфейс фабрики классов)
Local – этот интерфейс используется другими компонентами находящимися в этом же контейнере.
Вызов происходит следующим образом
Модули EJB – объединенные в группу компоненты EJB, которые могут взаимодействовать.
Типы компонентов EJB:
Session
– связаны с бизнес процессами приложения; имеют доступ к бд, но не предоставляют доступа к ней; жизненный цикл – до перезагрузки сервера. ( вызов сессионных компонентов: сервлетты, страницы JSP, java приложения). Разделяется на 2 типа:
Stateless
– не сохраняет информации о своем состоянии
Statefull
– могут сохранять инф о своем состоянии
(У них сильно различаются жизненные циклы.)
Entity
– моделируют бизнесс данные приложения; предоставляют доступ к БД; часто 1 обращается к 2; t жизни = t жизни бд(при перезагр сервера автоматически восстанавливаются); вызов из 1 и компонентов WEB;
MessageDriven
– прдставляют действия. Их можно вызвать только послав сообщение этому компоненту; С помощью 3 организуют доступ к 1. t жизни как у 1
Так цепочку обращений в J2EE можно представить следующим образом:
Java Beans
JB это не EJB, EJB более обширное понятие.
JB – для создания пользовательского интерфейса, для взаимодействия между страницами.
EJB – для создания серв приложений, только не визуальные компоненты.
|