Вы находитесь на странице: 1из 650

Руководство по Web-сервисам

Copyright © Sun Microsystems®, Все права защищены.

Аннотация

Это руководство представляет собой учебник для начинающих, посвященный разработке


Web-служб и Web-приложений с использованием Java™ Web Services Developer Pack (Java
WSDP). Java WSDP является самодостаточным набором средств, содержащим ключевые
технологии, упрощающие построение Web-служб с использованием Java 2 Platform. Ниже
мы перечислим все, что вам необходимо знать для наиболее эффективного изучения
данного руководства.

Rendered by www.RenderX.com
2

Оглавление
1. Об этом руководстве...................................................................................................... 1
1.1. Для кого предназначено руководство.........................................................................1
1.2. Как читать это руководство......................................................................................... 1
1.3. О примерах................................................................................................................... 2
1.3.1. Предварительные требования........................................................................... 2
1.3.2. Запуск примеров..................................................................................................2
1.3.2.1. Требуемое программное обеспечение..................................................... 2
1.3.2.2. Построение примеров................................................................................ 3
1.3.2.3. Настройка примеров...................................................................................3
1.4. Как распечатать это руководство................................................................................3
1.5. Типографские соглашения.......................................................................................... 3

2. Введение в Web-службы................................................................................................ 3
2.1. Значение XML и платформы Java™........................................................................... 4
2.2. Что такое XML?.............................................................................................................5
2.2.1. Что обеспечивает переносимость XML?........................................................... 6
2.3. Обзор Java API для XML..............................................................................................7
2.4. JAXP.............................................................................................................................. 8
2.4.1. SAX API................................................................................................................ 8
2.4.2. DOM API............................................................................................................. 10
2.4.2.1. Пространства имен XML.......................................................................... 12
2.4.3. XSLT API.............................................................................................................13
2.4.3.1. Преобразование дерева DOM в XML-документ.....................................13
2.4.3.2. Преобразование XML-документа в HTML-документ..............................14
2.5. JAX-RPC...................................................................................................................... 15
2.5.1. Обзор JAX-RPC..................................................................................................15
2.5.1.1. Способность к взаимодействию.............................................................. 16
2.5.1.2. Простота использования..........................................................................16
2.5.1.3. Дополнительные функции....................................................................... 17
2.5.2. Использование JAX-RPC.................................................................................. 17
2.5.3. Создание Web-службы......................................................................................18
2.5.4. Кодирование клиентской программы...............................................................19
2.5.5. Вызов удаленного метода................................................................................ 20
2.6. JAXM............................................................................................................................21
2.6.1. Установка соединения...................................................................................... 22
2.6.1.1. Установка соединения точка-точка......................................................... 22
2.6.1.2. Установка соединения с поставщиком системы обмена
сообщениями......................................................................................................... 23
2.6.2. Создание сообщения........................................................................................ 23
2.6.3. Заполнение сообщения.................................................................................... 24
2.6.3.1. Заполнение SOAP-части сообщения...................................................... 24

Web-

Rendered by www.RenderX.com
3

2.6.3.2. Заполнение части вложений сообщения................................................25


2.6.4. Передача сообщения........................................................................................ 26
2.7. JAXR............................................................................................................................ 26
2.7.1. Использование JAXR........................................................................................ 27
2.7.1.1. Регистрация субъекта бизнеса................................................................27
2.7.1.2. Поиск в реестре........................................................................................ 28
2.8. Пример сценария....................................................................................................... 29
2.8.1. Сценарий............................................................................................................29
2.8.1.1. Поиск новых поставщиков........................................................................29
2.8.1.2. Запрос прайс-листов................................................................................ 30
2.8.1.3. Сравнение цен и заказ кофе....................................................................30
2.8.1.4. Продажа кофе по сети Интернет.............................................................30
2.8.2. Заключение........................................................................................................ 30

3. Освоение XML...............................................................................................................31
3.1. Введение в XML..........................................................................................................31
3.1.1. Что такое XML?..................................................................................................31
3.1.1.1. Теги и атрибуты........................................................................................ 32
3.1.1.2. Пустые теги............................................................................................... 32
3.1.1.3. Комментарии в XML-файлах................................................................... 33
3.1.1.4. Пролог XML............................................................................................... 33
3.1.1.5. Директивы................................................................................................. 34
3.1.2. В чем важность XML?........................................................................................35
3.1.2.1. Обыкновенный текст................................................................................ 35
3.1.2.2. Идентификация данных........................................................................... 35
3.1.2.3. Стиль отображения.................................................................................. 35
3.1.2.4. Встроенная возможность многократного использования..................... 36
3.1.2.5. Связываемость......................................................................................... 36
3.1.2.6. Простота обработки................................................................................. 36
3.1.2.7. Иерархичность.......................................................................................... 36
3.1.3. Как можно использовать XML?.........................................................................36
3.1.3.1. Традиционная обработка данных........................................................... 37
3.1.3.2. Основанное на документах программирование (DDP)..........................37
3.1.3.3. Связывание............................................................................................... 37
3.1.3.4. Архивация................................................................................................. 38
3.1.3.5. Итог............................................................................................................ 38
3.2. XML и связанные спецификации: освоение алфавитной путаницы...................... 38
3.2.1. Основные стандарты.........................................................................................39
3.2.1.1. SAX............................................................................................................ 39
3.2.1.2. DOM........................................................................................................... 40
3.2.1.3. JDOM и dom4j............................................................................................40
3.2.1.4. DTD............................................................................................................ 40
3.2.1.5. Пространство имен...................................................................................41
3.2.1.6. XSL.............................................................................................................41
3.2.1.7. XSLT (+XPATH)......................................................................................... 41
3.2.2. Стандарты схем.................................................................................................42

Web-

Rendered by www.RenderX.com
4

3.2.2.1. XML Schema.............................................................................................. 43


3.2.2.2. RELAX NG................................................................................................. 43
3.2.2.3. TREX.......................................................................................................... 43
3.2.2.4. SOX............................................................................................................ 43
3.2.2.5. Schematron................................................................................................ 44
3.2.3. Стандарты связывания и представления........................................................44
3.2.3.1. XML Linking................................................................................................44
3.2.3.2. XHTML....................................................................................................... 44
3.2.4. Стандарты знаний............................................................................................. 45
3.2.4.1. RDF............................................................................................................ 45
3.2.4.2. RDF Schema.............................................................................................. 45
3.2.4.3. XTM............................................................................................................ 45
3.2.5. Стандарты, основанные на XML...................................................................... 46
3.2.5.1. Extended Document Standards (стандарты расширенных
документов)............................................................................................................46
3.2.5.1.1. SMIL.................................................................................................. 46
3.2.5.1.2. MathML..............................................................................................46
3.2.5.1.3. SVG................................................................................................... 46
3.2.5.1.4. DrawML............................................................................................. 46
3.2.5.2. Стандарты электронной коммерции (eCommerce)................................ 47
3.2.5.2.1. ICE.....................................................................................................47
3.2.5.2.2. ebXML............................................................................................... 47
3.2.5.2.3. cxml................................................................................................... 47
3.2.5.2.4. CBL....................................................................................................47
3.2.5.2.5. UBL....................................................................................................47
3.2.6. Итоги...................................................................................................................48
3.3. Разработка структуры данных XML.......................................................................... 48
3.3.1. Облегчение своей работы................................................................................ 48
3.3.2. Атрибуты и элементы........................................................................................48
3.3.2.1. Вынужденный выбор................................................................................ 48
3.3.2.2. Стилистический выбор............................................................................. 49
3.3.3. Нормализация данных...................................................................................... 50
3.3.4. Нормализация DTD........................................................................................... 51

4. Начало работы с Tomcat.............................................................................................. 52


4.1. Установка.................................................................................................................... 52
4.1.1. Получение кода примера.................................................................................. 52
4.1.1.1. Схема кода примера.................................................................................52
4.1.2. Установка переменной PATH........................................................................... 53
4.1.3. Создание файла свойств компоновки............................................................. 53
4.2. Краткий обзор............................................................................................................. 54
4.3. Создание первого приложения................................................................................. 55
4.3.1. Компонент ConverterBean................................................................................. 55
4.3.1.1. Кодирование компонента ConverterBean................................................55
4.3.2. Web-клиент ........................................................................................................56
4.3.2.1. Кодирование Web-клиента.......................................................................56

Web-

Rendered by www.RenderX.com
5

4.4. Компоновка первого приложения при помощи ant.................................................. 58


4.4.1. Создание файла компоновки и размещения для ant..................................... 59
4.4.2. Компиляция исходных файлов.........................................................................61
4.5. Размещение приложения.......................................................................................... 61
4.5.1. Запуск Tomcat ................................................................................................... 62
4.5.2. Установка приложения при помощи ant.......................................................... 62
4.5.3. Размещение приложения при помощи deploytool...........................................63
4.5.3.1. Создание WAR-файла и идентификация файлов в Web-
приложении ........................................................................................................... 63
4.5.3.2. Выбор типа компонентов......................................................................... 64
4.5.3.3. Установка свойств компонента................................................................64
4.5.3.4. Размещение приложения.........................................................................64
4.5.3.5. Просмотр дескриптора размещения....................................................... 64
4.6. Выполнение первого приложения.............................................................................65
4.6.1. Выполнение Web-клиента ............................................................................... 65
4.6.2. Остановка Tomcat..............................................................................................66
4.7. Использование admintool...........................................................................................66
4.7.1. Понимание ролей, групп и пользователей...................................................... 67
4.7.2. Добавление ролей при помощи admintool.......................................................67
4.7.3. Добавление пользователей при помощи admintool........................................68
4.8. Модификация приложения........................................................................................ 68
4.8.1. Модификация файла классов.......................................................................... 68
4.8.2. Модификация Web-клиента .............................................................................69
4.9. Общие проблемы и их решение................................................................................69
4.9.1. Ошибки при запуске Tomcat............................................................................. 69
4.9.1.1. Ошибка "Out of Environment Space" ("Не хватает пространства
окружения")............................................................................................................ 69
4.9.1.2. Ошибка "Unable to Locate the Server localhost:8080" ("Невозможно
обнаружить сервер localhost:8080")..................................................................... 69
4.9.2. Ошибки компиляции.......................................................................................... 70
4.9.2.1. Server returned HTTP response code: 401 for URL : (Сервер
возвратил код ответа HTTP: 401 для URL :)....................................................... 70
4.9.2.2. Ant Cannot Locate the Build File (ant не может найти файл
компоновки)............................................................................................................70
4.9.2.3. The Compiler Cannot Resolve Symbols (компилятор не может
разрешить символы)............................................................................................. 70
4.9.2.4. Ошибка "Connection refused" ("В соединении отказано")...................... 71
4.9.2.5. При попытке выполнения задания на установку система, по всем
признакам, виснет..................................................................................................71
4.9.3. Ошибки размещения......................................................................................... 71
4.9.3.1. Failure to run client application (Ошибка при выполнении клиентского
приложения)........................................................................................................... 71
4.9.3.2. The localhost Machine Is Not Found (Компьютер localhost не
найден)................................................................................................................... 72

Web-

Rendered by www.RenderX.com
6

4.9.3.3. The Application Has Not Been Deployed (Приложение не


размещено)............................................................................................................ 72
4.9.3.4. Ошибка "Build Failed: Application Already Exist at Path" (Компоновка
неудачна: приложение уже существует)..............................................................72
4.9.3.5. HTTP 500: No Context Error (HTTP 500: Ошибка: нет контекста).......... 72
4.10. Дополнительная информация.................................................................................73

5. Web-приложения...........................................................................................................74
5.1. Жизненный цикл Web-приложения........................................................................... 74
5.2. Архивы Web-приложения...........................................................................................76
5.2.1. Структура каталога WAR.................................................................................. 76
5.2.2. Структура каталога примера............................................................................ 76
5.2.3. Создание WAR...................................................................................................77
5.3. Настройка Web-приложений......................................................................................78
5.3.1. Пролог................................................................................................................ 79
5.3.2. Пути псевдонимов............................................................................................. 79
5.3.3. Параметры контекста и инициализации.......................................................... 80
5.3.4. Перехватчики событий...................................................................................... 81
5.3.5. Отображения фильтров.................................................................................... 82
5.3.6. Отображение ошибок........................................................................................ 83
5.3.7. Ссылки на элементы окружения, на элементы окружения ресурсов,
или на ресурсы............................................................................................................ 83
5.4. Установка Web-приложений...................................................................................... 84
5.5. Размещение Web-приложений..................................................................................85
5.6. Просмотр списка установленных и размещенных Web-приложений.....................86
5.7. Выполнение Web-приложений.................................................................................. 86
5.8. Обновление Web-приложений.................................................................................. 86
5.8.1. Перезагрузка Web-приложений........................................................................87
5.8.2. Повторное размещение Web-приложений...................................................... 88
5.9. Удаление Web-приложений.......................................................................................89
5.10. Отмена размещения Web-приложений.................................................................. 89
5.11. Интернационализация и локализация Web-приложений......................................89
5.12. Получение доступа к базам данных из Web-приложений.....................................91
5.12.1. Примеры...........................................................................................................91
5.12.2. Установка и запуск сервера баз данных........................................................91
5.12.3. Заполнение базы данных............................................................................... 92
5.12.4. Настройка в Web-приложении ссылки на источник данных.........................92
5.12.5. Определение источника данных в Tomcat.................................................... 93
5.12.6. Настройка в Tomcat отображения JNDI-имени в источник данных............. 93
5.13. Дополнительная информация.................................................................................94

6. Java API for XML Processing.........................................................................................94

Web-

Rendered by www.RenderX.com
7

6.1. JAXP API......................................................................................................................95


6.2. Обзор пакетов.............................................................................................................95
6.3. The Simple API for XML (SAX).................................................................................... 96
6.3.1. Пакеты SAX........................................................................................................97
6.4. The Document Object Model API (DOM)..................................................................... 98
6.4.1. Пакеты DOM.......................................................................................................99
6.5. XML Stylesheet Language Transformations API (XSLT)............................................. 99
6.5.1. Пакеты XSLT.................................................................................................... 100
6.6. Компиляция и выполнение программ..................................................................... 100
6.7. Куда идти дальше?...................................................................................................100

7. Simple API for XML...................................................................................................... 101


7.1. Когда используется SAX.......................................................................................... 102
7.2. Написание простого XML-файла.............................................................................102
7.2.1. Создание файла.............................................................................................. 103
7.2.2. Написание объявления...................................................................................103
7.2.3. Добавление комментария...............................................................................103
7.2.4. Определение корневого элемента.................................................................103
7.2.5. Добавление атрибутов к элементу................................................................ 104
7.2.6. Добавление вложенных элементов............................................................... 104
7.2.7. Добавление HTML-текста .............................................................................. 105
7.2.8. Добавление пустого элемента....................................................................... 106
7.2.9. Законченный продукт...................................................................................... 106
7.3. Дублирование XML-файла при помощи SAX-анализатора.................................. 107
7.3.1. Создание скелета программы........................................................................ 107
7.3.2. Импорт классов................................................................................................108
7.3.3. Настройка ввода/вывода................................................................................ 108
7.3.4. Реализация интерфейса ContentHandler.......................................................109
7.3.5. Настройка анализатора.................................................................................. 110
7.3.6. Вывод результата............................................................................................111
7.3.7. Расстановка разделителей при выводе........................................................ 112
7.3.8. Обработка событий содержимого.................................................................. 112
7.3.8.1. События документа................................................................................ 112
7.3.8.2. События элементов................................................................................113
7.3.8.3. События для символов.......................................................................... 114
7.3.9. Компиляция и выполнение программы......................................................... 117
7.3.10. Проверка выводимой информации..............................................................118
7.3.11. Идентификация событий.............................................................................. 118
7.3.12. Сжатие выводимой информации................................................................. 121
7.3.13. Исследование выходной информации........................................................ 123
7.3.14. Документы и данные..................................................................................... 124
7.4. Добавление дополнительных обработчиков событий.......................................... 124

Web-

Rendered by www.RenderX.com
8

7.4.1. Указание месторасположения документа..................................................... 124


7.4.2. Управление командами обработки................................................................ 126
7.4.3. Резюме............................................................................................................. 127
7.5. Обработка ошибок в неверифицирующем анализаторе...................................... 128
7.5.1. Введение в ошибки..........................................................................................128
7.5.2. Обработка SAXParseException....................................................................... 129
7.5.3. Обработка SAXException................................................................................ 130
7.5.4. Усовершенствование обработчика SAXParseException...............................131
7.5.5. Обработка ParserConfigurationException....................................................... 132
7.5.6. Обработка IOException....................................................................................133
7.5.7. Обработка нефатальных ошибок...................................................................133
7.5.8. Обработка предупреждений........................................................................... 134
7.6. Замена и вставка текста.......................................................................................... 135
7.6.1. Обработка специальных символов................................................................ 135
7.6.1.1. Предопределенные сущности............................................................... 136
7.6.1.2. Символьные ссылки............................................................................... 136
7.6.2. Использование ссылки на сущность в XML-документе................................136
7.6.3. Обработка текста с синтаксисом XML........................................................... 137
7.6.4. Обработка CDATA и других символов...........................................................138
7.7. Создание определения типа документа (DTD)...................................................... 139
7.7.1. Основные DTD-определения..........................................................................139
7.7.2. Определение текста и вложенных элементов.............................................. 140
7.7.3. Ограничения DTD............................................................................................ 140
7.7.4. Значения специальных элементов в DTD..................................................... 141
7.7.5. Ссылка на DTD................................................................................................ 141
7.8. Влияние DTD на неверифицирующий анализатор................................................143
7.8.1. Отслеживание игнорируемых пробелов........................................................144
7.8.2. Очистка.............................................................................................................145
7.8.3. Документы и данные....................................................................................... 145
7.8.4. Пустые элементы, пересмотренный вариант............................................... 146
7.9. Определение атрибутов и сущностей в DTD......................................................... 146
7.9.1. Определение атрибутов в DTD...................................................................... 146
7.9.2. Определение сущностей в DTD..................................................................... 148
7.9.3. Вывод ссылок на сущность.............................................................................149
7.9.4. Дополнительные полезные сущности........................................................... 149
7.9.5. Ссылки на внешние сущности........................................................................ 149
7.9.6. Отображение внешней сущности...................................................................151
7.9.7. Итоговая информация по сущностям............................................................ 151
7.10. Обращение к двоичным сущностям......................................................................151
7.10.1. Использование типа данных MIME.............................................................. 151
7.10.2. Альтернатива: использование ссылок на сущность...................................153
7.11. Выбор вашей реализации анализатора............................................................... 153

Web-

Rendered by www.RenderX.com
9

7.12. Использование верифицирующего анализатора................................................ 153


7.12.1. Конфигурирование генератора.................................................................... 154
7.12.2. Верификация с использованием XML-схемы..............................................154
7.12.2.1. Установка свойств SAX-анализатора................................................. 155
7.12.2.2. Установка соответствующей обработки ошибок................................155
7.12.2.3. Установка связи между документом и схемой................................... 156
7.12.3. Эксперименты с ошибками верификации................................................... 157
7.12.4. Обработка ошибок в верифицирующем анализаторе................................158
7.13. Определение сущностей-параметров и условных секций..................................159
7.13.1. Создание сущностей-параметров и обращение к ним ..............................159
7.13.2. Условные секции........................................................................................... 161
7.14. Анализ параметризованного DTD.........................................................................162
7.14.1. DTD-предупреждения....................................................................................163
7.15. Обработка лексических событий...........................................................................164
7.15.1. Как работает LexicalHandler..........................................................................165
7.15.2. Работа с LexicalHandler.................................................................................165
7.15.2.1. Отображение комментариев................................................................168
7.15.2.2. Отображение другой лексической информации................................ 168
7.16. Использование DTDHandler и EntityResolver....................................................... 171
7.16.1. DTDHandler API..............................................................................................171
7.16.2. EntityResolver API.......................................................................................... 172
7.17. Дополнительная информация...............................................................................173

8. Document Object Model............................................................................................... 173


8.1. Когда используется DOM.........................................................................................173
8.1.1. Документы против данных.............................................................................. 174
8.1.2. Модель смешанного содержимого.................................................................174
8.1.2.1. Типы узлов.............................................................................................. 175
8.1.3. Более простая модель.................................................................................... 175
8.1.4. Увеличение сложности................................................................................... 176
8.1.5. Выбор вашей модели...................................................................................... 178
8.2. Чтение XML-данных в DOM..................................................................................... 179
8.2.1. Создание программы...................................................................................... 179
8.2.1.1. Создание скелета................................................................................... 179
8.2.1.2. Импорт требуемых классов................................................................... 179
8.2.1.3. Объявление DOM................................................................................... 180
8.2.1.4. Обработка ошибок..................................................................................180
8.2.1.5. Создание экземпляра генератора.........................................................182
8.2.1.6. Получение анализатора и анализ файла............................................. 182
8.2.1.7. Выполнение программы.........................................................................182
8.2.2. Дополнительная информация........................................................................ 183
8.2.2.1. Настройка генератора............................................................................ 183
8.2.2.2. Обработка ошибок верификации.......................................................... 183
8.2.3. Забегая вперед................................................................................................ 185

Web-

Rendered by www.RenderX.com
10

8.3. Отображение DOM-иерархии.................................................................................. 185


8.3.1. Отображение узлов дерева............................................................................ 185
8.3.2. Преобразование DomEcho в приложение GUI..............................................185
8.3.2.1. Добавление операторов импорта......................................................... 185
8.3.2.2. Создание GUI-среды.............................................................................. 186
8.3.2.3. Добавление компонентов для отображения........................................ 188
8.3.3. Создание адаптера для отображения DOM в JTree.....................................191
8.3.3.1. Определение класса AdapterNode........................................................ 191
8.3.3.2. Определение адаптера TreeModel........................................................196
8.3.4. Завершение..................................................................................................... 200
8.4. Исследование структуры DOM................................................................................201
8.4.1. Отображение простого дерева.......................................................................201
8.4.2. Отображение более сложного дерева...........................................................202
8.4.2.1. Резюме по лексическим управляющим элементам.............................205
8.4.3. Завершение..................................................................................................... 206
8.5. Создание дружественного пользователю JTree из DOM......................................207
8.5.1. Сжатие просматриваемого дерева................................................................ 207
8.5.1.1. Сделать операции выбираемыми......................................................... 207
8.5.1.2. Идентификация узлов дерева............................................................... 207
8.5.1.3. Управление видимостью узла............................................................... 209
8.5.1.4. Управление доступом к потомку............................................................210
8.5.1.5. Проверка результатов............................................................................211
8.5.1.6. Дополнительные действия.................................................................... 211
8.5.2. Действия с выбранными узлами дерева....................................................... 212
8.5.2.1. Идентификация типов узлов..................................................................212
8.5.2.2. Объединение узлов для определения содержимого элемента..........213
8.5.2.3. Отображение содержимого в JTree ..................................................... 215
8.5.2.4. Соединение JTree и JEditorPane .......................................................... 216
8.5.2.5. Выполнение приложения....................................................................... 217
8.5.2.6. Дополнительное задание.......................................................................219
8.5.3. Обработка изменений..................................................................................... 220
8.5.4. Завершение .................................................................................................... 220
8.6. Создание и управление DOM..................................................................................220
8.6.1. Получение DOM из генератора...................................................................... 220
8.6.1.1. Измененяем код......................................................................................220
8.6.1.2. Создаем узлы Element и Text................................................................ 221
8.6.1.3. Выполните приложение......................................................................... 223
8.6.2. Нормализация DOM........................................................................................ 223
8.6.3. Другие операции..............................................................................................224
8.6.3.1. Обход узлов............................................................................................ 225
8.6.3.2. Поиск узлов............................................................................................. 225
8.6.3.3. Получение содержимого узла................................................................226
8.6.3.4. Создание атрибутов............................................................................... 227
8.6.3.5. Удаление и изменение узлов................................................................ 228
8.6.3.6. Вставка узлов..........................................................................................228
8.6.4. Завершение..................................................................................................... 228

Web-

Rendered by www.RenderX.com
11

8.7. Использование пространства имен........................................................................ 228


8.7.1. Определение пространства имен в DTD....................................................... 228
8.7.2. Ссылка на пространство имен........................................................................229
8.7.3. Определение префикса пространства имен................................................. 229
8.8. Верификация при помощи XML Schema................................................................ 231
8.8.1. Обзор процесса верификации........................................................................231
8.8.2. Настройка генератора DocumentBuilder........................................................ 231
8.8.2.1. Установка связи документа со схемой..................................................232
8.8.3. Верификация при использовании нескольких пространств имен............... 233
8.8.3.1. Объявление схем в наборе XML-данных............................................. 234
8.8.3.2. Объявление схем в приложении........................................................... 234
8.9. Дополнительная информация.................................................................................236

9. XML Stylesheet Language for Transformations........................................................... 236


9.1. Введение в XSLT и XPath........................................................................................ 236
9.1.1. JAXP-пакеты преобразований........................................................................ 237
9.2. Выбор механизма трансформации......................................................................... 238
9.2.1. Анализ производительности...........................................................................238
9.2.2. Анализ функциональности............................................................................. 240
9.2.3. Что выбрать..................................................................................................... 240
9.3. Как работает XPath.................................................................................................. 240
9.3.1. Выражения XPATH.......................................................................................... 241
9.3.2. Модель данных XSLT/XPath........................................................................... 241
9.3.3. Шаблоны и контексты......................................................................................241
9.3.4. Основы XPath-адресации............................................................................... 242
9.3.5. Основы XPath-выражений.............................................................................. 243
9.3.6. Комбинирование индексных адресов............................................................ 243
9.3.7. Групповые символы........................................................................................ 244
9.3.8. Адресация расширенного пути.......................................................................244
9.3.9. Типы данных и операторы XPath................................................................... 244
9.3.10. Строковое значение элемента..................................................................... 245
9.3.11. XPath-функции............................................................................................... 245
9.3.11.1. Функции набора узлов..........................................................................245
9.3.11.2. Функции позиционирования.................................................................245
9.3.11.3. Строковые функции..............................................................................246
9.3.11.4. Логические функции............................................................................. 246
9.3.11.5. Числовые функции............................................................................... 247
9.3.11.6. Функции преобразования.....................................................................247
9.3.11.7. Функции пространства имен................................................................ 247
9.3.12. Резюме........................................................................................................... 247
9.4. Запись DOM в XML-файл.........................................................................................248
9.4.1. Чтение XML...................................................................................................... 248
9.4.2. Создание преобразователя............................................................................250

Web-

Rendered by www.RenderX.com
12

9.4.3. Вывод XML....................................................................................................... 252


9.4.4. Вывод поддерева DOM................................................................................... 253
9.4.4.1. Очистка....................................................................................................254
9.4.5. Резюме............................................................................................................. 254
9.5. Генерирование DOM из произвольной структуры данных....................................254
9.5.1. Создание простого файла.............................................................................. 255
9.5.2. Создание простого анализатора.................................................................... 256
9.5.3. Изменение анализатора для генерирования SAX-событий.........................259
9.5.4. Использование анализатора в качестве SAXSource....................................265
9.5.5. Выполнение преобразования......................................................................... 268
9.6. Преобразование XML-данных при помощи XSLT..................................................268
9.6.1. Определение простого типа документа <article>..........................................268
9.6.2. Создание тестового документа...................................................................... 270
9.6.3. Написание XSLT-преобразования................................................................. 271
9.6.4. Обработка основных структурных элементов...............................................272
9.6.4.1. Обработка элемента <TITLE>............................................................... 273
9.6.4.2. Обработка заголовков............................................................................ 273
9.6.4.3. Генерирование сообщений времени выполнения............................... 274
9.6.5. Написание основной программы....................................................................275
9.6.6. Удаление пробелов......................................................................................... 277
9.6.7. Обработка оставшихся структурных элементов........................................... 279
9.6.7.1. Изменение шаблона <PARA>................................................................280
9.6.7.2. Обработка элементов <LIST> и <ITEM>...............................................280
9.6.7.3. Сортировка шаблонов в таблице стилей............................................. 281
9.6.7.4. Обработка элементов <NOTE>............................................................. 282
9.6.7.5. Выполнение программы.........................................................................283
9.6.8. Обработка встроенных элементов (элементов содержимого).................... 283
9.6.8.1. Выполнение программы.........................................................................287
9.6.9. Распечатка HTML............................................................................................ 287
9.6.10. Что еще может делать XSLT?...................................................................... 287
9.6.10.1. Проблемы с переменными.................................................................. 289
9.7. Преобразование из командной строки................................................................... 289
9.7.1. Компиляция транслета....................................................................................289
9.7.2. Выполнение транслета................................................................................... 290
9.8. Объединение преобразований при помощи цепочки фильтров.......................... 291
9.8.1. Написание программы.................................................................................... 291
9.8.2. Как работает цепочка фильтров.................................................................... 295
9.8.3. Тестирование программы............................................................................... 295
9.8.4. Заключение...................................................................................................... 298
9.9. Дополнительная информация.................................................................................298

10. Java API for XML-based RPC.................................................................................... 298


10.1. Что такое JAX-RPC?...............................................................................................298

Web-

Rendered by www.RenderX.com
13

10.2. Простой пример: HelloWorld.................................................................................. 299


10.2.1. HelloWorld во время выполнения................................................................. 299
10.2.2. Файлы HelloWorld.......................................................................................... 300
10.2.3. Настройка.......................................................................................................300
10.2.4. Создание и размещение службы................................................................. 301
10.2.4.1. Кодирование интерфейса определения службы и класса
реализации...........................................................................................................301
10.2.4.2. Компиляция кода определения службы............................................. 302
10.2.4.3. Пакетирование кода в WAR-файл.......................................................302
10.2.4.4. Генерирование узлов и WSDL-файла.................................................303
10.2.4.5. Размещение службы............................................................................ 304
10.2.4.6. Верификация размещения...................................................................304
10.2.4.7. Отмена размещения службы...............................................................304
10.2.5. Создание и запуск клиентской программы..................................................304
10.2.5.1. Генерирование заглушек..................................................................... 305
10.2.5.2. Кодирование клиентской программы.................................................. 305
10.2.5.3. Компилирование кода клиентской программы...................................306
10.2.5.4. Пакетирование клиентской программы.............................................. 306
10.2.5.5. Выполнение клиентской программы................................................... 307
10.2.6. Итеративная разработка...............................................................................307
10.2.7. Особенности реализации............................................................................. 307
10.3. Типы, поддерживаемые в JAX-RPC......................................................................308
10.3.1. Классы J2SE SDK.......................................................................................... 308
10.3.2. Примитивы..................................................................................................... 309
10.3.3. Массивы......................................................................................................... 309
10.3.4. Прикладные классы.......................................................................................309
10.3.5. Компоненты JavaBeans................................................................................. 309
10.4. Пример клиентской программы динамического прокси...................................... 310
10.4.1. Листинг клиентской программы динамического прокси HelloClient........... 310
10.4.2. Создание и выполнение примера динамического прокси..........................311
10.5. Пример клиентской программы Dynamic Invocation Interface (DII)..................... 311
10.5.1. Листинг DII HelloClient................................................................................... 312
10.5.2. Создание и выполнение примера DII...........................................................313
10.6. Безопасность в JAX-RPC....................................................................................... 314
10.6.1. Базовая аутентификация по SSL................................................................. 314
10.6.1.1. Генерирование сертификатов для базовой аутентификации...........314
10.6.1.2. Добавление SSL-коннектора к Tomcat................................................315
10.6.1.3. Добавление элементов безопасности в web.xml............................... 316
10.6.1.4. Установка свойств безопасности в коде клиентской
программы............................................................................................................316
10.6.1.4.1. Свойство trustStore...................................................................... 317
10.6.1.4.2. Свойство trustStorePassword...................................................... 317
10.6.1.4.3. Свойства username и password.................................................. 317
10.6.1.5. Компоновка и выполнение примера для базовой аутентификации
по SSL...................................................................................................................317

Web-

Rendered by www.RenderX.com
14

10.6.2. Взаимная аутентификация по SSL...............................................................318


10.7. JAX-RPC в J2EE SDK 1.3.1.................................................................................... 318
10.7.1. Предварительные требования..................................................................... 319
10.7.2. Пример программы........................................................................................319
10.7.3. Пакетирование клиентской программы JAX-RPC и Web-службы ............ 320
10.7.4. Настройка J2EE SDK 1.3.1............................................................................320
10.7.5. Размещение сессионного компонента GreetingEJB................................... 321
10.7.6. Размещение JAX-RPC-службы.....................................................................322
10.7.7. Выполнение клиентского приложения JAX-RPC.........................................322
10.7.8. Удаление действий jwsdponj2ee.................................................................. 323
10.8. Создание службы JAX-RPC в deploytool...............................................................323
10.8.1. Компиляция исходного кода......................................................................... 323
10.8.2. Компоновка Web-приложения...................................................................... 324
10.8.3. Размещение Web-приложения..................................................................... 325
10.8.4. Проверка статуса Web-службы.................................................................... 325
10.8.5. Выполнение клиентской программы............................................................ 326
10.9. Дополнительная информация...............................................................................326

11. Java API for XML Messaging..................................................................................... 326


11.1. Введение в JAXM................................................................................................... 327
11.1.1. Сообщения.....................................................................................................327
11.1.1.1. Структура XML-документа................................................................... 328
11.1.1.2. Что такое сообщение?......................................................................... 328
11.1.1.2.1. Сообщения без вложений........................................................... 328
11.1.1.2.2. Сообщения с вложениями.......................................................... 329
11.1.2. Соединения....................................................................................................331
11.1.2.1. SOAPConnection................................................................................... 331
11.1.2.2. ProviderConnection................................................................................ 332
11.1.3. Поставщики службы обмена сообщениями................................................ 333
11.1.3.1. Прозрачность........................................................................................ 333
11.1.3.2. Профили................................................................................................ 333
11.1.3.3. Непрерывная активность..................................................................... 333
11.1.3.4. Промежуточные пункты назначения................................................... 334
11.1.3.5. Когда используется поставщик службы обмена сообщениями........ 334
11.1.3.6. Обмен сообщениями с поставщиком и без него................................335
11.2. Выполнение примеров........................................................................................... 335
11.2.1. Примеры программ........................................................................................336
11.2.2. Исходный код примеров................................................................................337
11.3. Учебник....................................................................................................................337
11.3.1. Клиент, не использующий поставщика службы обмена
сообщениями............................................................................................................. 338
11.3.1.1. Получение объекта SOAPConnection................................................. 338
11.3.1.2. Создание сообщения........................................................................... 339
11.3.1.2.1. Части сообщения......................................................................... 339

Web-

Rendered by www.RenderX.com
15

11.3.1.2.2. Доступ к элементам сообщения................................................. 339


11.3.1.2.3. Добавление содержимого в тело............................................... 340
11.3.1.3. Передача сообщения........................................................................... 343
11.3.1.4. Получение содержимого сообщения.................................................. 343
11.3.2. Клиент, использующий поставщика службы обмена сообщениями......... 344
11.3.2.1. Получение объекта ProviderConnection.............................................. 344
11.3.2.2. Создание сообщения........................................................................... 345
11.3.2.2.1. Получение MessageFactory.........................................................345
11.3.2.2.2. Добавление содержимого в заголовок.......................................346
11.3.2.2.3. Добавление содержимого в SOAP-тело.................................... 347
11.3.2.2.4. Добавление содержимого в объект SOAPPart.......................... 349
11.3.2.3. Передача сообщения........................................................................... 349
11.3.3. Добавление вложений.................................................................................. 350
11.3.3.1. Создание объекта AttachmentPart и добавление содержимого........350
11.3.3.2. Получение доступа к объекту AttachmentPart.................................... 352
11.3.3.3. Резюме.................................................................................................. 352
11.3.4. Ошибки SOAP................................................................................................ 352
11.3.4.1. Обзор..................................................................................................... 352
11.3.4.2. Создание и заполнение объекта SOAPFault...................................... 354
11.3.4.3. Извлечение информации об ошибке.................................................. 355
11.4. Примеры приложений............................................................................................ 356
11.4.1. Request.java................................................................................................... 356
11.4.2. UddiPing.java и MyUddiPing.java................................................................... 358
11.4.2.1. Создание MyUddiPing.java................................................................... 359
11.4.2.1.1. Настройка..................................................................................... 360
11.4.2.1.2. Исследование MyUddiPing.......................................................... 361
11.4.2.2. Добавление нового кода...................................................................... 363
11.4.3. SOAPFaultTest.java........................................................................................366
11.4.3.1. Выполнение SOAPFaultTest.................................................................368
11.4.4. Заключение.................................................................................................... 370
11.5. Дополнительная информация...............................................................................370

12. Java API for XML Registries.......................................................................................370


12.1. Обзор JAXR.............................................................................................................371
12.1.1. Что такое реестр?..........................................................................................371
12.1.2. Что такое JAXR?............................................................................................ 371
12.1.3. Архитектура JAXR......................................................................................... 372
12.2. Реализация JAXR-клиента.................................................................................... 373
12.2.1. Установка соединения.................................................................................. 373
12.2.1.1. Начальные сведения: получение доступа к реестру......................... 374
12.2.1.2. Создание или поиск центра соединений............................................ 374
12.2.1.3. Создание соединения.......................................................................... 374
12.2.1.4. Установка свойств соединения........................................................... 375
12.2.1.5. Получение и использование объекта RegistryService....................... 377
12.2.2. Запрос реестра.............................................................................................. 377
12.2.2.1. Поиск организации по названию......................................................... 378

Web-

Rendered by www.RenderX.com
16

12.2.2.2. Поиск организаций по классификации................................................379


12.2.2.3. Поиск служб и связей со службами.....................................................381
12.2.3. Управление данными реестра......................................................................382
12.2.3.1. Получение авторизации от реестра....................................................382
12.2.3.2. Создание организации......................................................................... 382
12.2.3.3. Добавление классификаций................................................................ 384
12.2.3.4. Добавление служб и связей со службами в организацию................ 384
12.2.3.5. Сохранение организации..................................................................... 385
12.2.3.6. Удаление данных из реестра.............................................................. 386
12.2.4. Использование таксономий в JAXR-клиентах.............................................387
12.2.4.1. Определение таксономии.................................................................... 387
12.2.4.2. Указание почтовых адресов................................................................ 390
12.2.5. Выполнение примеров клиентских приложений......................................... 392
12.2.5.1. Перед компиляцией примеров............................................................ 392
12.2.5.2. Компиляция примеров..........................................................................394
12.2.5.3. Выполнение примеров......................................................................... 394
12.2.5.4. Выполнение примера JAXRPublish..................................................... 395
12.2.5.5. Выполнение примера JAXRQuery ...................................................... 395
12.2.5.6. Выполнение примера JAXRQueryByNAICSClassification...................395
12.2.5.7. Выполнение примера JAXRDelete...................................................... 395
12.2.5.8. Выполнение примера JAXRQueryByWSDLClassification................... 395
12.2.5.9. Публикация классификационной схемы.............................................396
12.2.5.10. Выполнение примеров, работающих с почтовым адресом............ 396
12.2.5.11. Удаление классификационной схемы...............................................397
12.2.5.12. Получение списка ваших объектов реестра.....................................397
12.2.5.13. Другие задания................................................................................... 397
12.3. Дополнительная информация...............................................................................397

13. Технология Java Servlet........................................................................................... 398


13.1. Что такое Сервлет?................................................................................................398
13.2. Примеры сервлетов............................................................................................... 399
13.2.1. Устранение неисправностей.........................................................................402
13.3. Жизненный цикл сервлета.....................................................................................403
13.3.1. Обработка событий жизненного цикла сервлетов......................................403
13.3.1.1. Определение класса-слушателя.........................................................403
13.3.1.2. Определение классов-слушателей событий......................................405
13.3.2. Обработка ошибок.........................................................................................405
13.4. Использование совместного доступа к информации.......................................... 406
13.4.1. Использования объектов области действия............................................... 406
13.4.2. Управление параллельным доступом к общим ресурсам......................... 407
13.4.3. Доступ к базам данных..................................................................................408
13.5. Инициализация сервлета...................................................................................... 409
13.6. Написание методов служб.....................................................................................410
13.6.1. Получение информации из запросов...........................................................410
13.6.2. Построение ответов...................................................................................... 412

Web-

Rendered by www.RenderX.com
17

13.7. Фильтрация запросов и ответов........................................................................... 414


13.7.1. Програмирование фильтров.........................................................................415
13.7.2. Программирование заказных запросов и ответов...................................... 416
13.7.3. Задание отображений фильтров..................................................................418
13.8. Вызов других Web-ресурсов..................................................................................420
13.8.1. Включение других ресурсов в ответ............................................................ 421
13.8.2. Передача управления другому Web-компоненту........................................422
13.9. Организация доступа к web-контексту..................................................................423
13.10. Сохранение состояния клиента.......................................................................... 424
13.10.1. Организация доступа к сессии................................................................... 424
13.10.2. Ассоциирование атрибутов с сессией....................................................... 424
13.10.2.1. Уведомление объектов о том, что они ассоциированы с
сессией................................................................................................................. 425
13.10.3. Управление сессией....................................................................................425
13.10.4. Отслеживание сессии................................................................................. 426
13.11. Завершение работы сервлета.............................................................................427
13.11.1. Отслеживание запросов службы................................................................427
13.11.2. Предупреждение методов о завершении работы.....................................428
13.11.3. Создание "изящных" затянувшихся методов............................................ 429
13.12. Дополнительная информация.............................................................................429

14. Технология JavaServer Pages.................................................................................. 430


14.1. Что такое JSP-страница?.......................................................................................430
14.2. Примеры JSP-страниц........................................................................................... 432
14.3. Жизненный цикл JSP-страницы............................................................................ 434
14.3.1. Трансляция и компиляция............................................................................ 434
14.3.2. Выполнение................................................................................................... 435
14.3.2.1. Использование буферизации.............................................................. 435
14.3.2.2. Обработка ошибок................................................................................435
14.4. Инициализация и завершение работы JSP-страницы........................................ 436
14.5. Создание статического содержимого................................................................... 437
14.6. Создание динамического содержимого................................................................437
14.6.1. Использование объектов в JSP-страницах................................................. 437
14.6.1.1. Неявные объекты................................................................................. 438
14.6.1.2. Объекты-приложения........................................................................... 438
14.6.1.3. Использование совместного доступа к объектам (общие
объекты)............................................................................................................... 438
14.6.2. JSP-элементы сценариев............................................................................. 439
14.6.2.1. Объявления...........................................................................................440
14.6.2.2. Скриптлеты........................................................................................... 440
14.6.2.3. Выражения............................................................................................ 442
14.7. Включение содержимого в JSP-страницу.............................................................443
14.8. Передача управления другому web-компоненту................................................. 444

Web-

Rendered by www.RenderX.com
18

14.8.1. Элемент jsp:param.........................................................................................444


14.9. Включение апплета................................................................................................ 445
14.10. Расширение JSP-языка........................................................................................447
14.11. Дополнительная информация.............................................................................448

15. JavaBean-компоненты в JSP-страницах................................................................. 448


15.1. Правила создания JavaBean-компонентов.......................................................... 449
15.2. Зачем использовать JavaBean-компоненты?.......................................................450
15.3. Создание и использование JavaBean-компонентов............................................ 451
15.4. Установление свойств JavaBean-компонентов....................................................452
15.5. Извлечение свойств JavaBean-компонентов....................................................... 454

16. Заказные теги в JSP-страницах...............................................................................455


16.1. Что такое заказной тег?......................................................................................... 456
16.2. Примеры JSP-страниц........................................................................................... 457
16.3. Использование тегов..............................................................................................459
16.3.1. Объявление библиотек тегов....................................................................... 459
16.3.2. Как сделать реализацию библиотеки тегов доступной.............................. 460
16.3.3. Типы тегов......................................................................................................460
16.3.3.1. Простые теги......................................................................................... 460
16.3.3.2. Теги с атрибутами.................................................................................461
16.3.3.3. Теги с телом.......................................................................................... 461
16.3.3.4. Осуществление выбора между способом передачи информации
в атрибутах или в теле тега................................................................................ 462
16.3.3.5. Теги, определяющие переменные создания сценария..................... 462
16.3.3.6. Взаимодействие тегов..........................................................................462
16.4. Определение тегов................................................................................................ 463
16.4.1. Обработчики тегов.........................................................................................463
16.4.2. Дескрипторы библиотеки тегов.................................................................... 464
16.4.2.1. Элемент listener.................................................................................... 465
16.4.2.2. Элемент tag...........................................................................................465
16.4.3. Простые теги..................................................................................................466
16.4.3.1. Обработчики тегов................................................................................466
16.4.3.2. Элемент body-content........................................................................... 467
16.4.4. Теги с атрибутами......................................................................................... 467
16.4.4.1. Определение атрибутов в обработчике тега..................................... 467
16.4.4.2. Элемент Attribute.................................................................................. 468
16.4.4.3. Проверка атрибутов............................................................................. 469
16.4.5. Теги с телами................................................................................................. 470
16.4.5.1. Обработчики тегов................................................................................470
16.4.5.1.1. Случай, когда обработчик тега не взаимодействует с его
телом.............................................................................................................. 470
16.4.5.1.2. Случай, когда обработчик тега взаимодействует с его
телом.............................................................................................................. 470

Web-

Rendered by www.RenderX.com
19

16.4.5.2. Элемент body-content........................................................................... 471


16.4.6. Теги, определяющие переменные создания сценариев............................ 472
16.4.6.1. Обработчики тегов................................................................................472
16.4.6.2. Предоставление информации о переменной создания
сценария...............................................................................................................472
16.4.6.2.1. Элемент variable.......................................................................... 473
16.4.6.2.2. Класс TagExtraInfo....................................................................... 474
16.4.7. Взаимодействие тегов...................................................................................475
16.5. Примеры..................................................................................................................477
16.5.1. Тег итераций.................................................................................................. 477
16.5.1.1. JSP-страница........................................................................................ 477
16.5.1.2. Обработчик тега....................................................................................478
16.5.1.3. Дополнительный информационный класс тега..................................481
16.5.2. Библиотека тегов шаблона...........................................................................481
16.5.2.1. JSP-страница........................................................................................ 482
16.5.2.2. Обработчики тегов................................................................................483
16.5.3. Как вызывается обработчик тега?................................................................486

17. Стандартная библиотека тегов JavaServer-страниц............................................. 487


17.1. Примеры JSP-страниц........................................................................................... 488
17.2. Использование JSTL.............................................................................................. 490
17.3. Поддержка языка выражений................................................................................ 492
17.3.1. Двойные библиотеки..................................................................................... 493
17.3.2. Язык выражений JSTL...................................................................................494
17.3.2.1. Атрибуты............................................................................................... 494
17.3.2.2. Неявные объекты................................................................................. 494
17.3.2.3. Литералы...............................................................................................495
17.3.2.4. Операторы.............................................................................................496
17.3.3. Взаимодействие тегов...................................................................................496
17.4. Теги ядра.................................................................................................................497
17.4.1. Теги выражений............................................................................................. 497
17.4.2. Теги управления потоками............................................................................499
17.4.2.1. Теги условий......................................................................................... 499
17.4.2.2. Теги итераций....................................................................................... 501
17.4.3. URL-теги......................................................................................................... 502
17.5. XML-теги..................................................................................................................503
17.5.1. Теги ядра........................................................................................................504
17.5.2. Теги управления потоками............................................................................505
17.5.3. Теги преобразований.................................................................................... 506
17.6. Теги интернационализации................................................................................... 506
17.6.1. Установка региона......................................................................................... 507
17.6.2. Теги сообщений............................................................................................. 507
17.6.2.1. Тег bundle.............................................................................................. 507
17.6.2.2. Тег message.......................................................................................... 508

Web-

Rendered by www.RenderX.com
20

17.6.3. Теги форматирования................................................................................... 508


17.7. SQL-теги.................................................................................................................. 509
17.7.1. Конечный интерфейс тега query...................................................................511
17.8. Дополнительная информация...............................................................................513

18. Безопасность Web-приложений...............................................................................513


18.1. Краткий обзор......................................................................................................... 514
18.2. Пользователи, группы и роли................................................................................514
18.2.1. Роли безопасности........................................................................................ 515
18.2.2. Управление ролями и пользователями....................................................... 515
18.2.2.1. Использование Утилиты Администрирования Web-сервера
Tomcat (admintool)................................................................................................516
18.2.2.1.1. Запуск Tomcat.............................................................................. 516
18.2.2.1.2. Запуск admintool...........................................................................517
18.2.2.2. Управление ролями..............................................................................518
18.2.2.3. Управление пользователями...............................................................518
18.2.2.3.1. Рассуждения при изменении профиля пользователя.............. 519
18.2.3. Отображение ролей приложения на роли области.................................... 520
18.3. Безопасность Web-ярусов..................................................................................... 521
18.3.1. Защита Web-ресурсов...................................................................................521
18.3.2. Контроль доступа к Web-ресурсам.............................................................. 521
18.3.3. Установка безопасности без использования deploytool............................. 522
18.3.4. Аутентификация пользователей Web-ресурсов......................................... 524
18.3.4.1. Базовая аутентификация..................................................................... 524
18.3.4.2. Аутентификация, связанная с формой............................................... 524
18.3.4.3. Аутентификация, основанная на сертификации клиента................. 524
18.3.4.4. Профильная (digest) аутентификация................................................ 525
18.3.4.5. Настройка механизма аутентификации Web-ресурсов..................... 525
18.3.4.6. Использование протокола SSL для увеличения
конфиденциальности базовой HTTP-аутентификации и аутентификации,
связанной с формой............................................................................................ 526
18.3.5. Использование программируемой безопасности в Web-ярусах............... 526
18.3.6. Незащищенные Web-ресурсы...................................................................... 527
18.4. Безопасность EIS-ярусов.......................................................................................527
18.4.1. Настройка входа в систему...........................................................................528
18.4.2. Вход, управляемый контейнером.................................................................528
18.4.3. Вход, управляемый компонентом................................................................ 528
18.5. Установка и настройка поддержки SSL для Tomcat............................................ 528
18.5.1. Использование JSSE.....................................................................................529
18.5.2. Настройка сертификата сервера................................................................. 529
18.5.2.1. Получение цифрового сертификата................................................... 531
18.5.3. Настройка SSL-коннектора........................................................................... 532
18.5.3.1. Добавление SSL-коннектора в admintool............................................532
18.5.3.2. Настройка SSL-коннектора в файле server.xml..................................533

Web-

Rendered by www.RenderX.com
21

18.5.4. Проверка поддержки SSL............................................................................. 534


18.5.5. Выявление неисправностей при SSL-соединениях....................................534
18.5.5.1. При загрузке Tomcat возбуждается исключительная ситуация
наподобие "java.io.FileNotFoundException: {some-directory}/{some-file} not
found".................................................................................................................... 534
18.5.5.2. При загрузке Tomcat возбуждается исключительная ситуация
наподобие "java.io.FileNotFoundException: Keystore was tampered with, or
password was incorrect"........................................................................................534
18.5.5.3. Если у вас по прежнему возникают проблемы,..................................534
18.5.6. Общие советы по работе с SSL................................................................... 535
18.5.7. Дополнительная информация о протоколе SSL......................................... 535
18.6. Устранение неисправностей................................................................................. 535
18.6.1. Сервер возвращает код ответа HTTP: 403..................................................535
18.7. Дополнительная информация...............................................................................536

19. Приложение Coffee Break.........................................................................................536


19.1. Обзор приложения Coffee Break........................................................................... 536
19.2. Служба JAX-RPC поставщика............................................................................... 538
19.2.1. Интерфейс службы........................................................................................538
19.2.2. Реализация службы...................................................................................... 538
19.2.3. Публикация службы в реестре..................................................................... 540
19.2.4. Удаление службы из реестра....................................................................... 545
19.3. Служба JAXM поставщика..................................................................................... 547
19.3.1. Клиент JAXM.................................................................................................. 548
19.3.1.1. Отправка зароса................................................................................... 549
19.3.1.2. Извлечение прайс-листа...................................................................... 550
19.3.1.3. Заказ кофе.............................................................................................552
19.3.1.3.1. Создание заказа.......................................................................... 552
19.3.1.3.2. Извлечение подтверждения заказа............................................556
19.3.2. Служба JAXM................................................................................................. 556
19.3.2.1. Возвращение прайс-листа................................................................... 557
19.3.2.2. Возвращение подтверждения заказа..................................................562
19.4. Сервер Coffee Break...............................................................................................564
19.4.1. JSP-страницы.................................................................................................565
19.4.1.1. orderForm...............................................................................................565
19.4.1.2. checkoutForm.........................................................................................565
19.4.1.3. checkoutAck........................................................................................... 565
19.4.2. JavaBean-компоненты................................................................................... 565
19.4.2.1. RetailPriceList.........................................................................................565
19.4.2.1.1. Обнаружение службы JAX-RPC................................................. 565
19.4.2.2. ShoppingCartItem...................................................................................566
19.4.2.3. OrderConfirmation.................................................................................. 566
19.4.2.4. CheckoutFormBean................................................................................566
19.4.3. RetailPriceListServlet...................................................................................... 567
19.5. Построение, установка и исполнение приложения............................................. 567

Web-

Rendered by www.RenderX.com
22

19.5.1. Построение общих классов.......................................................................... 568


19.5.2. Построение и установка службы JAX-RPC..................................................568
19.5.3. Построение и установка службы JAXM....................................................... 569
19.5.4. Построение и установка сервера Coffee Break........................................... 569
19.5.5. Запуск клиента Coffee Break.........................................................................570
19.5.6. Размещение приложения Coffee Break........................................................572

20. Утилита администрирования Tomcat...................................................................... 572


20.1. Запуск admintool..................................................................................................... 573
20.2. Настройка Tomcat...................................................................................................575
20.2.1. Настройка свойств сервера.......................................................................... 576
20.3. Настройка элементов Service................................................................................576
20.3.1. Настройка элементов Connector.................................................................. 577
20.3.1.1. Типы элементов Connector.................................................................. 578
20.3.1.2. Аттрибуты элемента Connector........................................................... 578
20.3.2. Настройка элементов Host........................................................................... 580
20.3.2.1. Атрибуты элемента Host...................................................................... 581
20.3.2.2. Альтернативные имена хоста..............................................................581
20.3.2.3. Настройка элементов Context..............................................................582
20.3.2.3.1. Атрибуты элемента Context ....................................................... 583
20.3.3. Настройка элементов Logger........................................................................585
20.3.3.1. Атрибуты элемента Logger.................................................................. 586
20.3.4. Настройка элементов Realm........................................................................ 587
20.3.4.1. Атрибуты JDBCRealm...........................................................................589
20.3.4.2. Атрибуты JNDIRealm............................................................................ 590
20.3.4.2.1. Определение атрибутов Realm в файле Server.xml................. 593
20.3.4.3. Атрибуты UserDatabaseRealm............................................................. 594
20.3.4.4. Атрибуты MemoryRealm....................................................................... 594
20.3.5. Настройка элементов Valve..........................................................................594
20.3.5.1. Атрибуты элемента Valve.................................................................... 595
20.3.5.1.1. Атрибуты AccessLogValve........................................................... 595
20.3.5.1.2. Значения для атрибута Pattern...................................................596
20.3.5.1.3. Атрибуты RemoteAddrValve........................................................ 597
20.3.5.1.4. Атрибуты RemoteHostValve.........................................................597
20.3.5.1.5. Атрбуты SingleSignOn..................................................................598
20.4. Настройка элемента Resources............................................................................ 598
20.4.1. Атрибуты элемента Data Source.................................................................. 601
20.4.2. Атрибуты элемента Environment Entries......................................................602
20.5. Администрирование ролей, групп и пользователей............................................603
20.6. Дополнительная информация...............................................................................603

21. Менеджер Web-приложений Tomcat (Tomсat Web Application Manager)..............604


21.1. Запуск менеджера Web-приложений.................................................................... 604
21.2. Исполнение команд менеджера с использованием задач Ant........................... 605

Web-

Rendered by www.RenderX.com
23

22. Сервер реестра Java WSDP.................................................................................... 606


22.1. Установка сервера реестра................................................................................... 606
22.2. Использование JAXR API для получения доступа к серверу реестра...............607
22.3. Использование клиентского сценария командной строки с сервером
реестра.............................................................................................................................608
22.3.1. Получение аутентификации......................................................................... 609
22.3.2. Сохранение бизнеса......................................................................................610
22.3.3. Поиск бизнеса................................................................................................ 610
22.3.4. Получение деталей бизнеса.........................................................................611
22.3.5. Удаление бизнеса......................................................................................... 611
22.3.6. Проверка UDDI-сообщений...........................................................................612
22.3.7. Извлечение бизнеса пользователя..............................................................612
22.3.8. Отправка сообщений UDDI-запроса............................................................ 613
22.4. Использование утилиты Indri для получения доступа к базе данных сервера
реестра.............................................................................................................................613
22.4.1. Сохранение бизнеса......................................................................................614
22.4.2. Получение деталей бизнеса.........................................................................614
22.4.3. Поиск бизнеса................................................................................................ 614
22.4.4. Удаление бизнеса......................................................................................... 615
22.4.5. Отображение содержимого базы данных....................................................615
22.5. Добавление в реестр новых пользователей........................................................ 615
22.6. Дополнительная информация...............................................................................616

23. Броузер реестра....................................................................................................... 617


23.1. Запуск броузера..................................................................................................... 617
23.2. Опрос реестра........................................................................................................ 618
23.2.1. Запрос по имени............................................................................................ 618
23.2.2. Запрос по классификации.............................................................................619
23.3. Управление данными реестра.............................................................................. 619
23.3.1. Добавление организации.............................................................................. 619
23.3.2. Добавление информации о службах организации..................................... 620
23.3.3. Добавление привязок к заданной службе................................................... 620
23.3.4. Добавление и удаление классификаций..................................................... 621
23.3.5. Подтверждение введенных данных............................................................. 621
23.4. Удаление организации...........................................................................................622
23.5. Завершение работы броузера...............................................................................622
23.6. Использование броузера реестра JAXR совместно с сервером реестра......... 622
23.6.1. Добавление и удаление организаций.......................................................... 622
23.6.2. Опрос реестра............................................................................................... 622

24. Утилита администрирования поставщика (Provider Administration Tool)..............623


25. Схемы кодировок Java............................................................................................. 624

Web-

Rendered by www.RenderX.com
24

25.1. Схемы кодировок Java........................................................................................... 624


25.1.1. US-ASCII.........................................................................................................624
25.1.2. ISO-8859-1......................................................................................................624
25.1.3. UTF-8.............................................................................................................. 624
25.1.4. UTF-16............................................................................................................ 624
25.2. Дополнительная информация...............................................................................624

26. Обзор HTTP...............................................................................................................625


26.1. Запросы HTTP........................................................................................................ 625
26.2. Ответы HTTP.......................................................................................................... 625

Web-

Rendered by www.RenderX.com
Для кого предназначено руководство Стр. 1 из 626

1. Об этом руководстве
1.1. Для кого предназначено руководство
Данное руководство предназначено для програмистов, интересующихся разработкой и
размещением Web-служб и Web-приложений с использованием Java WSDP.

1.2. Как читать это руководство


Данное руководство состоит из пяти частей:
• Введение
Первые пять глав знакомят с основными понятиями и технологиями. Мы рекомендуем
вам прочитать их перед всеми остальными частями руководства. В частности, многие
примеры Java WSDP используют Java-сервлет Tomcat и JSP-контейнер, а глава "Начало
работы с Tomcat" описывает как запустить, остановить и управлять Tomcat.
• Технология Java XML
В этих главах рассматриваются все Java XML API.
- Java API для обработки XML (JAXP)
- Java API для системы обмена сообщениями XML (JAXM) и Soap with Attachments API
для Java (SAAJ)
- Java API для основанных на XML RPC (JAX-RPC)
- Java API для XML Registries (JAXR) и Registry Server - UDDI-совместимый реестр,
доступный через JAXR
• Web-технология
В этих главах рассматриваются технологии, использующиеся при разработке Web-
приложений, ориентированных на представление информации различного типа.
- Сервлеты Java
- JavaServer Pages
- Пользовательские теги и JSP Standard Tag Library (JSTL)
• Реальный пример
Глава "Приложение Coffee Break" в этом разделе описывает приложение, использующее
большинство из API, рассмотренных в данном руководстве.
• Приложения
В приложениях рассмотрены программные средства, поставляемые вместе с Java
WSDP.
- Программа администрирования сервера Tomcat
- Менеджер Web-приложений Tomcat
- JAXM Provider Admin
- xprcc

Web-

Rendered by www.RenderX.com
Стр. 2 из 626 Об этом руководстве

- Registry Browser
В этой части приведены также схемы кодирования HTTP и Java.

1.3. О примерах
1.3.1. Предварительные требования
Для понимания примеров вы должны хорошо знать язык программирования Java, SQL и
основы реляционных баз данных. Темы, перечисленные в таблице P-1 "Руководства по
Java™" особенно важны:
Таблица P-1. Важные темы в "Руководстве по Java™"
Тема Web-страница
JDBC™ http://java.sun.com/docs/books/tutorial/jdbc
Потоки http://java.sun.com/docs/books/tutorial/essential/threads
JavaBeans™ http://java.sun.com/docs/books/tutorial/javabeans
Безопасность http://java.sun.com/docs/books/tutorial/security1.2

1.3.2. Запуск примеров


В этом разделе рассматривается все, что нужно знать для получения, построения, установки
и запуска примеров.

1.3.2.1. Требуемое программное обеспечение


Если вы просматриваете данное описание в интернете, вам необходимо загрузить
"Руководство по Web-службам Java™" с
http://java.sun.com/webservices/downloads/webservicestutorial.html
После установки пакета с руководством исходные коды примеров находятся в каталоге
JWSDP_HOME/docs/tutorial/examples, в котором расположены подкаталоги для каждой из
технологий, включенных в пакет.
Это руководство описывает Java WSDP 1.0_01. Для построения, размещения и запуска
примеров вам необходимы копии Java WSDP и Java™ 2 Platform, Standard Edition (J2SE™)
SDK 1.3.1 или 1.4. Java WSDP можно загрузить с
http://java.sun.com/webservices/downloads/webservicespack.html
J2SE 1.3.1 SDK можно загрузить с
http://java.sun.com/j2se/1.3/
J2SE 1.4 SDK можно загрузить с
http://java.sun.com/j2se/1.4/
Добавьте каталоги bin установленных Java WSDP и J2SE SDK в начало переменной
окружения PATH, для того чтобы начальные сценарии Java WSDP для Tomcat, Ant,
deploytool, сервера реестра и других программ заменили сценарии из других инсталляций.

Web-

Rendered by www.RenderX.com
Как распечатать это руководство Стр. 3 из 626

1.3.2.2. Построение примеров


Большинство из примеров поставляются с файлом конфигурации для Ant версии 1.4.1,
переносимого средства построения, входящего в Java WSDP. В каждой главе приводятся
рекомендации для построения примеров.

1.3.2.3. Настройка примеров


Большинство из примеров Java WSDP используют Java-сервлет Tomcat и JSP-контейнер.
Для установки, регистрации, перезагрузки и удаления Web-приложений используется
программа manager. Информация по этой программе находится в Приложении В.

1.4. Как распечатать это руководство


Для распечатки данного руководства выполните следующие действия:
1. Убедитесь, что у вас установлен Adobe Acrobat Reader.
2. Откройте PDF-версию этой книги.
3. Щелкните на иконке с принтером в Adobe Acrobat Reader.

1.5. Типографские соглашения


В Таблице Р-2 перечислены типографские соглашения, принятые в данном руководстве.
Таблица Р-2 Типографские соглашения
Стиль шрифта Использование
жирный Выделения, заголовки, первое упоминание терминов
URL, исходные коды примеров, имена файлов, названия
команд, ключевые слова языка программирования
моноширинный Различные имена файлов

Выбор меню обозначается при помощи символа правой стрелки ->, например, First->Second
следует интерпретировать следующим образом: выберите меню First, затем подменю
Second из меню First.

2. Введение в Web-службы
Web-службы, в общем смысле, представляют собой службы, предлагаемые в Web. В
традиционном сценарии Web-служб бизнес-приложение передает запрос в службу по
определенному URL, используя протокол SOAP по HTTP. Служба принимает запрос,
обрабатывает его и возвращает ответ. Часто приводимым примером Web-службы является
служба котировок акций, в которой запрашивается текущая цена определенной акции.
Цена возвращается в ответе. Это одна из простейших форм Web-службы, в которой ответ
формируется практически сразу, запрос и ответ являются частями одного и того же вызова
метода.
Другим примером может являться служба, определяющая эффективный маршрут доставки
товаров. В этом случае передается запрос, указывающий пункт назначения, а процессы
службы определяют наиболее эффективный маршрут доставки. Время передачи ответа

Web-

Rendered by www.RenderX.com
Стр. 4 из 626 Введение в Web-службы

зависит от сложности маршрутов, то есть ответ может быть передан в виде отдельной от
запроса операции.
Web-службы и потребители Web-служб обычно являются бизнес-процессами,
предназначенными преимущественно для так называемых business-to-business (B-to-B)
транзакций. Предприятие может как предоставлять Web-службы, так и являться
потребителем других Web-служб. Например, оптовый торговец специями может выступать
в роли потребителя при использовании Web-службы для проверки доступности ванильных
зерен, а также в роли поставщика Web-службы во время предложения предполагаемым
потребителям различных цен на зерна от разных поставщиков.

2.1. Значение XML и платформы Java™


Web-службы зависят от способности участников взаимодействовать друг с другом даже
при использовании ими различных информационных систем. XML (Extensible Markup
Language), язык разметки, делающий данные переносимыми, является ключевой
технологией, предназначенной для обеспечения такой способности. Корпоративные
пользователи увидели преимущества использования XML для интеграции данных как для
совместного использования существующих данных между подразделениями, так и для
использования их совместно с другими предприятиями. В результате XML все больше
используется в корпоративных интегрированных приложениях, как в сильносвязанных, так
и в слабосвязанных системах. Из-за такой способности к интеграции данных XML стал
фундаментом Web-вычислений.
Web-службы зависят также от способности предприятий использовать различные
вычислительные платформы для взаимодействия друг с другом. Это требование делает
платформу Java™, программы в которой являются переносимыми, естественным выбором
для разработки Web-служб. Этот выбор стал еще более привлекательным после появления
новых Java API для XML, что сделало более легким использование XML в языке
программирования Java. Общая информация по этим API приводится в этом введении
далее, а более детально каждый API рассматривается в соответствующем руководстве.
Кроме переносимости кода и данных Web-службы должны быть масштабируемыми,
безопасными и эффективными. Java™ 2 Platform, Enterprise Edition (J2EE™), специально
разработана для удовлетворения этих потребностей. Она облегчает в действительности
трудную часть разработки Web-служб, а именно программирование инфраструктуры. Эта
инфраструктура включает в себя такие функции как безопасность, управление
распределенными транзакциями и управление пулом соединений, которые имеют
важнейшее значение для производительности Web-служб. А поскольку компоненты
являются повторно используемыми, время разработки существенно уменьшается.
Поскольку XML и платформа Java хорошо работают вместе, они стали играть центральную
роль в Web-службах. Фактически, преимущества, предлагаемые Java API для XML и
платформой J2EE, делают их идеальной комбинацией для размещения Web-служб.
Описанные в этом руководстве API дополняют и располагаются на верхнем уровне J2EE
API. Эти API дают возможность сообществу Java, разработчикам и поставщикам сервисных
программ и контейнеров начать разработку приложений Web-служб и использование
стандартных Java API, составляющих основу принципа технологии Java - Write Once, Run
Anywhere™ (пишется один раз, используется везде). Java Web Services Developer Pack
(Java WSDP) собирает все эти API в один пакет. В Java WSDP входят jar-файлы,

Web-

Rendered by www.RenderX.com
Что такое XML? Стр. 5 из 626

реализующие эти API, а также документация и примеры. Примеры в Java WSDP должны
запускаться в контейнере Tomcat (входящим в пакет Java WSDP), или в J2EE-контейнере
после установки jar-файлов Java WSDP в J2EE SDK. Рекомендации по установка jar-файлов
в J2EE SDK находятся в документации по Java WSDP в каталоге
<JWSDP_HOME>/docs/jwsdponj2ee.html.
В оставшейся части введения дается краткий обзор XML и объясняется, каким образом
эта технология обеспечивает переносимость данных. Затем приводится обзор Java API
для XML, поясняющий, что делают эти API и то, как они облегчают создание Web-
приложений. Каждый API описывается отдельно и затем приводится сценарий, который
демонстрирует их совместную работу.
Последующие руководства дают более детальную информацию и постепенно учат вас
использованию Java API для XML при создании приложений для Web-служб. В них
приводятся также примеры приложений, которые вы можете выполнять.

2.2. Что такое XML?


В этой главе приведено краткое введение в XML и объясняется, каким образом эта
технология обеспечивает переносимость данных. Другими словами, здесь дается основа
для чтения приведенных ниже описаний Java API для XML. В главе 1 дано более полное
и детальное описание XML и методов работы с ним.
XML является отраслевым стандартом системно-независимого способа представления
данных. Подобно HTML (HyperText Markup Language) XML заключает данные в теги, но
между этими двумя языками разметки есть существенные различия. Во-первых, XML-теги
связаны со значением заключенного в них текста, в то время как HTML-теги указывают
лишь способ отображения текста. Следующий пример XML представляет собой прайс-
лист с названием и ценой двух сортов кофе.

<priceList>
<coffee>
<name>Mocha Java</name>
<price>11.95</price>
</coffee>
<coffee>
<name>Sumatra</name>
<price>12.50</price>
</coffee>
</priceList>
Теги <coffee> и </coffee> указывают синтаксическому анализатору, что информация между
ними относится к кофе. Два других тега внутри тегов <coffee> указывают, что заключенная
в них информация является названием кофе и его ценой. Поскольку XML-теги указывают
на структуру и содержимое данных, они дают возможность производить такие операции,
как архивирование и поиск.
Вторым основным отличием между XML и HTML является расширяемость XML. При помощи
XML вы можете определять свои собственные теги для описания содержимого конкретного

Web-

Rendered by www.RenderX.com
Стр. 6 из 626 Введение в Web-службы

типа документа. При использовании HTML вы ограничены только теми тегами, которые
определены в спецификации HTML. Вторым аспектом расширяемости XML является
возможность создания файла, называемого схемой и описывающего структуру конкретного
типа XML-документа. Например, можно написать схему для прайс-листа, указывающую,
какие теги могут быть использованы и где они могут находиться. Любой XML-документ
следующий ограничениям, установленным в схеме, считается соответствующим этой
схеме.
Наверное наиболее широко используемый язык схем - это Document Type Definition (DTD),
поскольку он является одной из составных частей спецификации XML 1.0. Написанная на
этом языке схема обычно называется DTD. Приведенная ниже DTD определяет теги,
используемые в XML-документе - прайс-лист. В ней определяются четыре тега (элемента)
и указывается, какие теги могут (или должны) использоваться внутри других тегов. В DTD
также определяется иерархическая структура XML-документа, в том числе и порядок
написания тегов.

<!ELEMENT priceList (coffee)+>


<!ELEMENT coffee (name, price) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT price (#PCDATA) >
В первой строке примера определяется элемент верхнего уровня - priceList, это значит,
что все остальные теги в документе будут находиться между тегами <priceList> и </priceList>.
Первая строка указывает также на то, что элемент priceList должен содержать один или
более элементов coffee (это указано знаком плюс). Во второй строке указывается, что все
элементы coffee должны содержать элемент name и элемент price в данном порядке. В
третьей и четвертой строке определяется, что данные между тегами <name> и </name> и
между <price> и </price> представляют собой символьные данные. Имя и цена каждого
сорта кофе представляют собой конкретный текст, формирующий прайс-лист.
Другим популярным языком схем является XML Schema, разработанный консорциумом
World Wide Web (W3C). Язык XML Schema значительно мощнее DTD и после его принятия
в W3C Recomendation в мае 2001 года его использование и количество реализаций стало
увеличиваться. Сообщество разработчиков, использующих платформу Java, заметило эту
тенденцию и группа экспертов по Java™ API for XML Processing (JAXP) начала работу над
добавлением поддержки XML Schema в спецификацию JAXP 1.2. Текущая реализация
Java™ Web Services developer Pack включает поддержку XML Schema.

2.2.1. Что обеспечивает переносимость XML?


Переносимость XML-данных обеспечивает схема. DTD priceList, рассмотренная ранее,
является простым примером схемы. Когда приложению передается документ priceList в
формате XML и имеется DTD priceList, оно может обработать документ в соответствии с
правилами, указанными в DTD. Например, имея DTD priceList, синтаксический анализатор
знает структуру и тип содержимого любого XML-документа, сформированного согласно
этой DTD. Если синтаксический анализатор (парсер) является верифицирующим, он знает,
что документ не корректен, если документ содержит не включенные в DTD элементы,
например, элемент <tea>, или если элементы не расположены в определенном порядке,
например, элемент price предшествует элементу name.

Web-

Rendered by www.RenderX.com
Обзор Java API для XML Стр. 7 из 626

Другие особенности делают свой вклад в популярность XML как метода обмена данными.
Одна из них - текстовый формат данных, который легко читается и человеком и текстовыми
редакторами. Приложения могут анализировать и обрабатывать XML-документы, а при
возникновении ошибок при обработке человек может сам прочитать их. Другая особенность
- поскольку XML-документы не содержат инструкций форматирования, они могут быть
отображены различными способами. Хранение данных отдельно от инструкций
форматирования означает, что одни и те же данные могут быть представлены на различных
носителях информации.
XML обеспечивает переносимость документов, но он не может работать в вакууме, то есть,
использующие XML стороны должны согласиться с определенными условиями. Например,
вместе с договоренностью об использовании XML для обмена информацией, два
приложения должны согласовать набор используемых элементов и их значения. При
использовании ими Web-служб, необходимо также согласовать, какие методы Web-служб
будут использоваться, что эти методы будут делать и порядок их вызова в случае
необходимости вызова более одного метода.
Для удовлетворения этих требований предприятиям доступны несколько технологий. Они
могут использовать схемы DTD и XML Schema для описания корректных терминов и XML-
документов, которые будут использоваться при взаимодействии. Средство описания Web-
служб и их методов предоставляют реестры. На более высоком уровне абстракции
предприятия могут использовать партнерские соглашения и схемы рабочих процессов.
Более подробно схемы и реестры рассмотрены ниже.

2.3. Обзор Java API для XML


Java API для XML дают вам возможность писать Web-приложения полностью на языке
программирования Java. Они подразделяются на две большие категории: связанные
непосредственно с обработкой XML-документов и связанные с процедурами.
• Документо-ориентированные
- Java™ API for XML Processing (JAXP) - обрабатывает XML-документы, используя
различные синтаксические анализаторы
• Процедурно-ориентированные
- Java™ API for XML-based RPC (JAX-RPV) - передает вызовы SOAP-методов
удаленным участникам по сети Интернет и получает ответы.
- Java™ API for XML Messaging (JAXM) - передает SOAP-сообщения по сети Интернет
стандартным способом
- Java™ API for XML Registries (JAXR) - предоставляет стандартный способ доступа
к бизнес-реестрам и общей информации
Возможно, самой важной особенностью Java API для XML является поддержка ими
отраслевых стандартов, что гарантирует возможность взаимодействия. Различные группы
по стандартам сетевого взаимодействия, такие как World Wide Web Consortium (W3C) и
Organization for the Advancement of Structured Information Standards (OASIS) (организация
по улучшению стандартов структурированной информации), определили стандартные
способы работы, следуя которым можно организовать совместную работу приложений и
данных.

Web-

Rendered by www.RenderX.com
Стр. 8 из 626 Введение в Web-службы

Еще одной особенностью Java API для XML является их большая гибкость. Для
пользователей - это способы использования API. Например, JAXR-код может использовать
различные средства для обработки XML-документа, а JAXM-код может использовать
различные протоколы обмена сообщениями на верхнем уровне SOAP. Разработчикам
также доступна эта гибкость. Java API для XML определяют жесткие требования по
совместимости для гарантии того, что все реализации предоставляют стандартную
функциональность, но эти API, в то же время, дают разработчикам большую степень
свободы в предоставлении реализаций, адаптированных для конкретных задач.
В следующих главах обсуждаются каждый из этих API.

2.4. JAXP
Java API for XML Processing (JAXP) упрощает обработку XML-данных в приложениях,
написанных на языке программирования Java. JAXP использует особенности стандартов
SAX (Simple API for XML Parsing) и DOM (Document Object Model), то есть вы можете выбрать
между синтаксическим анализом ваших данных как потока событий, или построить
древовидную структуру их представления. Последние версии JAXP поддерживают также
стандарт CSLT (XML Stylesheet Language Transformations), который предоставляет контроль
над способом представления данных и дает возможность преобразования данных в другие
XML-документы или в другие форматы, например HTML. JAXP обеспечивает также
поддержку пространства имен, разрешая работу со схемами, которые могли бы в противном
случае вызвать конфликт имен.
JAXP дает возможность использовать любой XML-совместимый анализатор в вашем
приложении. Это обеспечивается так называемым уровнем подключаемых модулей,
который позволяет вам подключить реализацию SAX или DOM API. Этот уровень позволяет
также подключить XSL-процессор, который может преобразовывать ваши XML-данные
различными способами, в том числе и их внешнее представление.
Последней версией JAXP является JAXP 1.2, в которую добавлена поддержка XML Schema.
Начальная версия JAXP 1.2 включена в данную редакцию Java WSDP и доступна также в
пакете Java XML Pack.

2.4.1. SAX API


Simple API for XML (SAX) определяет API для анализатора, основанного на событиях.
Анализатор такого типа читает XML-документ от начала до конца и каждый раз, когда он
распознает синтаксическую конструкцию, он уведомляет приложение, которое его
использует. SAX-анализатор уведомляет приложение при помощи вызова методов
интерфейса ContentHandler. Например, когда анализатор встречает знак "меньше чем"
(<), он вызывает метод startElement; когда он встречает символьные данные, он вызывает
метод characters; когда встречается знак "меньше чем" со знаком деления (</), вызывается
метод endElement и т.д. Для иллюстрации вышесказанного рассмотрим часть примера
XML-документа из предыдущей главы и опишем, что делает анализатор для каждой строки.
(Для простоты вызовы метода ignorableWhiteSpace не показаны.)

<priceList> [ startElement]
<coffee> [ startElement]

Web-

Rendered by www.RenderX.com
JAXP Стр. 9 из 626

<name>Mocha Java</name> [
startElement,
characters, endElement]
<price>11.95</price> [
startElement,
characters, endElement]
</coffee> [ endElement]
Реализации вызываемых анализатором методов по умолчанию не делают ничего, то есть
вы должны написать подкласс, реализующий соответствующие методы для получения
желаемой функциональности. Например, предположим, что вам нужно получить цену
фунта кофе сорта Mocha Java. Вы должны написать класс, расширяющий DefaultHandler
(реализация ContentHandler по умолчанию), в котором нужно написать ваши собственные
реализации методов startElement и characters.
Прежде всего, необходимо создать объект SAXParser из объекта SAXParserFactory. Вы
будете вызывать его метод parse, передавая прайс-лист и экземпляр вашего нового класса
(с новыми реализациями методов startElement и characters). В данном примере прайс-лист
- это файл, хотя метод parse может также принимать и другие источники входных данных,
включая объект InputStream, URL и объект InputSource.

SAXParserFactory factory = SAXParserFactory.newInstance();


SAXParser saxParser = factory.newSAXParser();
saxParser.parse("priceList.xml", handler);
Результат вызова метода parse зависит прежде всего от того, как реализованы методы в
handler. SAX-анализатор проходит по файлу priceList.xml строка за строкой, вызывая
соответствующие методы. Кроме упомянутых выше методов анализатор вызывает и другие
методы, такие как startDocument, endDocument, ignorableWhiteSpace и procesingInstructions,
но эти методы имеют реализации по умолчанию и ничего не делают.
Приведенные ниже определения методов показывают один из способов реализации
методов characters и startElement для поиска и отображения цены сорта Mocha Java. Из-
за особенностей работы SAX-анализатора эти два метода работают совместно,
осуществляя поиск элемента name, символов "Mocha Java" и элемента price, следующего
сразу после Mocha Java. Эти методы используют три флага для отслеживания того, какие
условия были обнаружены. Обратите внимание, что SAX-анализатор должен будет вызвать
оба метода более одного раза, прежде чем можно будет распечатать цену.

public void startElement(..., String elementName, ...){


if(elementName.equals("name")){
inName = true;
} else if(elementName.equals("price") && inMochaJava ){
inPrice = true;
inName = false;
}

Web-

Rendered by www.RenderX.com
Стр. 10 из 626 Введение в Web-службы

public void characters(char [] buf, int offset, int len) {


String s = new String(buf, offset, len);
if (inName && s.equals("Mocha Java")) {
inMochaJava = true;
inName = false;
} else if (inPrice) {
System.out.println("The price of Mocha Java is: " + s);
inMochaJava = false;
inPrice = false;
}
}
}
При обнаружении анализатором элемента coffee Mocha Java приведенные ниже основные
состояния будут возникать после вызова следующих методов:

startElement -- inName true


characters -- inMochaJava true

startElement -- inPrice true


characters -
SAX-анализатор может выполнять контроль во время анализа XML-данных, что означает
проверку соответствия данных правилам, указанным в схеме XML-документа. SAX-
анализатор будет осуществлять верификацию, если он создан объектом SAXParserFactory,
в котором такая верификация включен. Включение верификации для объекта SAXParser-
Factory factory производится следующим образом:

factory.setValidating(true);
Для того чтобы анализатор знал, какую схему использовать для верификации, XML-документ
должен содержать ссылку на схему в своем объявлении DOCTYPE. Схемой для прайс-
листа является priceList.DTD, то есть, объявление DOCTYPE должно быть примерно таким:

<!DOCTYPE PriceList SYSTEM "priceList.DTD">

2.4.2. DOM API


Document Object Model (DOM), разработанная рабочей группой W3C DOM, представляет
собой набор интерфейсов для построения представления объектов анализируемого XML-
документа в древовидной форме. После построения DOM вы можете манипулировать
документом при помощи методов DOM, например, insert и remove, также как и любым
другим объектом в древовидной структуре данных. Таким образом, в отличие от SAX-

Web-

Rendered by www.RenderX.com
JAXP Стр. 11 из 626

анализатора, DOM-анализатор предоставляет произвольный доступ к отдельным данным


в XML-документе. Еще одним отличием является то, что используя SAX-анализатор можно
только читать XML-документ, а при помощи DOM-анализатора можно сформировать
объектное представление документа и манипулировать им в памяти, добавляя новый
элемент или удаляя существующий.
В предыдущем примере мы использовали SAX-анализатор для поиска только одного
фрагмента данных в документе. Использование DOM-анализатора требует наличия полной
объектной модели документа в памяти, что обычно менее эффективно для поиска
небольшого количества элементов, особенно при большом размере документа. В
следующем примере мы добавим новый сорт кофе, используя DOM-анализатор. SAX-
анализатор использовать нельзя, так как он только читает данные.
Предположим, что вы хотите добавить кофе Kona в прайс-лист. Вы должны прочитать
XML-файл прайс-листа в DOM и затем вставить новый элемент coffee вместе с названием
и ценой. В следующем фрагменте кода создается объект DocumentBuilderFactory, который
затем используется для создания объекта DocumentBuilder builder. Затем вызывается
метод builder parse, которому передается файл priceList.xml.

DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("priceList.xml");
С этого момента document - это DOM-представление прайс-листа, расположенное в памяти.
В следующем фрагменте кода в прайс-лист добавляется новый сорт кофе (с названием
"Kona" и ценой 13.50). Поскольку мы хотим вставить новый сорт кофе перед сортом "Mocha
Java", первым шагом является получение списка элементов coffee и итерация по списку
для поиска "Mocha Java". При помощи интерфейса Node, включенного в пакет org.w3c.dom,
создается объект Node для нового элемента coffee и новые объекты для элементов name
и price. Элементы name и price содержат символьные данные, поэтому создаются объекты
Text для каждого из них, которые добавляются к объектам Node, представляющим элементы
name и price.

Node rootNode = document.getDocumentElement();


NodeList list = document.getElementsByTagName("coffee");

// .
for (int i=0; i < list.getLength(); i++) {
thisCoffeeNode = list.item(i);
Node thisNameNode = thisCoffeeNode.getFirstChild();
if (thisNameNode == null) continue;
if (thisNameNode.getFirstChild() == null) continue;
if (! thisNameNode.getFirstChild() instanceof
org.w3c.dom.Text) continue;

Web-

Rendered by www.RenderX.com
Стр. 12 из 626 Введение в Web-службы

String data = thisNameNode.getFirstChild().getNodeValue();


if (! data.equals("Mocha Java")) continue;

// Mocha Java.

// .

Node newCoffeeNode = document.createElement("coffee");

Node newNameNode = document.createElement("name");


Text tnNode = document.createTextNode("Kona");
newNameNode.appendChild(tnNode);

Node newPriceNode = document.createElement("price");


Text tpNode = document.createTextNode("13.50");
newPriceNode.appendChild(tpNode);

newCoffeeNode.appendChild(newNameNode);
newCoffeeNode.appendChild(newPriceNode);
rootNode.insertBefore(newCoffeeNode, thisCoffeeNode);
break;
}
Обратите внимание, что данный фрагмент кода является упрощенным, поскольку мы
предположили, что не встретим таких элементов как комментарий, атрибут или незначащий
пробел. Информация по более надежному использованию DOM-анализатора находится
в разделе "Повышение сложности".
Можно указать DOM-анализатору проверять документ, точно так же как и SAX-анализатору.
Перед созданием вашего DOM-анализатора нужно вызвать setValidating(true) и проверить,
что анализируемый XML-документ имеет ссылку на свою схему в объявлении DOCTYPE.

2.4.2.1. Пространства имен XML


Все имена в схеме, включая и имена в DTD, являются уникальными, что исключает
двусмысленность. Однако, если какой-либо XML-документ ссылается на несколько схем,
существует вероятность того, что две или более из этих схем содержат одно и то же имя.
Следовательно, документ должен указать пространство имен для каждой схемы, чтобы
анализатор знал, какое определение использовать во время анализа экземпляра конкретной
схемы.
Существует стандартная система обозначений для объявления пространства имен XML,
которая обычно располагается в корневом элементе XML-документа. В следующем
объявлении пространства имен обозначение xmlns указывает, что nsName объявляет
пространство имен, а nsName указывает URL фактического пространства имен:

Web-

Rendered by www.RenderX.com
JAXP Стр. 13 из 626

<priceList xmlns:nsName="myDTD.dtd"
xmlns:otherNsName="myOtherDTD.dtd">
...
</priceList>
Внутри документа можно указать, к какому пространству имен принадлежит элемент,
например:

<nsName:price> ...
Для того чтобы ваш SAX или DOM-анализатор был способен распознавать пространство
имен, нужно вызвать метод setNamespaceAware(true) вашего экземпляра ParserFactory.
После вызова этого метода любой создаваемый анализатор будет правильно обрабатывать
пространства имен.

2.4.3. XSLT API


XML Stylesheet Language for Transformations (XSLT), разработанный рабочей группой W3C
XSL, определяет язык для преобразования XML-документов в другие XML-документы или
в другие форматы. Для выполнения преобразования необходимо предоставить таблицу
стилей, которая записывается на языке XML Stylesheet Language (XSL). Таблица стилей
XSL определяет форму отображения XML-данных, а XSLT использует инструкции
форматирования таблицы стилей для выполнения преобразования.
Поддержка языка XSLT в JAXP реализована в пакете javax.xml.transform, который дает
возможность подключить XSLT-преобразователь для выполнения преобразования.
Субпакеты содержат SAX-, DOM- и потоковые API, которые позволяют выполнять
преобразования непосредственно из дерева DOM и событий SAX. Два приведенных ниже
примера демонстрируют создание XML-документа из дерева DOM и преобразование
полученного XML-документа в формат HTML при помощи таблицы стилей XSL.

2.4.3.1. Преобразование дерева DOM в XML-документ


Для преобразования созданного в предыдущей главе дерева DOM в XML-документ в
приведенном ниже фрагменте программы сначала создается объект Transformer, который
затем выполнит преобразование.

TransformerFactory transFactory =
TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
Используя корневой узел дерева DOM, следующая строка кода создает объект DOMSource,
являющийся источником преобразования.

DOMSource source = new DOMSource(document);


Следующий фрагмент программы создает объект StreamResult для получения результатов
преобразования и преобразует дерево в XML-файл.

Web-

Rendered by www.RenderX.com
Стр. 14 из 626 Введение в Web-службы

File newXML = new File("newXML.xml");


FileOutputStream os = new FileOutputStream(newXML);
StreamResult result = new StreamResult(os);
transformer.transform(source, result);

2.4.3.2. Преобразование XML-документа в HTML-документ


XSLT можно также использовать для преобразования нового XML-документа, newXML.xml,
в HTML, используя таблицу стилей. При создании таблицы стилей используйте пространство
имен XML для ссылки на XML-компоненты. Например, каждая таблица стилей содержит
корневой элемент, идентифицирующий язык таблицы стилей, как показано в следующей
строке кода.

<xsl:stylesheet version="1.0" xmlns:xsl=


"http://www.w3.org/1999/XSL/Transform">
При ссылке на конкретный компонент языка таблицы стилей используется префикс
пространства имен, после которого помещается двоеточие и название конкретного
компонента. Например, следующий фрагмент таблицы стилей указывает, что данные name
должны быть вставлены в строку HTML-таблицы.

<xsl:template match="name">
<tr><td>
<xsl:apply-templates/>
</td></tr>
</xsl:template>
В следующей таблице стилей указывается, что XML-данные преобразуются в HTML и
записи о сортах кофе вставляются в строку таблицы.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="priceList">
<html><head>Coffee Prices</head>
<body>
<table>
<xsl:apply-templates />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="name">
<tr><td>

Web-

Rendered by www.RenderX.com
JAX-RPC Стр. 15 из 626

<xsl:apply-templates />
</td></tr>
</xsl:template>
<xsl:template match="price">
<tr><td>
<xsl:apply-templates />
</td></tr>
</xsl:template>
</xsl:stylesheet>
Для выполнения преобразования необходимо получить XSLT-преобразователь и
использовать его для применения таблицы стилей к XML-данным. В следующем фрагменте
программы создается преобразователь путем создания экземпляра объекта Transformer-
Factory, чтения таблицы стилей и XML-файлов, создания файла для записи HTML и,
наконец, получения объекта Transformer transformer из объекта TransformerFactory tFactory.

TransformerFactory tFactory =
TransformerFactory.newInstance();
String stylesheet = "prices.xsl";
String sourceId = "newXML.xml";
File pricesHTML = new File("pricesHTML.html");
FileOutputStream os = new FileOutputStream(pricesHTML);
Transformer transformer =
tFactory.newTransformer(new StreamSource(stylesheet));
Преобразование завершается вызовом метода transform, в который передаются данные
и выходной поток.

transformer.transform(
new StreamSource(sourceId), new StreamResult(os));

2.5. JAX-RPC
Java API for XML-based RPC (JAX-RPC) - это Java API для разработки и использования
Web-служб.

2.5.1. Обзор JAX-RPC


Web-службы, основанные на RPC, представляют собой набор процедур, которые могут
быть вызваны удаленным клиентом по сети Интернет. Обычным примером Web-службы,
основанной на RPC, является служба биржевых котировок, которая принимает SOAP
(Simple Object Access Protocol) запрос о стоимости указанной акции и возвращает стоимость,
используя SOAP.
Примечание. Спецификация SOAP 1.1, доступная на http://www.w3.org/, определяет среду
для обмена XML-документами. В ней определяется, среди прочего, что необходимо и что

Web-

Rendered by www.RenderX.com
Стр. 16 из 626 Введение в Web-службы

не обязательно в SOAP-сообщении и как данные могут кодироваться и передаваться. JAX-


RPC и JAXM основаны на SOAP.
Web-служба, являющаяся серверным приложением, которое реализует доступные для
вызова клиентами процедуры, размещается в контейнере на стороне сервера. Контейнер
может быть контейнером сервлетов, таким как Tomcat, или контейнером Java™ 2 Platform,
Enterprise Edition(J2EE™), который основывается на технологии Enterprise JavaBeans™
(EJB™).
Web-служба может стать доступной для потенциальных клиентов после описания ее в
документе Web Services Description Language (WSDL). WSDL-описание представляет собой
XML-документ, в котором находится вся необходимая информация о Web-службе,
включающая ее название, операции, которые можно вызывать, параметры этих операций
и место, куда надо передавать запросы. Пользователь (Web-клиент) может использовать
WSDL-документ для изучения того, что предлагает служба и как получить к ней доступ.
Ниже рассматриваются способы использования разработчиком WSDL-документа для
создания Web-службы.

2.5.1.1. Способность к взаимодействию


Наверное, наиболее важным требованием к Web-службе является способность к
взаимодействию между клиентами и серверами. При помощи JAX-RPC клиентское
приложение, написанное на языке, отличном от Java, может получить доступ к Web-службе,
разработанной и размещенной на платформе Java. И наоборот, клиентское приложение,
написанное на языке программирования Java, может взаимодействовать со службой,
разработанной и размещенной при использовании какой-то другой платформы.
Наличие в JAX-RPC поддержки SOAP и WSDL обеспечивает его способность к
взаимодействию. SOAP определяет стандарты для системы обмена сообщениями XML и
для отображения типов данных, при использовании которых приложения могут
взаимодействовать друг с другом. JAX-RPC придерживается стандартов SOAP и,
фактически, основан на системе обмена сообщениями SOAP. То есть, удаленный вызов
процедур JAX-RPC реализован в виде SOAP-сообщений типа запрос-ответ.
Наличие в JAX-RPC поддержки WSDL также обеспечивает его способность к
взаимодействию. WSDL-описание, будучи XML-документом, описывающим Web-службу
стандартным способом, обеспечивает переносимость описания. WSDL-документы и их
использование будут рассмотрены немного позже.

2.5.1.2. Простота использования


Тот факт, что JAX-RPC основан на механизме удаленного вызова процедур (RPC), означает
выдающуюся дружественность для разработчика. RPC имеет сложную инфраструктуру,
но, к счастью, JAX-RPC делает детали внутренней реализации незаметными ни для клиента,
ни для разработчика службы. Например, клиент Web-служб просто вызывает Java-метод,
а маршализация, демаршализация и передача происходят автоматически. На стороне
сервера Web-служба просто реализует предлагаемые клиентам службы и, также как клиент,
не беспокоится о механизмах внутренней реализации.
В основном благодаря простоте использования JAX-RPC является основным API Web-
служб как для клиентских, так и для серверных приложений. JAX-RPC использует главным
образом систему обмена сообщениями SOAP типа точка-точка, основной механизм,
используемый большинством клиентов и Web-служб. JAX-RPC концентрирует внимание

Web-

Rendered by www.RenderX.com
JAX-RPC Стр. 17 из 626

на простоте использования для наиболее общих задач, хотя он может предоставить


асинхронный обмен сообщениями и может быть расширен для обеспечения поддержки
высококачественного обмена. То есть, JAX-RPC - это хороший выбор для тех приложений,
в которых желательно избежать более сложных аспектов системы обмена сообщениями
SOAP, а также для тех, для которых хорошо подходит модель взаимодействия RPC. Более
мощная альтернатива системе обмена сообщениями SOAP - Java™™ API for XML
Messaging (JAXM) - рассматривается ниже.

2.5.1.3. Дополнительные функции


Хотя JAX-RPC основывается на модели RPC, он предлагает функции, выходящие за рамки
RPC. Одной из них является возможность передачи документа полностью, а также его
фрагментов. Кроме того, JAX-RPC поддерживает обработчики системы обмена
сообщениями SOAP, что предоставляет возможность передавать большое разнообразие
типов сообщений. JAX-RPC может быть расширен для одностороннего обмена сообщениями
в дополнение к способу запрос-ответ, обычно используемому в RPC. Еще одной
дополнительной функцией является гибкое отображение типов, что дает JAX-RPC еще
большую универсальность.

2.5.2. Использование JAX-RPC


Рассмотрим стандартный случай. Пользователь может, например, нуждаться в заказе
частей и товаров. Можно самыми разными методами обнаружить их потенциальные
источники, но удобным способом является поиск в бизнес-реестре и службе архивов, таких
как реестр Universal Description, Discovery and Integration (UDDI). Обратите внимание, что
Java API for XML Registries (JAXR), рассматриваемый далее, предлагает легкий метод
поиска Web-служб в бизнес-реестре и архиве. Web-службы обычно регистрируют себя в
бизнес-реестре и сохраняют связанные документы, включая WSDL-описания, в его архиве.
После поиска в бизнес-реестре потенциального источников можно получить несколько
WSDL-документов, по одному для каждой Web-службы, удовлетворяющей критерию поиска.
Бизнес-клиент может использовать WSDL-документы для просмотра того, что предлагают
службы и как с ними связаться.
Еще одной важной областью применения WSDL-документа является его использование
в качестве основы для создания заглушек - низкоуровневых классов, необходимых клиентам
для взаимодействия с удаленной службой. В JAX-RPC RI (reference implementation)
программа, использующая WSDL-документ для генерации заглушек, называется wscompile.
В RI имеется еще одна программа, называемая wsdeploy, которая создает узлы -
низкоуровневые классы, необходимые серверу для взаимодействия с удаленным клиентом.
Заглушки и узлы, следовательно, выполняют аналогичные функции: заглушки - на
клиентском компьютере, а узлы - на сервере. Кроме генерирования заглушек wsdeploy
может использоваться для создания WSDL-документов.
Исполняющая система JAX-RPC, например, входящая в JAX-RPC RI, использует заглушки
и узлы, созданные при помощи wscompile и wsdeploy, неявным образом. Сначала она
преобразует клиентский вызов удаленной процедуры в SOAP-сообщение и передает его
службе в виде HTTP-запроса. На стороне сервера исполняющая система JAX-RPC
принимает запрос, преобразует SOAP-сообщение в вызов метода и вызывает его. После
обработки запроса Web-службой исполняющая система выполняет похожий набор действий
для возврата результата клиенту. Помните, что как бы ни были сложны детали реализации

Web-

Rendered by www.RenderX.com
Стр. 18 из 626 Введение в Web-службы

взаимодействия между клиентом и сервером, они не видимы ни для Web-служб, ни для


их клиентов.

2.5.3. Создание Web-службы


Разработка Web-службы с использованием JAX-RPC является неожиданно простым
процессом. Служба сама по себе - это по существу два файла: интерфейс, объявляющий
удаленные процедуры службы, и класс, реализующий эти процедуры. Кроме этого,
необходимы еще настройка службы и размещение, но, прежде всего, давайте рассмотрим
два главных компонента Web-службы: определение интерфейса и класс реализации.
Следующее определение интерфейса является простым примером, показывающим методы,
которые оптовый продавец кофе возможно бы захотел сделать доступными для своих
вероятных покупателей. Обратите внимание, что интерфейс определения службы
расширяет java.rmi.Remote, а его методы генерируют объект java.rmi.RemoteException.

package coffees;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CoffeeOrderIF extends Remote {


public Coffee [] getPriceList()
throws RemoteException;
public String orderCoffee(String coffeeName, int quantity)
throws RemoteException;
}
Метод getPriceList возвращает массив объектов Coffee, каждый из которых содержит поля
name и price. Существует один объект Coffee для каждого сорта кофе, имеющегося в
наличии у продавца. Метод orderCoffee возвращает String, который должен соответствовать
заказу или указывать, что он является возвратом заказа.
В следующем примере показано, как может выглядеть эта реализация (детали реализации
опущены). Вероятно, метод getPriceList будет посылать запрос к базе данных компании
для получения текущей информации и возвращать результат в виде объектов Coffee.
Второй метод, orderCoffee, также должен обращаться к базе данных для проверки наличия
указанного в заказе количества кофе. Если такое количество есть, реализация запустит
внутренний процесс выполнения заказа и пошлет клиенту ответ, подтверждающий принятие
заказа. Если заказанного количества нет, реализация может сформировать свой
собственный заказ на пополнение запасов и проинформирует клиента о том, что его заказ
отложен.

package coffees;

public class CoffeeOrderImpl implements CoffeeOrderIF {


public Coffee [] getPriceList() throws RemoteException; {

Web-

Rendered by www.RenderX.com
JAX-RPC Стр. 19 из 626

. . .
}

public String orderCoffee(String coffeeName, int quantity)


throws RemoteException; {
. . .
}
}
После написания интерфейса службы и класса реализации разработчик должен запустить
программу отображения. Эта программа может использовать интерфейс и его реализацию
в качестве основы для генерации классов stub и tie и, при необходимости, дополнительных
классов. Как было отмечено ранее, разработчик может использовать эту программу также
для создания WSDL-описания для службы.
Последним действием в создании Web-службы является пакетирование и размещение.
Пакетирование определения Web-службы производится при помощи архива приложений
Web (WAR). WAR-файл является JAR-файлом для Web-приложений, то есть, файлом,
содержащим в сжатой форме все необходимые для Web-приложения файлы. Например,
служба CoffeeOrder может быть спакетирована в файле jaxrpccoffees.war, который облегчает
распространение и установку.
Одним из файлов, которые должны быть в каждом WAR-файле, является XML-файл,
называемый дескриптором размещения. Этот файл, называемый условно web.xml, содержит
информацию, необходимую для размещения определения службы. Например, если оно
размещается в контейнере сервлетов, таком как Tomcat, дескриптор размещения будет
включать имя сервлета и описание, класс сервлета, параметры инициализации и другую
информацию для запуска. Одним из файлов, на которые ссылается web.xml, является
файл конфигурации, автоматически генерируемый программой отображения. В данном
примере этот файл назван CoffeeOrder_Config.properties.
Размещение нашего примера Web-службы CoffeeOrder в контейнере Tomcat может быть
завершено простым копированием файла jaxrpc-coffee.war в каталог webapps системы
Tomcat. Размещение в контейнере J2EE упрощается при использовании программы
размещения, предоставляемой поставщиками сервера приложений.

2.5.4. Кодирование клиентской программы


Создание клиентского приложения для Web-службы сводится просто к написанию кода,
вызывающего нужный метод. Конечно же, для создания вызова удаленного метода и
передачи его в Web-службу нужно выполнить значительно больше действий, но все это
происходит неявно и незаметно для клиента.
Приведенное ниже определение класса представляет собой пример клиента Web-службы.
В нем создается экземпляр CoffeeOrderIF, который используется для вызова метода
getPriceList. Затем, для их отображения, осуществляется доступ к полям name и price
каждого объекта Coffee в массиве, который возвращается в методе getPriceList.
Класс CoffeeOrderServiceImpl - это один из классов, сгенерированных программой
отображения. Он является генератором заглушек и его единственный метод - getCoffee-
OrderIF; другими словами, его единственным предназначением является создание

Web-

Rendered by www.RenderX.com
Стр. 20 из 626 Введение в Web-службы

экземпляров CoffeeOrderIF. Экземпляры CoffeeOrderIF, созданные CoffeeOrderServiceImpl,


являются заглушками на стороне клиента, которые могут использоваться для вызова
методов, определенных в интерфейсе CoffeeOrderIF. Таким образом, переменная coffee-
Order представляет собой клиентскую заглушку, которая может быть использована для
вызова getPriceList - одного из методов, определенных в CoffeeOrderIF.
Метод getPriceList заблокирует работу приложения до тех пор, пока не получит ответ и не
возвратит его. Поскольку используется WSDL-документ, исполняющая система JAX-RPC
будет получать из него конечный адрес сужбы. В этом случае класс клиента может не
указывать назначение для удаленного вызова процедуры. Когда необходимо передать
конечный адрес службы, он может быть указан в виде аргумента в командной строке. Вот
как может выглядеть класс клиента:

package coffees;

public class CoffeeClient {


public static void main(String[] args) {
try {
CoffeeOrderIF coffeeOrder = new
CoffeeOrderServiceImpl().getCoffeeOrderIF();
Coffee [] priceList =
coffeeOrder.getPriceList():
for (int i = 0; i < priceList.length; i++) {
System.out.print(priceList[i].getName() + " ");
System.out.println(priceList[i].getPrice());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

2.5.5. Вызов удаленного метода


После обнаружения Web-службы клиент может вызвать один из ее методов. В следующем
примере производится удаленный вызов процедуры getPriceList, которая не принимает
аргументов. Как было отмечено ранее, выполняющая система JAX-RPC может определить
конечный адрес службы CoffeeOrder (являющийся его URI) из ее WSDL-описания. Если
WSDL-документ не используется, вы должны обеспечить URI службы в виде аргумента
командной строки. После компиляции файла CoffeeClient.java для вызова метода getPriceList
необходимо лишь ввести следующую командную строку:

java coffees.CoffeClient
Выполняемый этой строкой кода удаленный вызов процедуры является вызовом
статического метода. Другими словами, RPC был определен во время компиляция.

Web-

Rendered by www.RenderX.com
JAXM Стр. 21 из 626

Необходимо отметить, что при помощи JAX-RPC возможно динамически вызывать


удаленный метод во время выполнения. Это можно сделать либо используя Dynamic
Invocation Interface (DII), либо динамический прокси.

2.6. JAXM
Java API for XML Messaging (JAXM) предоставляет стандартный способ передачи XML-
документов по сети Интернет из платформы Java. Он базируется на спецификациях SOAP
1.1 и SOAP with Attachments, которые определяют основную среду для обмена XML-
сообщениями. JAXM может быть расширен для работы с протоколами обмена сообщениями
более высокого уровня, например определенным в ebXML (electronic business XML) Message
Service Specification, путем добавления новой функциональности на верхний уровень
SOAP.
Примечание: ebXML Message Service Specification доступна с http://www.oasis-
open.org/committees/ebxml-msg/. Среди других функций этот протокол обеспечивает более
безопасное средство передачи бизнес-сообщений по сети Интернет, чем спецификации
SOAP.
Обычно, бизнес-клиенты используют службу поставщика системы обмена сообщениями,
которая делает всю скрытую работу, требуемую для доставки и маршрутизации сообщений.
При использовании службы поставщика системы обмена сообщениями все JAXM-сообщения
проходят через нее, то есть при передаче сообщения оно сначала направляется к
поставщику отправителя, затем передается поставщику получателя и, наконец, попадает
к адресату. Также существует возможность направления сообщения промежуточным
получателям, прежде чем оно достигнет конечного адресата.
Поскольку сообщения проходят через поставщика, он должен позаботиться о деталях
таких служебных функций как назначение идентификаторов, хранение сообщений и
отслеживание того, доставлялось ли сообщение ранее. Поставщик службы обмена
сообщениями может также попытаться повторно передать сообщение, которое не достигло
назначения с первой попытки. Преимущество использования службы поставщика системы
обмена сообщениями состоит в том, что клиент, применяющий технологию JAXM ("JAXM-
клиент"), абсолютно не должен беспокоиться о том, какую внутреннюю работу делает
поставщик. JAXM-клиент просто вызывает Java-метод, а поставщик, используя свою
инфраструктуру, делает всю остальную работу незаметно для клиента.
Хотя обычно клиенты используют службу поставщика, возможно также осуществлять обмен
JAXM-сообщениями без поставщика. В этом случае, JAXM-клиент (называемый автономным
клиентом) ограничен передачей сообщений типа точка-точка непосредственно в Web-
службу, которая реализует систему обмена сообщениями типа запрос-ответ. Система
запрос-ответ является синхронной, это означает, что передача запроса и прием ответа
происходят в одной и той же операции. Сообщение типа запрос-ответ передается объектом
SOAPConnection через метод SOAPConnection.call, который передает сообщение и
блокирует работу до приема ответа. Автономный клиент может выступать только в роли
клиента, то есть он может только передавать запросы и принимать ответы на них. В отличие
от него JAXM-клиент, использующий службу обмена сообщениями поставщика, может
выступать и в роли клиента и в роли сервера (службы). В роли клиента он передает запросы,
а в роли сервера он может принимать запросы, обрабатывать их и передавать ответы.

Web-

Rendered by www.RenderX.com
Стр. 22 из 626 Введение в Web-службы

Хотя это и не обязательно, обмен сообщениями JAXM обычно происходит в контейнере,


как правило в контейнере сервлетов или в J2EE-контейнере. Web-служба, использующая
систему обмена сообщениями поставщика и размещенная в контейнере, обладает
способностью к однонаправленному обмену. Это означает, что она может принять запрос
как однонаправленное сообщение и передать ответ позже как другое однонаправленное
сообщение.
Из-за предоставляемых поставщиком системы обмена сообщениями функций JAXM может
иногда быть более удачным выбором системы обмена SOAP, чем JAX-RPC. В следующем
списке перечислены функции, которые может предоставить JAXM и обычно не может RPC
(в т.ч.JAX-RPC):
• Однонаправленный (асинхронный) обмен сообщениями
• Направление сообщения более чем одному адресату
• Надежный обмен сообщениями с такими функциями, как гарантированная доставка
Объект SOAPMessage представляет собой XML-документ, являющийся SOAP-сообщением.
Объект SOAPMessage всегда имеет необходимую SOAP-часть и может иметь одну или
более частей вложений. SOAP-часть всегда должна иметь объект SOAPenvelope, который,
в свою очередь, всегда должен содержать объект SOAPBody. Объект SOAPenvelope может
также содержать объект SOAPHeader, в который могут быть добавлены один или более
заголовков.
Объект SOAPBody может содержать XML-фрагменты в теле передаваемого сообщения.
Если вы хотите передать информацию, не записанную в формате XML или являющуюся
отдельным XML-документом, ваше сообщение должно содержать кроме SOAP-части часть
вложений. Для содержимого части вложений нет ограничений, то есть она может включать
изображения или любой другой тип информации, включая XML-фрагменты и документы.

2.6.1. Установка соединения


Прежде всего, JAXM-клиент должен установить соединение: либо объект SOAPConnection,
либо ProviderConnection.

2.6.1.1. Установка соединения точка-точка


Автономный клиент ограничен использованием объекта SOAPConnection, который является
соединением точка-точка, устанавливаемым непосредственно между отправителем и
получателем. Все JAXM-соединения создаются центром соединений. Для объекта SOAP-
Connection центром соединений является объект SOAPConnectionFactory. Получить
реализацию SOAPConnectionFactory по умолчанию клиент может при помощи следующего
кода:

SOAPConnectionFactory factory =
SOAPConnectionFactory.newInstance();
Клиент может использовать factory для создания объекта SOAPConnection.

SOAPConnection con = factory.createConnection();

Web-

Rendered by www.RenderX.com
JAXM Стр. 23 из 626

2.6.1.2. Установка соединения с поставщиком системы обмена сообщениями


Для того чтобы использовать службу обмена сообщениями поставщика, приложение
должно получить объект ProviderConnection, который является соединением с поставщиком,
а не с указанным получателем. Есть два способа получить объект ProviderConnection.
Первый похож на способ получения объекта SOAPConnection автономным клиентом. Этот
способ включает получение экземпляра реализации ProviderConnectionFactory по
умолчанию, который используется затем для создания соединения.

ProviderConnectionFactory pcFactory =
ProviderConnectionFactory.newInstance();
ProviderConnection pcCon = pcFactory.createConnection();
Переменная pcCon представляет собой соединение с реализацией по умолчанию
поставщика службы обмена сообщениями JAXM.
Вторым способом создания объекта ProviderConnection является получение объекта
ProviderConnectionFactory, который нужен для создания соединения с конкретным
поставщиком службы обмена сообщениями. В следующем фрагменте кода показано
получение такого объекта ProviderConnectionFactory и использование его для создания
соединения. Первые две строки используют Java Naming and Directory Interface™ (JNDI)
API для получения соответствующего объекта ProviderConnectionFactory из службы имен,
где он был зарегистрирован под именем "CoffeeBreakProvider". Если это логическое имя
передается в виде аргумента, метод lookup возвращает объект ProviderConnectionFactory,
с которым это имя было связано. Возвращаемое значение имеет тип Java Object и должно
быть переопределено как объект ProviderConnectionFactory для того, чтобы его можно
было использовать для создания соединения. В третьей строке используется JAXM-метод
для получения соединения.

Context ctx = getInitialContext();


ProviderConnectionFactory pcFactory =
(ProviderConnectionFactory)ctx.lookup("CoffeeBreakProvider");

ProviderConnection con = pcFactory.createConnection();


Экземпляр con ProviderConnection представляет собой соединение с поставщиком службы
обмена сообщениями "The Coffee Break".

2.6.2. Создание сообщения


Так же как и соединения, сообщения создаются центром сообщений. И, подобно центрам
соединений, объекты MessageFactory могут быть получены двумя способами. Первый
способ - получение экземпляра реализации по умолчанию класса MessageFactory. Этот
экземпляр в дальнейшем может быть использован для создания базового объекта
SOAPMessage.

MessageFactory messageFactory = MessageFactory.newInstance();


SOAPMessage m = messageFactory.createMessage();

Web-

Rendered by www.RenderX.com
Стр. 24 из 626 Введение в Web-службы

Все объекты SOAPMesage, которые создает messageFactory, включая m в предыдущей


строке кода, будут базовыми SOAP-сообщениями. Это значит, что они не будут иметь
предопределенных заголовков.
Одним из аспектов гибкости JAXM API является возможность специального использования
SOAP-заголовка. Например, другие протоколы, такие как ebXML, могут быть реализованы
на верхнем уровне системы SOAP для обеспечения реализации дополнительных
заголовков, обеспечивая, таким образом, дополнительную функциональность. Такое
использование SOAP данной группой стандартов или отраслью называется профилем.
(Дополнительная информация по профилям находится в разделе "Профили" "Руководства
по JAXM".)
При втором способе создания объекта MessageFactory используется метод createMessage-
Factory объекта ProviderConnection и передается профиль. Объекты SOAPMessage,
созданные полученным объектом MessageFactory, будут поддерживать указанный профиль.
Например, в следующем фрагменте кода, в котором schemaURI является URI схемы для
желаемого профиля, m2 будет поддерживать профиль, переданный в createMessageFactory.

MessageFactory messageFactory2 =
con.createMessageFactory(<schemaURI>);
SOAPMessage m2 = messageFactory2.createMessage();
Каждый из новых объектов SOAPMessage m и m2 автоматически содержит требуемые
элементы SOAPPart, SOAPEnvelope и SOAPBody, плюс необязательный элемент SOAP-
Header (который включен для удобства). Объекты SOAPHeader и SOAPBody первоначально
пусты. В следующем разделе показаны несколько из стандартных способов добавления
в них содержимого.

2.6.3. Заполнение сообщения


Содержимое может быть добавлено в объект SOAPPart, в один или несколько объектов
AttachmentPart, или в обе части сообщения.

2.6.3.1. Заполнение SOAP-части сообщения


Как утверждалось ранее, все сообщения имеют объект SOAPPart, который в свою очередь,
имеет объект SOAPEnvelope, содержащий объекты SOAPHeader и SOAPBody. Одним из
способов добавления содержимого в SOAP-часть сообщения является создание объекта
SOAPHeaderElement, или объекта SOAPBodyElement, и вставка XML-фрагмента, созданного
методом SOAPElement.addTextNode. В первых трех строках приведенного ниже фрагмента
кода осуществляется доступ к объекту SOAPBody body, который используется для создания
нового объекта SOAPBodyElement и добавления его в body. Передаваемый в метод
createName аргумент является объектом Name, идентифицирующим добавляемый
SOAPBodyElement. В последней строке добавляется XML-строка, передаваемая в метод
addTextNode.

SOAPPart sp = m.getSOAPPart();
SOAPEnvelope envelope = sp.getSOAPEnvelope();
SOAPBody body = envelope.getSOAPBody();

Web-

Rendered by www.RenderX.com
JAXM Стр. 25 из 626

SOAPBodyElement bodyElement = body.addBodyElement(


envelope.createName("text", "hotitems",
"http://hotitems.com/products/gizmo");
bodyElement.addTextNode("some-xml-text");
Другим способом добавления содержимого в объект SOAPPart является передача его в
объект javax.xml.transform.Source, который может быть объектом SAXSource, DOMSource
или StreamSource. Объект Source включает в себя содержимое SOAP-части сообщения,
а также информацию, необходимую для того, чтобы действовать как источник входных
данных. Объект StreamSource будет включать содержимое в виде XML-документа, а
объекты SAXSource или DOMSource будут включать содержимое и инструкции для
преобразования его в XML-документ.
В следующем фрагменте кода показано добавление содержимого в виде объекта
DOMSource. На первом шаге получаем объект SOAPPart из объекта SOAPMesage. Затем
код использует методы из JAXP API для создания добавляемого XML-документа. Для
получения объекта DocumentBuilder используется объект DocumentBuilderFactory. Затем
указанный файл анализируется для создания документа, который будет использоваться
для инициализации нового объекта DOMSource. И наконец, объект DOMSource domSource
передается в метод SOAPPart.setContent.

DocumentBuilderFactory dbf=
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("file:///foo.bar/soap.xml");
DOMSource domSource = new DOMSource(doc);

soapPart.setContent(domSource);

2.6.3.2. Заполнение части вложений сообщения


Объект Message может не иметь части вложений, но если он должен содержать что-либо
не в формате XML, это содержимое должно быть включено в часть вложений. Число частей
вложений может быть любым, и они могут содержать все, начиная с неформатированного
текста и заканчивая изображениями. В следующем фрагменте кода содержимым является
изображение из JPEG-файла, URL которого используется для инициализации объекта
javax.activation.DataHandler dh. Объект Message m создает объект AttachmentPart attachPart,
который инициализируется идентификатором данных, содержащим URL изображения. И,
наконец, сообщение добавляет attachPart к себе.

URL url = new URL("http://foo.bar/img.jpg");


DataHandler dh = new DataHandler(url);
AttachmentPart attachPart = m.createAttachmentPart(dh);
m.addAttachmentPart(attachPart);
Объект SOAPMessage может передать содержимое в объект AttachmentPart, передав
Object и тип его содержимого в метод createAttachmentPart.

Web-

Rendered by www.RenderX.com
Стр. 26 из 626 Введение в Web-службы

AttachmentPart attachPart =
m.createAttachmentPart("content-string", "text/plain");
m.addAttachmentPart(attachPart);
Третьей альтернативой является создание пустого объекта AttachmentPart и передача
Object и типа его содержимого в метод AttachmentPart.setContent. В данном фрагменте
кода Object имеет тип ByteArrayInputStream и иницилизирован jpeg-изображением.

AttachmentPart ap = m.createAttachmentPart();
byte[] jpegData = ...;
ap.setContent(new ByteArrayInputStream(jpegData),
"image/jpeg");
m.addAttachmentPart(ap);

2.6.4. Передача сообщения


После заполнения объекта SOAPMessage он готов для передачи. Автономный клиент
использует метод call объекта SOAPConnection для передачи сообщения. Этот метод
передает сообщение и блокируется до получения ответа. Аргументами метода call являются
передаваемое сообщение и объект URL, содержащий URL, который указывает конечный
адресат.

SOAPMessage response =
soapConnection.call(message, endpoint);
Приложение, использующее службу поставщика системы обмена сообщениями, для
передачи сообщения применяет метод send объекта ProviderConnection. Этот метод
передает сообщение в асинхронном режиме. Это означает, что он передает сообщение
и сразу заканчивает свою работу. Ответ, если таковой есть, будет передан как отдельная
операция в другое время. Обратите внимание, что этот метод принимает только один
параметр - передаваемое сообщение. Поставщик системы обмена сообщениями будет
использовать информацию из заголовка для определения адресата.

providerConnection.send(message);

2.7. JAXR
Java API for XML Registries (JAXR) предоставляет удобный способ получения доступа к
стандартным бизнес-реестрам по сети Интернет. Бизнес-реестры часто описываются как
электронные "желтые страницы", поскольку они содержат списки субъектов бизнеса и
предлагаемые ими продукты и службы. JAXR предоставляет разработчикам, пишущим
приложения на языке программирования Java, унифицированный способ использования
бизнес-реестров, основанных на открытых стандартах (таких как ebXML) или на отраслевых
спецификациях (таких как UDDI).

Web-

Rendered by www.RenderX.com
JAXR Стр. 27 из 626

Субъекты бизнеса могут зарегистрировать себя в реестре или найти других субъектов, с
которыми они, возможно, захотят сотрудничать. Кроме того, они могут предложить
материалы для совместного пользования или найти материалы, предложенные другими.
Группы по разработке стандартов разработали схемы для конкретных типов XML-
документов, и два субъекта бизнеса могут, например, согласиться использовать
стандартную отраслевую схему формы заказа на поставку. Поскольку схема хранится в
стандартном бизнес-реестре оба участника могут использовать JAXR для доступа к ней.
Реестры становятся все более важным компонентом Web-служб, поскольку они дают
возможность субъектам бизнеса взаимодействовать друг с другом динамически или
используя схему слабых связей. Следовательно, потребность в JAXR, позволяющем
предприятиям получать доступ к стандартным бизнес-реестрам из языка программирования
Java, также растет.

2.7.1. Использование JAXR


В следующем разделе приводятся примеры двух типичных способов использования бизнес-
реестра. Они предназначены для иллюстрации общих принципов использования JAXR и
не являются завершенными или всесторонними.

2.7.1.1. Регистрация субъекта бизнеса


Организация, использующая платформу Java в своем электронном бизнесе, может
использовать JAXR для регистрации в стандартном реестре. Она должна предоставить
свое имя, описание и некоторый принцип классификации для облегчения поиска. Это
показано в следующем фрагменте кода, в котором сначала создается объект RegistryService
rs, используемый далее для создания объекта BusinessLifeCycleManager lcm и объекта
BusinessQueryManager bqm. Субъект бизнеса, сеть магазинов называемых The Coffee
Break, представляется объектом Organization org, в который добавляется имя, описание
и код классификации по North American Industry Classification System (NAICS). Затем org,
который уже содержит свойства и классификации предприятия, добавляется в объект
Collection orgs. И, наконец, lcm сохраняет orgs и в дальнейшем будет управлять жизненным
циклом объектов Organization, содержащихся в orgs.

RegistryService rs = connection.getRegistryService();

BusinessLifeCycleManager lcm =
rs.getBusinessLifeCycleManager();
BusinessQueryManager bqm =
rs.getBusinessQueryManager();

Organization org = lcm.createOrganization("The Coffee Break");


org.setDescription(
"Purveyor of only the finest coffees. Established 1895");

ClassificationScheme cScheme =
bqm.findClassificationSchemeByName("ntis-gov:naics");

Web-

Rendered by www.RenderX.com
Стр. 28 из 626 Введение в Web-службы

Classification classification =
(Classification)lcm.createClassification(cScheme,
"Snack and Nonalcoholic Beverage Bars", "722213");

Collection classifications = new ArrayList();


classifications.add(classification);

org.addClassifications(classifications);
Collection orgs = new ArrayList();
orgs.add(org);
lcm.saveOrganizations(orgs);

2.7.1.2. Поиск в реестре


Субъект бизнеса может использовать JAXR также для поиска других субъектов. В
следующем фрагменте кода объект BusinessQueryManager bqm используется для поиска
The Coffee Break. Перед тем, как bqm сможет вызвать метод findOrganizations, необходимо
определить используемый критерий поиска. В данном случае, для findOrganizations
предоставляются три из возможных шести параметров поиска; послкольку для третьего,
пятого и шестого параметров используется значение null, эти критерии не используются
для ограничения поиска. Первый, второй и четвертый аргументы являются объектами
Collection, в которых определены параметры findQualifiers и namePatterns. Единственным
элементом в findQualifiers является объект String, указывающий, что не должна
возвращаться никакая организация, пока ее имя не будет соответствовать (регистр
символов имеет значение) одному из имени в параметре namePatterns. Этот параметр,
также являющийся объектом Collection с единственным элементом, указывает, что субъект
бизнеса, имеющий в своем названии "Coffee", соответствует критерию поиска. Другой
объект Collection - это classification, который определяет, когда компания The Coffee Break
зарегистрировала себя. Предыдущий фрагмент кода является примером определения
классификаций.

BusinessQueryManager bqm = rs.getBusinessQueryManager();

//
Collection findQualifiers = new ArrayList();
findQualifiers.add(FindQualifier.CASE_SENSITIVE_MATCH);
Collection namePatterns = new ArrayList();
namePatterns.add("%Coffee%"); // orgs ,

//'Coffee'

// ,

BulkResponse response = bqm.findOrganizations(findQualifiers,

Web-

Rendered by www.RenderX.com
Пример сценария Стр. 29 из 626

namePatterns, null, classifications, null, null);


Collection orgs = response.getCollection();
JAXR также поддерживает использование SQL-запросов для поиска в реестре. Для этого
используется объект DeclarativeQueryManager, как показано в следующем фрагменте кода.

DeclarativeQueryManager dqm = rs.getDeclarativeQueryManager();


Query query = dqm.createQuery(Query.QUERY_TYPE_SQL,
"SELECT id FROM RegistryEntry WHERE name LIKE %Coffee% " +
"AND majorVersion >= 1 AND " +
"(majorVersion >= 2 OR minorVersion >= 3)");
BulkResponse response2 = dqm.executeQuery(query);
Объект BulkResponse response2 будет содержать значение id (uuid) для каждой записи в
RegistryEntry, имеющей в своем имени символы "Coffee" и номер версии 1.3 и выше.
Для обеспечения возможности взаимодействия между JAXR-клиентом и реализацией
реестра обмен сообщениями происходит с использованием JAXM. Это происходит
полностью незаметно, так что вы, как пользователи JAXR, совершенно не должны
беспокоиться об этом.

2.8. Пример сценария


Следующий сценарий представляет собой пример того, как могут использоваться Java
API для XML и как они работают совместно. Одной из сильных сторон Java API для XML
является то, что во многих случаях они предлагают альтернативные способы реализации
чего-либо и, следовательно, позволяют вам адаптировать код под конкретные требования.
В этом разделе будут специально подчеркнуты случаи, когда можно применить различные
API, и будут объяснены причины, по которым тот или иной API может быть лучшим выбором.

2.8.1. Сценарий
Предположим, что владелец сети кофейных магазинов, называемых The Coffee Break,
хочет расширить свою деятельность продажей кофе в интерактивном режиме. Он
приказывает своему бизнес-менеджеру найти несколько новых поставщиков кофе, получить
их оптовые цены и размещать заказы по мере возникновения необходимости. The Coffee
Break может проанализировать цены и принять решение, какие новые сорта кофе
желательно приобретать и у какого из поставщиков.

2.8.1.1. Поиск новых поставщиков


Бизнес-менеджер ставит задачу инженеру-программисту компании найти потенциально
новые источники кофе. Она решает, что лучшим способом найти новых поставщиков
является поиск в реестре Universal Description, Discovery, and Integration (UDDI), в котором
The Coffee Break себя уже зарегистрировала.
Инженер использует JAXR для передачи запроса для поиска оптовых поставщиков кофе.
Реализация JAXR неявно использует JAXM для передачи запроса в реестр, но это является
полностью прозрачным для инженера.

Web-

Rendered by www.RenderX.com
Стр. 30 из 626 Введение в Web-службы

UDDI-реестр примет запрос и применит переданный в JAXR-коде критерий поиска к


имеющейся в нем информации по зарегистрированным организациям. После завершения
поиска реестр передаст обратно информацию о том, как связаться с оптовыми продавцами
кофе, удовлетворяющими указанному критерию поиска. Хотя реестр неявно использует
JAXM для передачи информации, ответ, который получит инженер, представляет из себя
JAXR-код.

2.8.1.2. Запрос прайс-листов


Следующим действием инженера является запрос прайс-листов у каждого поставщика
кофе. Она получила WSDL-описание каждого из них, в котором указывается, какую
процедуру надо вызвать для получения цен, и URI, куда нужно передать запрос. Ее
программа осуществляет соответствующие удаленные вызовы процедур при помощи JAX-
RPC API и получает ответы от поставщиков. Компания The Coffee Break имеет дело с
одним из поставщиков уже долгое время и подписывает соглашение с ним об обмене
JAXM-сообщениями, используя заранее оговоренную XML-схему. Таким образом, для
этого поставщика программа использует JAXM API для запроса текущих цен, а поставщик
возвращает прайс-лист в JAXM-сообщении.

2.8.1.3. Сравнение цен и заказ кофе


После получения ответов на свои запросы о ценах инженер обрабатывает прайс-листы,
используя SAX. Она использует SAX, а не DOM, поскольку для простого сравнения цен
это более эффективно. (Для изменения прайс-листа она выбрала бы DOM.) После того,
как ее приложение получило цены, назначенные разными поставщиками, происходит их
сравнение и отображение результатов.
После того, как владелец и бизнес-менеджер решают, с какими поставщиками иметь дело,
основываясь на сравнении цен, инженер готова для передачи заказов поставщикам. Заказы
новым поставщикам передаются через JAX-RPC, заказы к постоянным поставщикам
передаются через JAXM. Каждый поставщик, как использующий JAX-RPC, так и
использующий JAXM, передаст подтверждение с номером заказа и датой поставки.

2.8.1.4. Продажа кофе по сети Интернет


Между тем, компания The Coffee Break подготовилась для предложения своего
расширенного ассортимента кофе. Ей необходимо опубликовать прайс-лист и форму
заказа в HTML-формате на своем Web-сайте. Но перед этим компания должна определить
цену продажи. Инженер пишет приложение, умножающее оптовую цену на 135%. С
небольшими изменениями список розничных цен размещается на сайте в форме заказа.
Инженер использует технологию JavaServer Pages™ (JSP™) для создания HTML-формы
заказа, которую могут использовать клиенты для интерактивного заказа кофе. Из JSP-
страницы она получает название и цену каждого сорта и вставляет их в HTML-таблицу на
JSP-страницу. Клиент вводит количество каждого желаемого сорта кофе и нажимает кнопку
"Submit" для передачи заказа.

2.8.2. Заключение
Хотя этот сценарий упрощен в целях краткости, он иллюстрирует, как технологии XML
могут быть использованы в мире Web-служб. С появлением Java API для XML и платформы
J2EE создание Web-служб и написание приложений, использующих их, стали проще.

Web-

Rendered by www.RenderX.com
Введение в XML Стр. 31 из 626

В главе 18 приводится простая реализация этого сценария.

3. Освоение XML
В этой главе описывается Extensible Markup Language (XML) и связанные с ним
спецификации.

3.1. Введение в XML


В этом разделе рассмотрены основы XML. Наша цель - предоставить информацию для
начала работы с XML, дать вам понять, что же такое XML. (Вы изучите XML в следующих
разделах руководства.) Далее мы отметим основные особенности, которые делают XML
идеальным средством для хранения и обмена информацией, и рассмотрим главные
принципы использования XML.

3.1.1. Что такое XML?


XML - это текстовый язык разметки, который быстро становится стандартом для обмена
данными в Web. Как и в HTML для определения данных используются теги
(идентификаторы, заключенные в угловые скобки - <...>). Совокупность тегов называется
разметкой.
Но, в отличие от HTML, XML-теги идентифицируют данные, а не способ их отображения.
Если HTML-тег указывает, например, "отобразить эти данные жирным шрифтом" (<b>...</b>),
XML-тег действует как имя поля в вашей программе. Он ставит метку на часть данных,
которые идентифицирует (например: <message>...</message>).
Примечание: Поскольку идентификация данных происходит по их значению (как их
интерпретировать и что необходимо с ними сделать), XML иногда описывается как механизм
для определения семантики (значения) данных.
Так же как при определении имен полей структуры данных вы можете использовать любые
XML-теги, имеющие значение для данного приложения. Естественно, для того чтобы
несколько приложений использовали одни и те же XML-данные, они должны договориться
об именах тегов.
Вот пример XML-данных, которые можно использовать в почтовом приложении:

<message>
<to>you@yourAddress.com</to>
<from>me@myAddress.com</from>
<subject>XML Is Really Cool</subject>
<text>
How many ways is XML cool? Let me count the ways...
</text>
</message>
Примечание: В этом руководстве жирный шрифт используется для выделения текста, на
который мы хотим обратить ваше внимание. XML не использует жирный шрифт!

Web-

Rendered by www.RenderX.com
Стр. 32 из 626 Освоение XML

Теги в этом примере идентифицируют сообщение в целом, адреса отправителя и


получателя, тему и текст сообщения. Так же как и в HTML тег <to> имеет соответствующий
завершающий тег </to>. Данные между тегом и соответствующим ему завершающим тегом
определяют элемент XML-данных. Обратите внимание, что содержимое тега <to> полностью
содержится в области действия тега <message>...</message>. Именно способность одного
тега содержать другие обеспечивает в XML способность представлять иерархические
структуры данных.
И снова, так же как в HTML, пробелы не существенны, так что вы можете форматировать
данные для удобства чтения и в то же время легко обрабатывать их в программе. В отличие
от HTML, однако, в XML вы можете легко искать в наборе данных сообщения, содержащие
в своей теме слово "cool", поскольку XML-теги идентифицируют содержимое данных, а не
их представление.

3.1.1.1. Теги и атрибуты


Теги могут также содержать атрибуты - дополнительную информацию, включаемую как
часть самого тега вовнутрь его угловых скобок. В следующем примере показана структура
сообщения электронной почты, использующего атрибуты для полей "to", "from" и "subject":

<message to="you@yourAddress.com" from="me@myAddress.com"


subject="XML Is Really Cool">
<text>
How many ways is XML cool? Let me count the ways...
</text>
</message>
Как и в HTML, после имени атрибута следуют знак равенства и значение атрибута, а
несколько атрибутов разделяются пробелами. Однако, в отличие от HTML, запятые между
атрибутами в XML не игнорируются; если они существуют, генерируется ошибка.
Поскольку вы можете создать такую структуру данных как <message>, одинаково хорошо
используя как атрибуты, так и теги, принятие решения, какой дизайн лучше подходит для
конкретных целей, может потребовать значительных усилий. В разделе "Проектирование
структуры XML-данных" приведены некоторые рекомендации, которые помогут вам решить,
когда использовать атрибуты, а когда теги.

3.1.1.2. Пустые теги


Одним из действительно больших различий между HTML и XML является то, что XML-
документ всегда обязан быть формально-правильным. Существует несколько правил,
которые определяют корректность документа, но одним из самых важных является
следующее правило - каждый тег должен иметь завершающий тег. То есть, в XML тег </to>
является обязательным. Элемент <to> никогда не завершается каким-либо тегом, отличным
от </to>.
Примечание: Еще одним важным аспектом формально-правильного документа является
полная вложенность всех тегов. То есть вы можете записать
<message>..<to>..</to>..</message>, но никогда не сможете
<message>..<to>..</message>..</to>. Полный список требований находится в XML Frequently

Web-

Rendered by www.RenderX.com
Введение в XML Стр. 33 из 626

Asked Questions (FAQ) на странице http://www.ucc.ie/xml/#FAQ-VALIDWF. (Этот FAQ


находится в списке "Рекомендуется прочитать" организации W3C на htp://www.w3.org/XML/.)
Однако, иногда есть смысл использовать тег, стоящий особняком. Например, вы возможно
захотите добавить тег "flag", который помечает важное сообщение. Такой тег не имеет
никакого содержимого, и называется "пустым тегом". Вы можете создать пустой тег, закончив
его знаками /> вместо >. Например, следующее сообщение содержит такой тег:

<message to="you@yourAddress.com" from="me@myAddress.com"


subject="XML Is Really Cool">
<flag/>
<text>
How many ways is XML cool? Let me count the ways...
</text>
</message>
Примечание: Пустой тег предохраняет вас от необходимости записи <flag></flag> для
сохранения корректности документа. Вы можете контролировать, какие теги могут быть
пустыми, создав Document Type Definition, или DTD. Через некоторое время мы поговорим
об этом. Если DTD не существует, документ может содержать любые типы тегов, какие
вы захотите, пока документ остается формально-правильным.

3.1.1.3. Комментарии в XML-файлах


XML-комментарии выглядят также как и в HTML:

<message to="you@yourAddress.com" from="me@myAddress.com"


subject="XML Is Really Cool">
<!- -- >
<text>
How many ways is XML cool? Let me count the ways...
</text>
</message>

3.1.1.4. Пролог XML


И, в завершение этого введения в XML, обратите внимание, что XML-файл всегда
начинается с пролога. Минимальный пролог содержит объявление, идентифицирующее
документ как XML-документ, например:

<?xml version="1.0"?>
Объявление может также содержать дополнительную информацию, например:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>

Web-

Rendered by www.RenderX.com
Стр. 34 из 626 Освоение XML

XML-объявление по существу является таким же как и заголовок HTML, <html>, за


исключением того, что в нем используются <?..?> и он может иметь следующие атрибуты:
version - Идентифицирует используемую версию языка разметки XML. Этот атрибут является
обязательным.
encoding - Идентифицирует набор символов, используемый для кодирования данных. "ISO-
8859-1" - это набор символов "Latin-1" для языков Западной Европы и Англии. (По
умолчанию устанавливается сжатый Unicode: UTF-8.)
standalone - Указывает, ссылается или нет документ на внешнюю сущность или на внешнюю
спецификацию типов данных (см. ниже). Если нет внешних ссылок, используется значение
"yes".
Пролог может также содержать определения сущностей (элементов, вставляемых тогда,
когда вы ссылаетесь на них в документе) и спецификаций, указывающих, какие теги
являются разрешенными в документе. Сущности и спецификации объявляются в Document
Type Definition (DTD), определяемом непосредственно в прологе, или через указатель на
внешние файлы спецификаций. Но это - предмет для дальнейшего изучения в этом
руководстве. Более подробная информация об этом и многих других аспектах XML
находится в списке "Рекомендуется прочитать" организации htp://www.w3.org/XML/.
Примечание: На самом деле объявление не обязательно. Но включение его в любой
создаваемый XML-файл является хорошей идеей. Объявление должно содержать номер
версии и, по возможности, систему кодирования. Эта рекомендация упростит жизнь, если
в будущем XML-стандарт расширится, или если когда-нибудь понадобится локализовать
данные для других географических регионов.
Все, что следует за XML-прологом, составляет содержимое документа.

3.1.1.5. Директивы
XML-файл может также содержать директивы, которые передают команды или информацию
приложению, обрабатывающему XML-данные. Директивы имеют следующий формат:

<?target instructions?>
где target - имя приложения, которое, как ожидается, будет осуществлять обработку, а
instructions - это строка символов, заключающая в себе информацию или команды для
обработки приложением.
Поскольку директивы зависят от приложения, XML-файл может иметь несколько директив,
указывающих различным приложениям выполнить похожие действия, хотя и разными
способами. XML-файл для слайдшоу, например, может содержать директивы, позволяющие
докладчику выбрать техническую версию презентации или версию для исполнительного
звена. Если бы использовались несколько программ презентации, в программе, возможно,
понадобилось бы наличие нескольких версий директив (хотя было бы лучше, если бы эти
приложения распознавали стандартные директивы).
Примечание: Имя "XML" (в любой комбинации строчных или прописных букв)
зарезервировано для XML-стандартов. В некотором смысле объявление является
директивой, удовлетворяющей стандарту. (Однако, если вы позже будете работать с
анализатором, вы увидите, что метод для обработки директив никогда не видит
объявления.)

Web-

Rendered by www.RenderX.com
Введение в XML Стр. 35 из 626

3.1.2. В чем важность XML?


Существует большое количество причин всеобщего признания XML. В этом разделе
перечислены наиболее важные из них.

3.1.2.1. Обыкновенный текст


Поскольку XML не является двоичным форматом, вы можете создать и редактировать
файлы при помощи любого средства, начиная от стандартного текстового редактора и
заканчивая визуальной средой разработки. Это облегчает отладку ваших программ и
приносит пользу при хранении небольшого количества данных. С другой стороны, внешний
интерфейс XML к базе данных делает также возможным эффективное хранение большого
количества XML-данных. То есть XML, обеспечивает полную масштабируемость, начиная
от небольших конфигурационных файлов и заканчивая корпоративным хранилищем данных.

3.1.2.2. Идентификация данных


XML указывает типы данных, а не способ их отображения. Поскольку теги разметки
идентифицируют информацию и разбивают данные на части, почтовая программа может
обрабатывать их, программа поиска может искать сообщения, переданные определенному
человеку, а адресная книга может извлекать адрес из оставшейся части сообщения. Короче
говоря, поскольку идентифицируются различные части информации, они могут быть
использованы различными способами различными приложениями.

3.1.2.3. Стиль отображения


Когда способ отображения является важным, стандарт таблицы стилей XSL позволяет
вам указать, как отобразить данные. Например, таблица стилей для:

<to>you@yourAddress.com</to>
может сказать:
1. Начать новую строку.
2. Отобразить "To:" жирным шрифтом с последующим пробелом.
3. Отобразить данные получателя.
Вот что получится:

To: you@yourAddress
Конечно, вы можете сделать тоже самое и в HTML, но вы не сможете обработать данные
программами поиска и программами, извлекающими адреса и т.д. Более важным является
то, что, поскольку XML по своей сути не имеет стиля, вы можете использовать совершенно
разные таблицы стилей для выполнения вывода в форматах postscript, TEX, PDF или
каких-либо новых форматах, которые еще даже не разработаны. Такая гибкость означает
то, что один автор описал как "будущая защита" вашей информации. XML-документы,
созданные сегодня, могут использоваться в будущих, еще не известных системах доставки
документов.

Web-

Rendered by www.RenderX.com
Стр. 36 из 626 Освоение XML

3.1.2.4. Встроенная возможность многократного использования


Одной из замечательных возможностей XML-документов является возможность их
составления из отдельных модулей. Это возможно и в HTML, но только при помощи
указания ссылок на другие документы. В отличие от HTML, XML-модули могут быть
включены в документ "по месту". Подключенные модули выглядят как нормальные части
документа - вы можете производить поиск по всему документу одновременно или загружать
его одной частью. Это дает возможность разбивать документ на модули без помощи
ссылок. Вы можете отделить модуль так, что редактирование в нем отражается везде, где
он используется, а документ, составленный из таких модулей, выглядит для всех состоящим
только из одной части.

3.1.2.5. Связываемость
Благодаря HTML, способность определять связи между документами рассматривается
сегодня как необходимость. В следующем разделе этого руководства, "XML и связанные
спецификации: освоение алфавитной путаницы", обсуждается программа создания
спецификации по ссылкам. Эта программа позволяет вам определять двунаправленные
ссылки, многоцелевые ссылки, "расширяющиеся" ссылки (в которых переход по ссылке
вызывает появление запрошенной информации в текущем месте документа), и ссылки
между двумя существующими документами, определенные в третьем.

3.1.2.6. Простота обработки


Как упоминалось ранее, регулярная и непротиворечивая нотация облегчает создание
программ для обработки XML-данных. Например, в HTML тег <dt> может быть ограничен
тегами </dt>, другим <dt>, <dd> или </dl>. Это несколько затрудняет программирование.
Но в XML тег <dt> должен всегда ограничиваться тегом </dt>, в противном случае он должен
определяться как тег <dt/>. Это правило является критичным среди ограничений, которые
делают XML-документ формально-правильным. (В противном случае XML-анализатор не
будет способен прочитать данные.) А поскольку XML является независимым от
производителей стандартом, вы можете выбрать любой XML-анализатор, и каждый из них
сможет обработать XML-данные.

3.1.2.7. Иерархичность

3.1.3. Как можно использовать XML?


Существует несколько основных областей использования XML:
• Традиционная обработка данных, при которой данные кодируются в XML для
обрабатывающей их программы.
• Основанное на документах программирование, при котором XML-документы являются
контейнерами, создающими интерфейсы и приложения из существующих компонентов.
• Архивация - фундамент основанного на документах программирования, при котором
настроенная версия компонента сохраняется (архивируется) для дальнейшего
использования.
• Связывание, при котором DTD или схема, определяющая структуру XML-данных,
используется для автоматической генерации значительной части приложения, которое
в конечном итоге будет обрабатывать данные.

Web-

Rendered by www.RenderX.com
Введение в XML Стр. 37 из 626

3.1.3.1. Традиционная обработка данных


XML быстро становится стандартом, выбираемым для представления информации в Web.
Это проявляется еще сильнее при использовании его в соединении с сетевыми
программами платформы Java, передающими и принимающими информацию. То есть,
приложение клиент/сервер, например, может передавать XML-данные в обоих направлениях
между клиентом и сервером.
В будущем XML станет потенциальным решением при обмене данными в транзакциях
любого типа, как только обе стороны согласятся использовать одинаковую разметку.
(Например, какие теги почтовая программа должна обрабатывать: <FIRST> и <LAST>, или
<FIRSTNAME> и <LASTNAME>). Необходимость в общих стандартах в ближайшие годы
приведет к разработке многих отраслевых стандартов. Между тем, будут важны механизмы,
позволяющие "транслировать" теги в XML-документе. Такими механизмами являются,
например, инициатива RDF, в которой определяются "базовые теги", и XSL-спецификация,
определяющая трансляцию одних XML-тегов в другие.

3.1.3.2. Основанное на документах программирование (DDP)


Новейшим подходом к использованию XML является создание документа, описывающего
внешний вид страницы приложения. Этот документ, вместо того, чтобы просто быть
отображенным, состоит из ссылок на компоненты пользовательского интерфейса и
компоненты бизнес-логики, которые соединяются вместе для создания приложения на
лету.
Конечно, для таких компонентов имеет смысл использовать платформу Java. Для создания
таких приложений можно использовать и JavaBeans™ для интерфейсов, и JavaBeans™
для бизнес-логики. И хотя ни одно из предпринятых усилий еще не доведено до
коммерческого использования, очень много предварительной работы уже сделано.
Примечание: Язык программирования Java также отлично подходит для создания средств
обработки XML, которые являются такими же переносимыми, как и XML. Для платформы
Java были написаны несколько визуальных редакторов XML. Список редакторов, средств
обработки и других XML-ресурсов находится в разделе "Software" SGML/XML Web-страницы,
созданной Robin Cover, по адресу http://www.oasis-open.org/cover/.

3.1.3.3. Связывание
Как только вы определили структуру XML-данных, используя DTD или один из стандартов
схем, большая часть необходимой обработки уже определена. Например, если в схеме
указано, что текстовые данные в элементе <date> должны соответствовать одному из
распознаваемых форматов даты, один из аспектов критерия верификации данных уже
определен - остается только написать код. Хотя спецификация DTD не может обеспечить
такой же уровень детализации, DTD (как и схема) описывает грамматику, указывающую,
какие структуры данных могут встретиться и в какой последовательности. В этой
спецификации указывается, как написать высокоуровневый код, обрабатывающий элементы
данных.
Но когда структура данных (и возможно схема) полностью определена, код, необходимый
вам для обработки этих данных, может быть легко сгенерирован автоматически. Этот
процесс известен под названием связывание - создание классов, распознающих и
обрабатывающих различные элементы данных при обработке спецификации, которая
определяет эти элементы. Со временем вы обнаружите, что используете спецификацию

Web-

Rendered by www.RenderX.com
Стр. 38 из 626 Освоение XML

данных для генерирования значительной части кода, и сможете сконцентрироваться на


программировании уникальных для вашего приложения задач.

3.1.3.4. Архивация
Чашей Святого Грааля в программировании является создание повторно используемых,
модульных компонентов. В идеальном случае вы хотели бы взять их с полки, настроить и
подключить их для создания приложения, с минимальным дополнительным кодированием
и дополнительной компиляцией.
Основной механизм сохранения информации называется архивированием. Компонент
архивируется путем записи его в выходной поток в форме, которую можно будет
использовать в дальнейшем. Потом можно будет прочитать его и создать экземпляр,
используя сохраненные параметры. (Например, если вы сохранили элемент таблицы, его
параметрами могут быть количество строк и столбцов для отображения.) Архивированные
компоненты можно перемещать по Web и использовать множеством способов.
Когда компоненты архивируются в бинарной форме, существуют некоторые ограничения
в видах изменений, которые можно сделать в классах при желании сохранить совместимость
с предыдущими версиями. Если бы вы могли модифицировать архивную версию так, чтобы
изменения отразились в ней, это решило бы проблему. Но это очень тяжело сделать с
двоичными объектами. Такие рассуждения вызвали большое количество исследований в
использовании XML для архивирования. Но если состояние объекта было сархивировано
в текстовой форме с использованием XML, тогда все в нем может быть изменено так же
легко, как и сказать "найти и заменить".
Текстовый формат XML может также облегчить передачу объектов между приложениями,
написанными на разных языках. По всем этим причинам основанное на XML архивирование
возможно будет иметь большое распространение в не таком уж далеком будущем.

3.1.3.5. Итог
XML является довольно простым и очень гибким языком разметки. Он имеет много
применений, которые еще должны быть открыты - мы только начинаем использовать его
потенциал. Он является фундаментом для многих грядущих стандартов, обеспечивая
общий язык, который могут использовать различные компьютерные системы для обмена
данными друг с другом. Как только каждая отраслевая группа выйдет со своими
стандартами, компьютеры начнут связываться друг с другом способами, которые раньше
трудно было бы представить.
Более подробная информация по предпосылкам и движущим силам XML находится в
прекрасной статье в Scientific American по адресу
http://www.sciam.com/1999/0599issue/0599bosak.html.

3.2. XML и связанные спецификации: освоение алфавитной путаницы


Теперь, когда вы понимаете основы XML, имеет смысл рассмотреть различные имеющие
отношение к XML акронимы и их значение. Большой объем работы над XML продолжается,
так что у нас есть что изучить.
Существующими в настоящее время API для обработки XML-документов в
последовательном режиме или в режиме произвольного доступа являются соответственно
SAX и DOM. Спецификациями для обеспечения корректности XML-документов являются

Web-

Rendered by www.RenderX.com
XML и связанные спецификации: освоение алфавитной путаницы Стр. 39 из 626

DTD (оригинальный механизм, определенный как часть спецификации XML) и различные


предложения стандартов схем (новые механизмы, использующие синтаксис XML для
описания критериев верификации).
Среди других будущих стандартов, близких к завершению является стандарт XSL - механизм
для настройки правил трансляции XML-документов (например, в HTML или другой XML)
и для описания правил визуализации документа. Часть этого стандарта, предназначенная
для преобразований, XSLT(+XPATH) завершена и описана в этом руководстве. Еще один
стандарт, близкий к завершению - спецификация XML Link Language (XML Linking),
разрешающая связи между XML-документами.
Это основные стандарты, с которыми вы должны быть хорошо знакомы. В этом разделе
приведен также обзор нескольких других интересных предложений, включая HTML-подобный
стандарт, XHTML, и мета-стандарт для описания информации, содержащейся в XML-
документе, RDF. Продолжается работа также над стандартами, расширяющими
возможности XML, например Xlink и Xpointer.
Наконец, существует несколько интересных стандартов и предложений стандартов, которые
построены на XML, включая Synchronised Multimedia Integration Language (SMIL), Mathemat-
ical Markup Language (MathML), Scalable Vector Graphics (SVG) и DrawML, а также несколько
стандартов eCommerce.
В остальной части этой главы приведено более детальное описание этих стандартов. Для
ясности они разделены на:
• Основные стандарты
• Стандарты схем
• Стандарты связи и представления
• Стандарты знаний
• Стандарты, построенные на XML
Бегло просмотрите термины один раз для ознакомления и храните копию этого документа
под рукой, чтобы можно было обратиться к нему при встрече этих терминов где-нибудь
еще. Очень скоро все они зафиксируются в вашей памяти, и вы станете "хорошо знакомы"
с XML!

3.2.1. Основные стандарты


Существуют основные стандарты, с которыми вы должны быть хорошо знакомы. Они
присутствуют практически в любом обсуждении XML.

3.2.1.1. SAX
Простой API для XML.
Этот API был фактически продуктом совместной работы участников списка рассылки XML-
DEV, а не продуктом W3C. Он включен сюда потому, что имеет такие же "окончательные"
характеристики, что и рекомендации W3C.
Вы можете рассматривать этот стандарт как протокол "последовательного доступа" к XML.
Он является быстрым механизмом, который можно применить, например, для чтения или
записи XML-данных на сервер. Его называют также протоколом, управляемым событиями,
поскольку техника работы с ним следующая: регистрация вашего обработчика в SAX-
анализаторе, после чего анализатор обращается к вашим методам обратного вызова при

Web-

Rendered by www.RenderX.com
Стр. 40 из 626 Освоение XML

обнаружении нового XML-тега (либо встречает ошибку, либо хочет передать вам что-нибудь
еще).
Более детальная информация по протоколу SAX находится в разделе "Простой API для
XML".

3.2.1.2. DOM
Document Object Model (объектная модель документа).
Протокол Document Object Model преобразует XML-документ в набор объектов вашей
программы. После этого вы можете манипулировать ими любым способом. Этот механизм
известен также под названием - протокол "произвольного доступа", поскольку можно
обратиться к любой части данных в любое время. Вы можете затем модифицировать
данные, удалить их или вставить новые. Более подробная информация по спецификации
DOM находится в разделе Document Object Model.

3.2.1.3. JDOM и dom4j


В то время как Document Object Model (DOM) обеспечивает большие возможности
документо-ориентированной обработки, он не предоставляет чего-нибудь значительного
в области объектно-ориентированного подхода. Java-разработчики, работающие со
структурами, более ориентированными на данные, а не с книгами, статьями или другими
полностью готовыми документами, часто находят, что объектно-ориентированные API,
такие как JDOM и dom4j, легче в использовании и больше подходят под их требования.
Ниже приведены важные различия, которые нужно принимать во внимание при выборе
одного из этих API:
• JDOM немного более понятный, меньший по объему API. Когда важен "стиль
кодирования", JDOM - это хороший выбор.
• JDOM - это разработка Java Community Process (JCP). После завершения он станет
рекомендованным стандартом.
• dom4j - маленькая, быстрая реализация, находящая широкое применение в течение
уже нескольких лет.
• dom4j - является реализацией, основанной на генераторе. Это облегчает использование
в сложных приложениях специального назначения. На момент написания руководства
JDOM еще не использовал генератор для создания экземпляра анализатора (хотя
стандарт, кажется, продвигается в этом направлении). То есть, в JDOM вы всегда
получаете оригинальный анализатор. (Это хорошо для большинства приложений, но
не подходит для приложений специального назначения.)
Более подробная информация по JDOM находится на странице http://www.jdom.org/.
Более подробная информация по dom4j находится на странице http://dom4j.org/.

3.2.1.4. DTD
Document Type Definition (определение типа документа).
Спецификация DTD является фактически частью спецификации XML, а не отдельной
сущностью. С другой стороны, она не обязательна - вы можете написать XML-документ
без нее. И существует несколько альтернативных стандартов схем, предлагающих более
гибкие возможности. Поэтому DTD рассматривается здесь как отдельная спецификация.

Web-

Rendered by www.RenderX.com
XML и связанные спецификации: освоение алфавитной путаницы Стр. 41 из 626

DTD определяет типы тегов, которые можно использовать в XML-документе, и их


правильное расположение. DTD можно использовать для гарантии корректности XML-
структуры. Вы можете использовать ее также для проверки корректности XML-структуры,
которую читаете (или которая передается по сети).
К сожалению, очень трудно сформировать DTD для сложного документа так, чтобы она
предотвращала все неверные комбинации и разрешала все правильные. Создание DTD
представляет собой в какой-то степени искусство. DTD может существовать в самом
документе, как часть пролога. Она может существовать также в виде отдельной сущности,
или может быть разделена между прологом документа и одной или несколькими
дополнительными сущностями.
Однако, хотя механизм DTD был первым методом указания корректной структуры документа,
он не был последним. Было разработано несколько новых спецификаций схем. Очень
скоро вы узнаете про них.
Детальная информация приведена в разделе Создание Document Type Definition (DTD).

3.2.1.5. Пространство имен


Стандарт пространства имен позволяет вам написать XML-документ, использующий два
и более набора XML-тегов модульным способом. Предположим, что вы создали основанный
на XML список деталей, использующий XML-описания деталей, предлагаемых другими
производителями (в режиме онлайн!). Элемент "price" для субкомпонентов может означать
суммарную цену выбранных деталей, в то время как элемент "price" для структуры в целом
может означать что-либо для отображения. Спецификация пространства имен определяет
механизм уточнения имен для устранения двусмысленности. Она позволяет вам писать
программы, использующие информацию из других источников и правильно работающие
с ней.
Последняя информация по пространству имен находится на странице
http://www.w3.org/TR/REC-xml-names.

3.2.1.6. XSL
Extensible Stylesheet Language (расширяемый язык таблиц стилей).
XML-стандарт определяет способ интерпретации данных, а не способ их отображения.
HTML, с другой стороны, определяет, как данные должны быть отображены, без указания
их значения. XSL-стандарт имеет две части, XSLT (стандарт преобразования, описываемый
ниже) и XSL-FO (часть, описывающая объекты форматирования, известные, также, под
названием поток объектов). XSL-FO дает возможность определить различные области на
странице и затем связать их вместе. Когда текстовый поток направляется в такую
коллекцию, текст заполняет полностью первую область, а затем "перетекает" во вторую
область. Такие объекты используются в почтовых рассылках, каталогах и периодических
изданиях.
Последние работы W3C по XSL находятся на странице http://www.w3.org/TR/WD-xsl.

3.2.1.7. XSLT (+XPATH)


Extensible Stylesheet Language for Transformations (расширяемый язык таблиц стилей для
преобразований).

Web-

Rendered by www.RenderX.com
Стр. 42 из 626 Освоение XML

Стандарт преобразований XSLT является по существу механизмом преобразования,


дающим возможность указать, как преобразовать XML-тег так, чтобы его можно было
отобразить, например, в HTML. Различные XSL-форматы могут быть использованы для
отображения тех же самых данных различными способами для различных пользователей.
(Стандарт XPATH является механизмом адресации, используемым при создании инструкций
преобразования для указания частей XML-структуры, которые необходимо преобразовать.)
Дополнительная информация находится в разделе XML Stylesheet Language for Transfor-
mations.

3.2.2. Стандарты схем


DTD дает возможность проверять структуру относительно простых XML-документов, но
это все, на что он способен.
DTD не может ограничить содержимое элементов и не может определить сложные связи.
Например, в DTD невозможно определить, что <heading> для <book> должен иметь и <title>
и <author>, в то время как <heading> для <chapter> должен иметь только <title>. В DTD
можно определить структуру элемента <heading> только один раз. В нем нет
чувствительности к контексту.
Это происходит из-за того факта, что спецификация DTD не является иерархической.
Например, для почтового адреса, содержащего несколько элементов PCDATA ("parsed
character data"), DTD может выглядеть следующим образом:

<!ELEMENT mailAddress (name, address, zipcode)>


<!ELEMENT name (#PCDATA)>
<!ELEMENT address (#PCDATA)>
<!ELEMENT zipcode (#PCDATA)>
Как вы можете заметить, спецификации являются линейными. Этот факт заставляет вас
записывать новые имена похожих элементов в различных местах. Так что если вы захотите
добавить еще один элемент "name" в DTD, содержащий <firstName>, <middleInitial> и
<lastName> вы должны записать другой идентификатор. Вы не можете просто назвать его
"name" без возникновения конфликта с элементом <name>, определенным в <mailAddress>.
Другой проблемой не иерархической природы спецификации DTD является неясность
того, к чему относятся комментарии. Такой комментарий в начале как <!-- Адрес,
используемый для переписки через почтовую систему --> может относиться ко всем
элементам, составляющим почтовый адрес. Но такой комментарий как <!-- Адресат -->
может относиться только к элементу name. С другой стороны, такой комментарий как <!--
Строка из пяти цифр --> может относиться только к части #PCDATA элемента zipcode для
описания правильного формата. Наконец, DTD не позволяет формально определять
критерии верификации полей, такие как, например, ограничение в 5 цифр (или 5 и 4) в
поле zipcode.
И, наконец, DTD использует синтаксис, существенно отличающийся от XML, и поэтому не
может обрабатываться стандартным XML-анализатором. Это означает, что нельзя прочитать
DTD в DOM, например, для его модификации и сохранения.

Web-

Rendered by www.RenderX.com
XML и связанные спецификации: освоение алфавитной путаницы Стр. 43 из 626

Для преодоления этих недостатков были сделаны несколько предложений более похожих
на базы данных иерархических схем, определяющих критерии верификации. Основные
предложения обсуждаются ниже.

3.2.2.1. XML Schema


Это большой комплексный стандарт, имеющий две части. Одна часть определяет
структурные взаимосвязи. (Это самая большая и наиболее сложная часть.) Другая часть
определяет механизмы проверки содержимого XML-элементов при помощи определения
типов данных (возможно очень сложных) для каждого элемента. Хорошей новостью
является то, что XML Schema for Structures позволяет указать любой тип взаимосвязей,
какие можно только представить. Плохой новостью является большой объем работы для
их реализации и некоторое время на изучение. Большинство из альтернатив предоставляют
более простые определения структуры, чем стандарт типов данных XML Schema.
Дополнительная информация по XML Schema находится в спецификации W3C XML Schema
(Structures) и XML Schema (Datatypes) вместе с другой дополнительной информацией на
странице http://www.w3.org/XML/Schema.

3.2.2.2. RELAX NG
Regular Language description for XML (описание языка регулярных выражений для XML).
Более простым, чем XML Structure Schema, является появляющийся стандарт под
протекцией OASIS (Organization for the Advancement of Structured Information Systems) -
Организации по развитию структурированных информационных систем. RELAX NG
использует модель регулярных выражений для указания ограничений структурных
взаимосвязей. Этот стандарт разработан для работы с механизмом определения типов
данных XML Schema и указания ограничений их содержимого. Он использует синтаксис
XML и содержит преобразователь DTD в RELAX. ("NG" обозначает "Next Generation". Это
более новая версия механизма схем RELAX, которая интегрирует в себя TREX.)
Дополнительная информация по RELAX NG находится на странице http://www.oasis-
open.org/committes/relax-ng/.

3.2.2.3. TREX
Tree Regular Expressions for XML (дерево регулярных выражений для XML).
Это средство выражения критериев верификации путем описания шаблона структуры и
содержимого XML-документа. Сейчас является частью спецификации RELAX NG.
Дополнительная информация по TREX находится на странице http://www.thaiopen-
source.com/trex/.

3.2.2.4. SOX
Schema for Object-oriented XML (схема для объектно-ориентированного XML).
SOX является схемой, включающей расширяемые типы данных, пространства имен и
встраиваемую документацию.
Дополнительная информация по SOX находится на странице http://www.w3.org/TR/NOTE-
SOX/.

Web-

Rendered by www.RenderX.com
Стр. 44 из 626 Освоение XML

3.2.2.5. Schematron
Схема для объектно-ориентированного XML.
Механизм схемы, основанный на утверждениях и предлагающий комплексную верификацию.
Дополнительная информация по механизму верификации Schematron находится на
странице http://www.ascc.net/xml/resource/schematron/schematron.html.

3.2.3. Стандарты связывания и представления


Бесспорно, двумя основными преимуществами HTML были способность иметь связи между
документами и способность создавать форматированные документы (и, в конечном итоге,
очень сложные форматированные документы). Следующие стандарты призваны сохранить
преимущества HTML в области XML, а также добавить новую функциональность.

3.2.3.1. XML Linking


Эти спецификации предоставляют разнообразные мощные механизмы связывания и,
конечно же, оказывают большое влияние на то, как используются XML-документы.
XLink
Протокол XLink - это спецификация обработки связей между XML-документами. Эта
спецификация предоставляет возможность организовывать некоторые довольно непростые
связи, включая двунаправленные ссылки, ссылки на несколько документов,
"расширяющиеся" ссылки, которые вставляют связанную информацию в ваш документ, а
не заменяют его новой страницей, ссылки между двумя документами, созданными в
третьем, независимом документе, и непрямые ссылки (так что вы можете указать на
"адресную книгу" а не прямо на нужный документ - обновление адресной книги
автоматически изменит все ссылки, ее использующие).
XML Base
Этот стандарт определяет атрибут XML-документов, в котором указывается "базовый"
адрес, используемый при вычислении указанного в документе относительного адреса.
(Так, например, простое имя файла может быть найдено в указанном в базовом адресе
каталоге.)
XPointer
В общем случае, спецификация XLink ссылается на документ или сегмент документа,
используя его ID (идентификатор). Спецификация XPointer определяет механизмы для
"адресации во внутренние структуры XML-документов" без необходимости указания автором
документа ID для этого сегмента. Цитируя спецификацию, она обеспечивает "обращение
к элементам, строкам символов и другим частям XML-документов, независимо от того,
имеют они или нет явный атрибут ID".
Дополнительная информация по стандартам XML Linking находится на странице
http://www.w3.org/XML/Linking.

3.2.3.2. XHTML
Спецификация XHTML - это способ создания XML-документов, которые выглядят и ведут
себя так же как HTML-документы. Поскольку XML-документ может содержать любые теги,
которые вы позаботились определить, почему бы не определить набор тегов, выглядящих
как HTML? Во всяком случае, именно эта идея стоит за спецификацией XHTML. Результатом
применения этой спецификации является документ, который может отображаться в

Web-

Rendered by www.RenderX.com
XML и связанные спецификации: освоение алфавитной путаницы Стр. 45 из 626

броузерах, а также обрабатываться как XML-данные. Данные могут быть не настолько


идентифицируемыми, как в "чистом" XML, но ими можно будет намного легче
манипулировать, чем в стандартном HTML, поскольку XML предлагает намного большую
регулярность и логичность.
Например, каждый тег в формально-правильном XML-документе должен иметь
завершающий тег или должен заканчиваться знаками />. То есть, вы можете увидеть
<p>...</p> или <p/>, но вы никогда не увидите стоящего отдельно <p>. Из-за этого
требования вы никогда не должны программировать непонятные конструкции, которые
можно увидеть в HTML, где, например, тег <dt> может завершаться тегом </DT>, другим
<DT>, <dd> или </dl>. Это намного облегчает написание кода!
Спецификация XHTML - это перенос HTML 4.0 в XML. Последняя информация находится
на странице http://www.w3.org/TR/xhtml1.

3.2.4. Стандарты знаний


Если оглянуться на весь путь развития информации в Web за последние пять или шесть
лет, можно заметить, что она превратилась в одну огромную базу знаний ("семантика
Web"). Последняя информация по этому вопросу находится на странице
http://www.w3.org/2001/sw/.
Между тем, вот фундаментальные стандарты, о которых вы должны знать:

3.2.4.1. RDF
Resource Description Framework (среда описаний ресурсов).
RDF является стандартом для определения метаданных - информации, описывающей,
чем является элемент данных и как он может быть использован. Используемый совместно
со спецификацией XHTML например, или с HTML-страницами, RDF может применяться
для описания содержимого страниц. Например, если ваш броузер сохранил вашу
идентификационную информацию как FIRSTNAME, LASTNAME и EMAIL, описание RDF
могло бы сделать возможной передачу данных в приложение, нуждающееся в NAME и
EMAILADDRESS. Только представьте: однажды вам не надо будет вводить имя и адрес
на каждом Web-сайте, который вы посещаете!
Последняя информация по RDF находится на странице http://www.w3.org/TR/REC-rdf-syntax.

3.2.4.2. RDF Schema


RDF Schema предоставляет спецификацию логических правил и дополнительную
информацию, описывающую, как должны интерпретироваться операторы в RDF.
Дополнительная информация по рекомендациям RDF Schema находится на странице
http://www.w3.org/TR/rdf-schema.

3.2.4.3. XTM
XML Topic Maps (карты тем XML).
Являясь по многим параметрам более простым, а также более готовым к использованию
представлением знаний, чем RDF, стандарт Topic Maps заслуживает внимания. До
настоящего времени RDF является стандартом W3C для представления знаний, но карты
тем могут, по-видимому, стать "выбором разработчика" среди стандартов представлений
знаний.

Web-

Rendered by www.RenderX.com
Стр. 46 из 626 Освоение XML

Дополнительная информация по XML Topic Maps находится на странице


http://www.topicmaps.org/xtm/index.html. Информацию по картам тем и Web можно найти
на сайте http://www.topicmaps.org/.

3.2.5. Стандарты, основанные на XML


Следующие стандарты и предложения основываются на XML. Поскольку XML является в
основном средством описания языка, эти спецификации используют его для определения
стандартизованных языков специального применения.

3.2.5.1. Extended Document Standards (стандарты расширенных документов)


Эти стандарты определяют механизмы для создания очень сложных документов - книг,
журналов, газет и т.п. - с использованием XML.

3.2.5.1.1. SMIL
Synchronized Multimedia Integration Language (язык синхронной интеграции мультимедиа).
SMIL - это рекомендация W3C, относящаяся к аудио, видео и анимации. Он также
предназначен для решения сложных вопросов синхронизации воспроизведения этих
элементов.
Дополнительная информация по SMIL находится на странице http://www.w3.org/TR/REC-
smil.

3.2.5.1.2. MathML
Mathematical Markup Language (язык математической разметки).
MathML - это рекомендация W3C, имеющая дело с представлением математических
формул.
Дополнительная информация по MathML находится на странице http://www.w3.org/TR/REC-
MathML.

3.2.5.1.3. SVG
Scalable Vector Graphics (масштабируемая векторная графика).
(Векторные графические изображения строятся на основе команд типа "начертить линию
(квадрат, круг) из точки xi в точку m,n", в отличие от кодирования изображений в виде
последовательности бит. Такие изображения легче масштабируются, хотя обычно они
требуют больше времени обработки для визуализации.)
Дополнительная информация по SVG находится на странице http://www.w3.org/TR/WD-
SVG.

3.2.5.1.4. DrawML
Drawing Meta Language (метаязык для рисования).
DrawML - это комментарий W3C, относящийся к 2D-изображениям для технических рисунков.
Он также предназначен для решения проблемы обновления и повышения качества таких
изображений.
Дополнительная информация по DrawML находится на странице http://www.w3.org/TR/NOTE-
drawml.

Web-

Rendered by www.RenderX.com
XML и связанные спецификации: освоение алфавитной путаницы Стр. 47 из 626

3.2.5.2. Стандарты электронной коммерции (eCommerce)


Эти стандарты нацелены на использование XML в мире business-to-business (B2B - бизнес-
бизнес) и business-to-consumer (B2C - бизнес-потребитель) коммерции.

3.2.5.2.1. ICE
Information and Content Exchange (обмен информацией и содержимым).
ICE - это протокол для использования содержимого поставщиками и их подписчиками. Он
сконцентрирован на "автоматизации обмена и повторного использования содержимого,
как в традиционных публикациях, так и B2B-отношениях".
Дополнительная информация по ICE находится на странице http://www.w3.org/TR/NOTE-
ice.

3.2.5.2.2. ebXML
Electronic Business with XML (электронный бизнес с использованием XML).
Этот стандарт предназначен для создания модульной среды электронного бизнеса с
использованием XML. Он является продуктом совместной инициативы организаций United
Nations (UN/CEFACT) и OASIS.
Дополнительная информация по ebXML находится на сайте http://www.ebxml.org/.

3.2.5.2.3. cxml
Commerce XML (коммерческий XML).
cxml - это стандарт RosettaNet (www.rosettanet.org) для настройки интерактивных онлайн-
каталогов для различных покупателей, в которых цены и предложения продуктов зависят
от компании. В него включены механизмы обработки заказов на поставку, изменений
заказов, обновлений состояния и уведомлений о доставке.
Дополнительная информация по cxml находится на сайте http://www.cxml.org/.

3.2.5.2.4. CBL
Common Business Library (библиотека бизнеса общего назначения).
CBL - это библиотека элементов и определений атрибутов, поддерживаемых CommerceNet
(www.commerce.net).
Дополнительная информация по CBL и множеству других инициатив, работающих совместно
в приложениях eCommerce, находится на странице
http://www.commerce.net/projects/currentprojects/eco/wg/eCo_Framework_Specifications.html.

3.2.5.2.5. UBL
Universal Business Library (бизнес-библиотека универсального назначения).
Инициатива OASIS, нацеленная на формирование стандартной библиотеки XML бизнес-
документов (заказов, счетов и т.д.), определяемых в описаниях XML Schema.
Дополнительная информация по UBL находится на странице http://www.oasis-
open.org/committees/ubl.

Web-

Rendered by www.RenderX.com
Стр. 48 из 626 Освоение XML

3.2.6. Итоги
XML становится общепринятым стандартом, используемым в огромном разнообразии
прикладных областей.

3.3. Разработка структуры данных XML


В этом разделе рассмотрены некоторые эвристические подходы к принятию тех или иных
решений при создании XML-документа.

3.3.1. Облегчение своей работы


Когда это возможно, используйте существующее определение схемы. Всегда легче
игнорировать ненужные элементы, чем создавать свои собственные с нуля. Кроме того,
использование DTD делает возможным обмен данными и может сделать возможным
использование программных средств, разработанных другими.
Итак, если существует отраслевой стандарт, используйте ссылку на его DTD. Одним из
мест для поиска отраслевых стандартов DTD является архив, созданный Organization for
the Advancement of Structured Information Standards (OASIS - организацией по развитию
стандартов структурированной информации), находящийся на сайте http://www.XML.org.
Другим местом для проверки является XML Exchange от CommerceOne на сайте
http://www.xmlx.com, который описывается как "архив для создания и совместного доступа
к определениям типов документов".
Примечание: Очень много хороших рекомендаций по созданию XML-структур находится
на странице OASIS http://www.oasis-open.org/cover/elementsAndAttrs.html.

3.3.2. Атрибуты и элементы


Одним из вопросов, с которым вы будете часто сталкиваться при разработке XML-структуры,
является вопрос, как смоделировать какой-либо элемент данных как субэлемент, или как
атрибут существующего элемента. Например, вы можете смоделировать заголовок слайда
либо как:

<slide>
<title>This is the title</title>
</slide>
либо как:

<slide title="This is the title">...</slide>


В некоторых случаях различные характеристики атрибутов и элементов облегчают выбор.
Рассмотрим сначала именно такие случаи, а затем перейдем к таким, где выбор более
неоднозначный.

3.3.2.1. Вынужденный выбор


Иногда выбор между атрибутом и элементом очень прост из-за их природы. Рассмотрим
несколько таких случаев:

Web-

Rendered by www.RenderX.com
Разработка структуры данных XML Стр. 49 из 626

Данные содержат подструктуры


В этом случае данные должны быть представлены как элемент. Он не может быть
представлен как атрибут, поскольку атрибуты могут содержать только простые строки. То
есть, если заголовок может содержать выделенный текст, как, например, The
<em>Best</em> Choice, то заголовок должен быть элементом.
Данные содержат несколько строк
Здесь тоже имеет смысл использовать элемент. Атрибуты должны быть простыми,
короткими строками, иначе они станут нечитаемыми, или вообще непригодными к
использованию.
Возможны несколько экземпляров
Если элемент данных может встретиться несколько раз, например параграфы в строке,
он должен быть представлен как элемент. Элемент, содержащий такие данные, может
иметь только один атрибут данного типа, но может иметь много субэлементов того же
типа.
Нет часто изменяемых данных
Если данные будут часто меняться при помощи редактора, имеет смысл представить их
как элемент. Многие из XML-редакторов легко позволяют модифицировать элементы
данных, в то время как к атрибутам иногда нелегко получить доступ.
Данные представляют собой короткую, простую строку, которая редко или никогда не
меняется
Такие данные могут быть представлены как атрибуты. Однако то, что вы можете сделать,
не означает то, что вы должны это сделать. Прочитайте следующий раздел "Стилистический
выбор", чтобы быть уверенным в своих действиях.
Использование DTD в том случае, когда данные ограничены небольшим количеством
фиксированных вариантов
Это как раз тот случай, когда имеет смысл использовать атрибуты. DTD может защитить
атрибут от получения значения, не входящего в предопределенный список, но не может
таким же образом ограничить элемент. (С другой стороны, схема может ограничить и
атрибуты и элементы.)

3.3.2.2. Стилистический выбор


Очень часто выбор не так тривиален, как описано выше. Когда выбор не является
вынужденным, вам нужно чувство "стиля" для направления хода мыслей. Следовательно,
нужно ответить на вопрос - что создает хороший XML-стиль, и почему.
Определение чувства стиля для XML, к сожалению, такое же неблагодарное дело, как и
определение "стиля" в искусстве или музыке. Однако существует несколько путей для
достижения этого. Цель этого раздела - изложить несколько полезных мыслей по вопросу
"XML-стиля".
Видимость
Один из эвристических подходов к выбору между XML-элементами и атрибутами использует
концепцию видимости. Если данные планируется показывать - отобразить для какого-либо
конечного пользователя - то они должны быть представлены как элемент. С другой стороны,

Web-

Rendered by www.RenderX.com
Стр. 50 из 626 Освоение XML

если информация предназначена для XML-обработки и никогда не показывается


пользователю, то ее лучше представить в виде атрибута. Например, в форме заказа обуви,
размер ее определенно может быть элементом. С другой стороны, кодовый номер
производителя разумно представить атрибутом.
Потребитель/поставщик
Другим подходом является ответ на вопрос - кто является потребителем и/или поставщиком
информации. Размер обуви вводится человеком-продавцом, то есть это - элемент. С другой
стороны кодовый номер производителя для данной модели обуви может быть передан в
приложение или записан в базу данных, то есть, он должен быть атрибутом. (Если бы он
вводился продавцом, он, возможно, был бы элементом.)
Контейнер против содержимого
Возможно, лучшим подходом к размышлению об элементах и атрибутах является
предположение, что элемент - это контейнер. Используя аналогию, содержимое контейнера
(вода или молоко) соответствует XML-данным, представленным как элементы. Такие
данные, по сути, являются переменными. С другой стороны, характеристики контейнера
(белый или синий кувшин) могут быть представлены как атрибуты. Такой тип информации
является более постоянным. Хорошим XML-стилем будет, следовательно, отделение
содержимого каждого контейнера от его характеристик.
Покажем эти эвристические подходы на практике. При показе слайдов тип слайда (для
администрации или для технического персонала) лучше всего представить в виде атрибута.
Это характеристика слайда, позволяющая выбрать или отложить слайд для конкретной
аудитории. Название слайда, с другой стороны, является частью его содержимого. Подход,
основанный на видимости, здесь тоже работает. При показе слайда его название
показывается, а тип слайда нет. Наконец в этом примере потребителем информации о
названии является аудитория, в то время как потребителем информации о типе является
программа презентации.

3.3.3. Нормализация данных


В разделе "Разработка структуры данных XML" показано, как создать внешний объект, на
который вы можете ссылаться в XML-документе. Такой объект обладает всеми
преимуществами модульной подпрограммы - изменение этой одной копии влияет на каждый
документ, к ней обращающийся. Процесс устранения избыточности известен под названием
нормализация, так что определение объектов - это один из хороших методов нормализации
ваших данных.
В HTML-файле единственным способом достичь такого типа модульности является
использование HTML-ссылок - естественно документ становится фрагментированным.
XML-сущности, с другой стороны, не страдают от такой фрагментации. Ссылка на сущность
работает как макроподстановка - содержимое объекта размещается в текущем месте,
создавая цельный документ, а не фрагментированный. И когда сущность определена во
внешнем файле, несколько документов могут ссылаться на нее.
Соображения для определения ссылки на сущность, следовательно, почти такие же, как
и те, какие вы применяете для разбиения на модули программного кода:
• Где бы вы ни обнаружили, что записываете один и тот же фрагмент более чем один
раз, подумайте об отдельной сущности. Это позволит вам записать ее один раз и
поставить ссылки в нескольких местах.

Web-

Rendered by www.RenderX.com
Разработка структуры данных XML Стр. 51 из 626

• Если существует вероятность изменения информации, особенно если она используется


более одного раза, определенно подумайте об определении сущности. Примером
является определение productName в виде сущности, для того чтобы можно было легко
изменить документы при изменении названия продукта.
• Если на сущность никогда не будет ссылок кроме текущего файла, определите ее в
local_subset DTD документа, точно также как вы определяете метод или внутренний
класс в программе.
• Если на сущность есть ссылки из нескольких документов, определите ее как внешнюю
сущность, так же как вы определяете любой общий класс в качестве внешнего класса.
Внешние сущности формируют XML-документ, который меньше по размерам, легче для
обновления и поддержки. Они могут также сделать результирующий документ несколько
более трудным для визуализации, также как и хороший OO-дизайн (объектно-
ориентированный) может быть легким для изменения, если вы понимаете его, но поначалу
тяжелым для просмотра, поскольку нужно мотать головой в разные стороны в поисках
нужных классов.
Вы можете также зайти слишком далеко при использовании сущностей. Впав в крайность,
вы можете создать ссылки на отдельную сущность для слова "the" - это не принесет вам
никакой выгоды, но вы можете сделать это.
Примечание: Чем больше сущность, тем менее вероятно, что ее изменение вызовет
побочные эффекты. При определении внешней сущности, охватывающей всю часть
инструкций по установке, например, при изменении в этой части очень маловероятно
испортить документы, зависящие от нее. Однако маленькие встроенные подстановки могут
быть более проблематичными. Например, если productName определен как сущность,
можно изменить имя в другую часть речи, и это может произойти. Предположим, что имя
продукта, например, "HtmlEdit". Это глагол. То есть вы пишете предложение, которое после
подстановки сущности выглядит так: "You can HtmlEdit your file...". Это предложение читается
нормально, поскольку глагол хорошо подходит в этот контекст. Но если имя случайно
изменить на "HtmlEditor", предложение станет таким: "You can HtmlEditor your file...", которое
явно не верно. Тем не менее, даже если такие подстановки могут иногда вызвать проблемы,
они могут потенциально сохранить много времени. (Одной из альтернатив было бы создание
сущностей с именем productNoun, productVerb, productAdj и productAdverb!)

3.3.4. Нормализация DTD


Также как вы можете нормализовать ваш XML-документ, вы можете нормализовать ваши
DTD-описания путем вынесения общих частей и создания ссылок на них при помощи
параметра. Этот процесс описан в руководства по SAX в разделе "Определение параметров
и условных секций". Выделение частей в DTD (называемое также как модуляризация или
нормализация) дает те же преимущества и недостатки, что и нормализованный XML-
документ - легко меняется, но немного трудно просматривается.
Вы можете также настроить условные DTD, как описано в разделе руководства по SAX
"Условные секции". Если количество и размер условных секций малы по сравнению с
размером целого DTD, вы можете создать "один источник" DTD, который сможете
использовать для разных целей. Если количество условных секций становится большим,
в результате может получиться сложный документ, который трудно редактировать.

Web-

Rendered by www.RenderX.com
Стр. 52 из 626 Начало работы с Tomcat

4. Начало работы с Tomcat


В этом разделе описываются процессы разработки, размещения и запуска простого Web-
приложения, состоящего из компонента JavaBeans™ - конвертора валют и клиентской
Web-страницы, созданной при помощи технологии JavaServer Pages (JSP). Это приложение
будет размещаться и запускаться в Tomcat - сервлете Java и контейнере JSP,
разработанном организацией The Apache Software Foundation (www.apache.org) и входящем
в Java Web Services Developer Pack (Java WSDP). Эта глава представляет собой введение
в использование Tomcat для размещения Web-служб и Web-приложений. Материал этой
главы является основой для других глав этого руководства.

4.1. Установка
Примечание: Перед началом работы с приложениями примера просмотрите инструкции
раздела "Об этом руководстве".

4.1.1. Получение кода примера


Исходный код примера находится в каталоге <JWSDP_HOME>/docs/tutorial/examples/gs/,
созданном при разархивации пакета руководства. Если вы просматриваете это руководство
в интерактивном режиме, этот пакет можно загрузить с:
http://java.sun.com/webservices/downloads/webservicestutorial.html

4.1.1.1. Схема кода примера


В этом примере приложения каталоги с исходным кодом организованы в соответствии со
статьей "Лучший практический подход к программированию Web-служб", находяйшейся в
файле <JSWDP_HOME>/docs/tomcat/appdev/deployment.html. В основном эта статья
рекомендует при создании приложения рассматривать организацию Web-приложения во
время его выполнения. Web-приложение в стандартной схеме определяется как иерархия
каталогов и файлов. Эта иерархия может быть доступна в распакованной форме, в которой
каждый каталог и файл существует в файловой системе отдельно, или в упакованной
форме, известной под названием архив Web-приложения, или WAR-файл (Web Application
Archive). Первый формат более полезен при разработке, в то время как второй формат
используется при распространении вашего приложения для установки.
Чтобы облегчить создание WAR-файла в нужном формате, удобно разместить файлы,
которые использует Tomcat при выполнении приложения, так, как требует сам WAR-формат.
В примере приложения <JWSDP_HOME>/docs/tutorial/examples/gs/ - это корневой каталог
с исходным кодом приложения. Приложение состоит из следующих файлов, находящихся
либо в каталоге /gs, либо его подкаталогах.
• - /src/converterApp/Converterbean.java - Компонент JavaBeans, содержащий методы get
и set для свойств yenAmount и euroAmount, используемых для конвертации долларов
США в йену и йены в евро.
• /web/index.jsp - Web-клиент, являющийся JSP-страницей и принимающий значение для
конвертации, кнопки для подтверждения значения и результат конвертации.
• /web/WEB-INF/web.xml - Дескриптор размещения для этого приложения. В этом простом
примере он содержит описание приложения.

Web-

Rendered by www.RenderX.com
Установка Стр. 53 из 626

• build.xml - Файл компоновки, использующий программу ant для компоновки и размещения


Web-приложения.
Более детальную информацию о WAR-файлах можно найти в разделе "Архивы Web-
приложения".
Ключевой рекомендацией "
Tomcat " является разделение иерархии каталогов, содержащих
исходный код, от иерархии каталогов, содержащих готовое к размещению приложение.
Выполнение этого разделения дает следующие преимущества:
• Содержимое каталогов с исходными кодами можно легко администрировать, перемещать
и копировать, если исполняемая версия приложения не смешивается с ними.
• Контролировать исходный код легче в каталогах, содержащих только файлы с исходным
кодом.
• Файлы, составляющие готовое к установке приложение, намного легче выбрать, когда
они размещены отдельно от остальных каталогов.
Как рассмотрено в разделе "Создание файлов компоновки и размещения для ant",
программа размещения ant упрощает создание и обработку такого типа иерархии каталогов.
В оставшейся части этого документа рассмотрены процессы создания, компоновки,
размещения и выполнения приложения примера. Если вы хотите пропустить информацию
по созданию приложения примера, можете перейти прямо к разделу "Краткий обзор".

4.1.2. Установка переменной PATH


Очень важно добавить каталоги bin установленных Java WSDP и J2SE SDK в начало вашей
переменной окружения PATH, для того чтобы начальные сценарии Java WSDP для Tomcat,
ant и deploytool, заменили сценарии из других инсталляций.
Примечание: Большинство примеров распространяются с конфигурационным файлом для
версии 1.4.1 ant - переносимой программы компоновки, входящей в Java WSDP. Если ваша
переменная PATH не указывает на каталог bin Java WSDP, многие из команд ant не будут
работать, поскольку версия ant, поставляемая с Java WSDP, устанавливает переменную
окружения jwsdp.home.

4.1.3. Создание файла свойств компоновки


Для того чтобы вызвать большинство из задач ant, вы должны поместить файл с именем
build.properties в ваш домашний каталог. В операционной системе Solaris ваш домашний
каталог обычно имеет формат /home/your_login_name. В операционных системах Windows
(например, Windows 2000) вашим домашним каталогом обычно являются C:\Documents и
Settings\yourProfile.
Файл build.properties содержит имя пользователя и пароль в текстовом формате, которые
соответствуют имени пользователя и паролю, указанным во время установки. Имя
пользователя и пароль, указанные вами во время установки Java WSDP, сохраняются в
файле <JWSDP_HOME>/conf/tomcat-users.xml.
В целях безопасности приложение Tomcat Manager проверяет, что именно вы (как
определено в файле build.properties) являетесь пользователем, которому позволено

Web-

Rendered by www.RenderX.com
Стр. 54 из 626 Начало работы с Tomcat

устанавливать и перезагружать приложения (как определено в tomcat-users.xml) перед


предоставлением вам доступа к серверу.
Если вы еще не создали файл build.properties в вашем домашнем каталоге, сделайте это
сейчас. Файл будет выглядеть примерно так:

username=your_username
password=your_password
Примечание: По соображениям безопасности сделайте файл build.properties не доступным
для чтения всем, кроме себя.
Файл tomcat-users.xml, который создается установщиком, выглядит примерно так:

<?xml version='1.0'?>
<tomcat-users>
<role rolename="admin"/>
<role rolename="manager"/>
<role rolename="provider"/>
<user username="your_username" password="your_password"
roles="admin,manager,provider"/>
</tomcat-users>

4.2. Краткий обзор


Теперь, когда вы загрузили приложение и установили ваше программное окружение для
выполнения приложений, мы приведем краткий обзор действий, необходимых для запуска
приложения. Каждое действие обсуждается более детально на указанных страницах.
1. Выполните действия из раздела "Установка".
2. Перейдите в каталог этого приложения - <JWSDP_HOME>/docs/tutorial/examples/gs
(см. раздел "Создание первого приложения").
3. Откомпилируйте исходные файлы, выполнив следующую команду (см. раздел
"Компоновка первого приложения с помощью ant").

ant build
Ошибки компиляции перечислены в разделе "Ошибки компиляции".
4. Запустите Tomcat, набрав в командной строке следующую команду (см. раздел "Запуск
Tomcat"):

<JWSDP_HOME>/bin/statup.sh ( Unix)

<JWSDP_HOME>\bin\startup (Microsoft Windows)

Web-

Rendered by www.RenderX.com
Создание первого приложения Стр. 55 из 626

5. Разместите Web-приложение при помощи ant, набрав в командной строке следующую


команду (см. раздел "Установка приложения при помощи ant"), или разместите Web-
приложение при помощи deploytool, следуя инструкциям раздела "Размещение
приложения при помощи deploytool":

ant install
Ошибки размещения рассматриваются в разделе "Ошибки размещения".
6. Запустите Web-броузер. Введите следующий URL для запуска примера приложения
(см. раздел "Запуск первого приложения"):

http://localhost:8080/GSApp
7. Остановите Tomcat, набрав следующую команду (см. раздел "Остановка Tomcat"):

<JWSDP_HOME>/bin/shutdown.sh ( Unix)

<JWSDP_HOME>\bin\shutdown (Microsoft Windows)

4.3. Создание первого приложения


Приложение примера содержит класс ConverterBean, Web-компонент, файл для компоновки
и запуска приложения и дескриптор размещения. Для этого примера мы создадим каталог
исходных файлов проекта с именем gs/. Все файлы этого примера создаются из этого
корневого каталога.

4.3.1. Компонент ConverterBean


Компонент ConverterBean используется совместно с JSP-страницей. Конечное приложение
является формой, позволяющей конвертировать американские доллары в иену и иену в
евро. Исходный код компонента ConverterBean находится в каталоге
<JWSDP_HOME>/docs/tutorial/examples/gs/src/converterApp/.

4.3.1.1. Кодирование компонента ConverterBean


Компонент ConverterBean этого примера содержит два свойства, yenAmount и euroAmount,
и методы get и set для этих свойств. Ниже приведен исходный код ConverterBean.

//ConverterBean.java
package converterApp;

import java.math.*;

Web-

Rendered by www.RenderX.com
Стр. 56 из 626 Начало работы с Tomcat

public class ConverterBean{

private BigDecimal yenRate;


private BigDecimal euroRate;
private BigDecimal yenAmount;
private BigDecimal euroAmount;

/** ConverterBean */
public ConverterBean() {
yenRate = new BigDecimal ("138.78");
euroRate = new BigDecimal (".0084");
yenAmount = new BigDecimal("0.0");
euroAmount = new BigDecimal("0.0");
}
public BigDecimal getYenAmount () {
return yenAmount;
}
public void setYenAmount(BigDecimal amount) {
yenAmount = amount.multiply(yenRate);
yenAmount = yenAmount.setScale(2,BigDecimal.ROUND_UP);
}
public BigDecimal getEuroAmount () {
return euroAmount;
}
public void setEuroAmount (BigDecimal amount) {
euroAmount = amount.multiply(euroRate);
euroAmount =
euroAmount.setScale(2,BigDecimal.ROUND_UP);
}
}

4.3.2. Web-клиент
Web-клиент содержится в JSP-странице <JWSDP_HOME>/docs/tutorial/exam-
ples/gs/web/index.jsp. JSP-страница представляет собой текстовый документ, содержащий
статическое и динамическое содержимое. Статическое содержимое - это шаблонные
данные, которые могут быть выражены в любом текстовом формате, таком как HTML,
WML, или XML. Динамическое содержимое создают JSP-элементы.

4.3.2.1. Кодирование Web-клиента


JSP-страница, index.jsp, используется для создания формы, появляющейся в Web-броузере
при запуске клиентского приложения. JSP-страница является обычной смесью статической
HTML-разметки и JSP-элементов. Если вы разрабатывали Web-страницы, вы, возможно,

Web-

Rendered by www.RenderX.com
Создание первого приложения Стр. 57 из 626

знакомы со структурными элементами HTML-документа (<head>, <body> и т.д.) и HTML-


командами, создающими форму <form> и меню <select>. Выделенные строки в примере
содержат следующие типы JSP-элементов:
• Директивы (<%@page: %>) импортируют классы в класс ConverterBean и устанавливают
тип содержимого, возвращаемого страницей.
• Элемент jsp:useBean объявляет, что страница будет использовать компонент bean,
записанный внутри и доступный из указанной области действия. Областью действия
по умолчанию является страница, так что вы можете не устанавливать ее явно в этом
примере.
• Элемент jsp:setProperty используется для установки свойств компонента JavaBeans в
JSP-странице.
• Элемент jsp:getProperty используется для извлечения свойств компонента JavaBeans
в JSP-странице.
• Скриптлеты (<% : %>) извлекают значение параметра amount, преобразовывает его в
BigDecimal и конвертирует значение в иену или евро.
• Выражения (<%= : %>) вставляют значение amount в ответ.
Ниже приведен исходный код index.jsp.

<%-- index.jsp --%>


<%@ page import="converterApp.ConverterBean,java.math.*" %>
<%@ page contentType="text/html; charset=ISO-8859-5" %>

<html>
<head>
<title>Currency Conversion Application</title>
</head>

<body bgcolor="white">
"<jsp:useBean id="converter"
class="converterApp.ConverterBean"/>

<h1><FONT FACE="ARIAL" SIZE=12>Currency Conversion Application


</FONT></h1>
<hr>
<p><FONT FACE="ARIAL" SIZE=10>Enter an amount to convert:</p>
</FONT>
<form method="get">
<input type="text" name="amount" size="25">
<br>
<p>
<input type="submit" value="Submit">

Web-

Rendered by www.RenderX.com
Стр. 58 из 626 Начало работы с Tomcat

<input type="reset" value="Reset">


</form>
<%
String amount = request.getParameter("amount");

if ( amount != null && amount.length() > 0 ) {

%>
<p><FONT FACE="ARIAL" SIZE=10><%= amount %> dollars are

<jsp:setProperty name="converter" property="yenAmount"


value="<%= new BigDecimal(amount)%>" />
<jsp:getProperty name="converter" property="yenAmount" /> Yen.

<p><%= amount %> Yen are

<jsp:setProperty name="converter" property="euroAmount"


value="<%= new BigDecimal(amount)%>" />
<jsp:getProperty name="converter" property="euroAmount" />
Euro. </FONT>

<%
}
%>

</body>
</html>

4.4. Компоновка первого приложения при помощи ant


Сейчас пример Web-приложения готов к компоновке.
Текущая редакция Java Web Services Developer Pack включает ant - make-программу,
являющуюся переносимой между платформами и разработанную организацией Apache
Software Foundation (http://www.apache.org). Документация по программе ant находится в
файле index.html в каталоге <JWSDP_HOME>/docs/ant/ вашей установки Java WSDP.
Примечание: Очень важно, чтобы ваша переменная окружения PATH содержала каталог
bin Java WSDP в самом начале. Если это не так, многие из команд ant не будут работать,
поскольку версия ant, поставляемая с Java WSDP, устанавливает переменную окружения
jwsdp.home, а другие версии ant - нет.
В этом примере программа ant используется для управления компиляцией исходных
файлов Java и созданием иерархии размещения. ant работает под управлением файла
компоновки, обычно называемого build.xml, который определяет требуемые действия. Этот
файл хранится в корневом каталоге вашей иерархии исходных файлов.

Web-

Rendered by www.RenderX.com
Компоновка первого приложения при помощи ant Стр. 59 из 626

Как и makefile, файл build.xml обеспечивает выполнение разных заданий, в том числе и
необязательных (таких как удаление домашнего каталога размещения, что бы вы могли
скомпоновать ваш проект с нуля). Этот файл компоновки включает задания по компиляции
приложения, установке приложения на работающем сервере, перезагрузке
модифицированного приложения на работающем сервере и удаление старых копий
приложения для повторной генерации их содержимого.
При использовании файла build.xml в этом примере для компиляции исходных файлов
создается временный каталог /build в корневом каталоге. Этот каталог содержит точный
образ двоичных установочных файлов вашего Web-приложения. Этот каталог удаляется
и создается заново по необходимости в процессе разработки, так что не редактируйте
файлы в этом каталоге.

4.4.1. Создание файла компоновки и размещения для ant


Чтобы использовать программу ant для этого примера, создайте файл build.xml в каталоге
gs/. Его исходный код приведен ниже.

<!-

-->
<project name="gs-example" default="build" basedir=".">
<target name="init">
<tstamp/>
</target>

<!-- PATH
-->
<property name="example" value="GSApp" />
<property name="path" value="/${example}"/>
<property name="build"
value="${jwsdp.home}/docs/tutorial/examples/${example}/build"
/>

<!--
Manager -->
<property name="url" value="http://localhost:8080/manager"/>
<property file="build.properties"/>
<property file="${user.home}/build.properties"/>

<!-- Ant
Manager -->

Web-

Rendered by www.RenderX.com
Стр. 60 из 626 Начало работы с Tomcat

<path id="classpath">
<fileset dir="${jwsdp.home}/common/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef name="install"
classname="org.apache.catalina.ant.InstallTask" />
<taskdef name="reload"
classname="org.apache.catalina.ant.ReloadTask" />
<taskdef name="remove"
classname="org.apache.catalina.ant.RemoveTask"/>

<target name="prepare" depends="init" description="Create


build directories.">
<mkdir dir="${build}" />
<mkdir dir="${build}/WEB-INF" />
<mkdir dir="${build}/WEB-INF/classes" />
</target>

<!-- -->

<target name="install" description="Install Web application"


depends="build">
<install url="${url}" username="${username}"
password="${password}" path="${path}"
war="file:${build}"/>
</target>

<target name="reload" description="Reload Web application"


depends="build">
<reload url="${url}" username="${username}"
password="${password}" path="${path}"/>
</target>

<target name="remove" description="Remove Web application">


<remove url="${url}" username="${username}"
password="${password}" path="${path}"/>
</target>

<target name="build" depends="prepare" description="Compile


app Java files and copy HTML and JSP pages" >

Web-

Rendered by www.RenderX.com
Размещение приложения Стр. 61 из 626

<javac srcdir="src" destdir="${build}/WEB-INF/classes">


<include name="**/*.java" />
<classpath refid="classpath"/>
</javac>
<copy todir="${build}/WEB-INF">
<fileset dir="web/WEB-INF" >
<include name="web.xml" />
</fileset>
</copy>
<copy todir="${build}">
<fileset dir="web">
<include name="*.html"/>
<include name="*.jsp" />
<include name="*.gif" />
</fileset>
</copy>
</target>

</project>

4.4.2. Компиляция исходных файлов


Для компиляции компонента JavaBeans (Converter.java) мы будем использовать программу
ant и запустим задние build в файле build.xml. Последовательность действий следующая:
1. В терминальном окне перейдите в каталог gs/, если вы создаете приложение
самостоятельно, или перейдите в каталог <JWSDP_HOME>/docs/tutorial/examples/gs/,
если вы компилируете файлы примеров, загруженные вместе с руководством.
2. Выполните следующую команду для компоновки Java-файлов.

ant build
Эта команда компилирует файлы для ConverterBean. Она размещает создаваемый
файл классов в каталог <JWSDP_HOME>/docs/tutorial/examples/Gapp/build/WEB-
INF/classes/converterApp, как указано в задании build в файле build.xml. Она также
помещает файл index.jsp в каталог GSApp/build и файл web.xml в каталог
GSApp/build/WEB-INF. Tomcat позволяет вам размещать приложение в такой
неупакованной форме. Размещение приложения рассматривается в разделе
"Размещение приложения".

4.5. Размещение приложения


В этой редакции Java WSDP существует два варианта размещения приложения:
использование программы ant и использование Application Deployment Tool. Для этого

Web-

Rendered by www.RenderX.com
Стр. 62 из 626 Начало работы с Tomcat

примера оба варианта требуют запуска Tomcat. Дополнительная информация по


размещению Web-приложений находится в разделе "Размещение Web-приложений".

4.5.1. Запуск Tomcat


Для запуска Tomcat введите следующую команду в терминальном окне.

<JWSDP_HOME>/bin/statup.sh ( Unix)

<JWSDP_HOME>\bin\startup (Microsoft Windows)

Начальный сценарий запускает задачу в фоновом режиме и затем сразу возвращается в


командную строку. Tomcat может запускаться полностью в течение нескольких минут.
Примечание: Начальный сценарий для Tomcat может выполняться несколько минут до
завершения. Для проверки выполнения Tomcat введите в вашем броузере http://local-
host:8080. Если отобразится начальный экран Tomcat, вы можете продолжать. Если
начальный экран не загрузится сразу, подождите несколько минут и повторите попытку.
Если через несколько минут начальный экран Tomcat все же не появился, обратитесь к
разделу по поиску неисправностей "Ошибка Unable to Locate the Server localhost:8080".
Документация по Tomcat находится в файле <JWSDP_HOME>/docs/tomcat/index.html.

4.5.2. Установка приложения при помощи ant


Web-приложение определяется в стандартной схеме как иерархия каталогов и файлов. В
этом примере иерархия доступна в неупакованной форме, при которой каждый каталог и
файл существует в файловой системе отдельно. В этом разделе рассматривается
процедура размещения приложения при помощи программы ant, определенная в разделе
"Создание файла компоновки и размещения для ant".
Контекст представляет собой имя, которое отображается в корневой каталог документов
Web-приложения. Контекстом для приложения GSApp является /GSAPP. Запрос URL
http://localhost:8080/GSApp/index.html извлекает файл index.html из корневого каталога
документов. Для установки приложения в Tomcat нужно проинформировать Tomcat о
доступности нового контекста.
Уведомление Tomcat о новом контексте производится при помощи задачи ant install в
файле build.xml. Задача ant install не требует перезагрузки Tomcat, но установленное
приложение не запоминается после перезагрузки Tomcat. Для постоянного размещения
приложения обратитесь к разделу "Размещение Web-приложений".
Задача ant install указывает менеджеру приложений Tomcat установить приложение с
контекстом, указанным в атрибуте path, и месторасположением, содержащим файлы Web-
приложения. Прочитайте раздел "Установка Web-приложений" для получения
дополнительной информации по этой процедуре. Для размещения этого Web-приложения
нужно выполнить следующие действия:
1. В терминальном окне перейдите в каталог GSApp/.
2. Выполните следующую команду для размещения файлов Web-приложения:

Web-

Rendered by www.RenderX.com
Размещение приложения Стр. 63 из 626

ant install
Эта команда копирует файл Web-клиента index.jsp в каталог
<JWSDP_HOME>/docs/tutorial/examples/GSApp/build/ и копирует файл классов
компонента JavaBeans ConverterBean.class в каталог <JWSDP_HOME>/docs/tutorial/exam-
ples/gs/build/WEB-INF/classes/converterApp/.

4.5.3. Размещение приложения при помощи deploytool


Программа Application Deployment Tool, называемая здесь и далее для краткости deploytool,
входит в данную редакцию Java WSDP. В этом разделе рассматривается использование
deploytool при создании WAR-файла (Web Application aRchive) для размещения вашего
приложения и управления вопросами безопасности. Для размещения приложения при
помощи deploytool выполните следующие действия:
1. Запустите Tomcat (если он еще не работает).
2. Запустите deploytool, программу командной строки, расположенную в каталоге bin
вашей установки Java WSDP.

<JWSDP_HOME>/bin/deploytool
3. В диалоговом окне Set Tomcat Server введите правильное имя пользователя и пароль.
Они устанавливаются при инсталляции Java WSDP или могут быть установлены при
помощи admintool. Информация по установке пользователей при помощи admintool
находится в разделе "Использование admintool".
4. Выберите OK для завершения размещения.
5. Выберите File.
6. Выберите New Web Application.
Отобразится мастер New Web Application. Этот мастер поможет спакетировать Web-
приложение в WAR-файл, определяя индивидуальные Web-компоненты и генерируя
дескриптор размещения для Web-приложения. Мы будем использовать мастер для
идентификации файлов в Web-приложении и для идентификации Web-компонентов в
дескрипторе размещения приложения.

4.5.3.1. Создание WAR-файла и идентификация файлов в Web-приложении


Для создания WAR-файла и указания мастеру New Web Application файлов, которые он
должен содержать, выполните следующие действия:
1. Выберите Next из страницы Introduction.
2. Отобразится раздел Create New Stand-Alone WAR Module на странице WAR File мастера.
3. Выберите кнопку Browse возле поля Module File Name и выберите путь к каталогу, в
котором надо создать этот файл, например, корневой каталог примера приложения,
сгенерированного ant, а именно <JWSDP_HOME>/docs/tutorial/examples/GSApp.
4. Введите имя WAR-файла, например, GSApp.war и нажмите кнопку Choose Module File.
5. Введите значение в поле WAR Display Name, например, GSApp.

Web-

Rendered by www.RenderX.com
Стр. 64 из 626 Начало работы с Tomcat

6. Нажмите кнопку Edit в поле Contents для добавления файлов к WAR-файлу.


7. Выберите ConverterBean.class из каталога <JWSDP_HOME>/docs/tutorial/exam-
ples/GSApp/build/WEB-INF/classes/converterApp, затем нажмите кнопку Add для
добавления этого файла к архиву. Это каталог, в котором был размещен файл в
сценарии build.xml.
8. Выберите index.jsp из каталога <JWSDP_HOME>/docs/tutorial/examples/GSApp/build/WEB-
INF, затем нажмите кнопку Add для добавления этого файла в архив. Это каталог, в
котором был размещен файл в сценарии build.xml.
9. Нажмите кнопку OK для выхода из диалогового окна Edit Contents.
10. Нажмите кнопку Next для продолжения.

4.5.3.2. Выбор типа компонентов


Следующей страницей мастера является страница Choose Component Type. На этой
странице мы выберем JSP-страницу в качестве типа создаваемого компонента:
1. Выберите JSP.
2. Выберите Next.

4.5.3.3. Установка свойств компонента


Следующей страницей мастера является страница Component General Properties. На этой
странице мы выберем JSP-файл:
1. Выберите index.jsp из списка JSP Filename.
2. Выберите Finish.
3. Выберите File, затем Save для сохранения WAR-файла.
Создается WAR-файл и его содержимое отображается на закладке General программы
Application Deployment Tool.

4.5.3.4. Размещение приложения


После создания WAR-файла мы можем разместить приложение. Для этого выполните
следующие действия. При выборе операции deploy созданный WAR-файл копируется в
Tomcat и Tomcat уведомляется о новом контексте. При помощи deploytool можно размещать
приложения только на localhost.
1. Выберите Tools, затем Deploy.
2. Нажмите OK для подтверждения того, что WAR готов к размещению.

4.5.3.5. Просмотр дескриптора размещения


При размещении приложения с использованием deploytool генерируется дескриптор
размещения. Для просмотра дескриптора размещения выберите Tools->Descriptor Viewer
из меню deploytool. Простой дескриптор размещения, сгенерированный для нашего примера
на предыдущих этапах, выглядит примерно так:

<?xmlversion="1.0"encoding="UTF-8"?>

Web-

Rendered by www.RenderX.com
Выполнение первого приложения Стр. 65 из 626

<!DOCTYPEweb-appPUBLIC'-
//SunMicrosystems,Inc.//DTDWebApplication2.3//EN''http://java.
sun.com/dtd/web-app_2_3.dtd'>

<web-app>
<display-name>GSApp</display-name>
<servlet>
<servlet-name>index</servlet-name>
<display-name>index</display-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>

4.6. Выполнение первого приложения


Для выполнения приложения необходимо проверить, работает ли Tomcat, затем запустить
JSP-страницу в Web-броузере.

4.6.1. Выполнение Web-клиента


Для запуска Web-клиента введите в адресной строке вашего броузера следующий URL:

http://localhost:8080/GSApp
В данной редакции Java WSDP Tomcat требует, чтобы хостом был localhost, который
является компьютером с выполняющимся Tomcat. В данном примере контекстом
приложения является "GSApp". Контекст определяется либо в файле build.xml, либо путем
ввода имени в поле WAR Display Name программы deploytool.
Для проверки приложения:
1. Введите 100 в поле "Enter an amount to convert".
2. Нажмите Submit.
На рисунке 3-1 изображено работающее приложение.

Web-

Rendered by www.RenderX.com
Стр. 66 из 626 Начало работы с Tomcat

Рисунок 3-1 Web-клиент ConverterBean

4.6.2. Остановка Tomcat


После завершения проверки и разработки приложения вы должны остановить Tomcat:

<JWSDP_HOME>/bin/shutdown.sh ( Unix)

<JWSDP_HOME>\bin\shutdown (Microsoft Windows)

4.7. Использование admintool


В пакет JWSDP входит программа Tomcat Web Server Administration Tool, называемый для
краткости здесь и далее admintool. Web-приложение admintool может быть использовано
для управления Tomcat во время его работы. Например, вы можете добавить и/или
настроить контексты, хосты, области и коннекторы, или настроить пользователей и роли
для безопасности, управляемой контейнером.
Для запуска admintool выполните следующие действия:
1. Запустите Tomcat как описано в разделе "Запуск Tomcat".
2. Запустите Web-броузер.
3. В адресной строке Web-броузера введите следующий URL:

http://localhost:8080/admin
Эта команда вызывает Web-приложение admin. Перед тем, как вы сможете использовать
это приложение, вы должны добавить ваши имя и пароль и связать с ними роль с
именем admin. Первоначальные имя пользователя и пароль, необходимые для доступа
к этой программе, устанавливаются во время инсталляции Java WSDP. Если вы забыли
имя пользователя и пароль, их можно посмотреть в файле <JWSDP_HOME>/conf/tomcat-

Web-

Rendered by www.RenderX.com
Использование admintool Стр. 67 из 626

users.xml при помощи любого текстового редактора. Этот файл содержит элемент
<user> для каждого конкретного пользователя и может выглядеть примерно так:

<user name="adeveloper" pasword="secret"


roles="admin, manager" />
4. Зарегистрируйтесь в admintool, используя имя пользователя и пароль, которым
назначена роль admin. Эта информация должна соответствовать имени пользователя
и паролю в файле build.properties.
5. После завершения выйдите из admintool, выбрав Logout в верхней панели.
admintooladmintool
• Сервер Tomcat.
• Службы, выполняющиеся на сервере Tomcat, плюс вложенные в Services элементы,
такие как Hosts, Contexts, Realms, Connectors, Loggers и Valves.
• Такие ресурсы, как Data Sources, Environment Entries и User Database.

4.7.1. Понимание ролей, групп и пользователей


Служба аутентификации сервера Tomcat включает следующие компоненты:
• Роли - абстрактное имя для разрешений доступа к отдельному набору ресурсов. Роль
можно сравнить с ключом, который может открыть замок. Многие люди могут иметь
копию ключа и замку все равно, кто вы, главное, что у вас есть правильный ключ.
• Пользователь - индивидуум (или прикладная программа), который аутентифицирован
(аутентификация рассматривалась в предыдущем разделе). Пользователь может иметь
набор ролей, назначенных ему и дающих право доступа к ресурсам, защищенным этими
ролями.
• Группа - набор аутентифицированных пользователей, классифицированных по общим
особенностям, например названию работы или пользовательскому профилю. Группы
тоже связываются с набором ролей, и каждый пользователь, являющийся членом
группы, наследует все роли, назначенные этой группе.
• Область - полная база данных ролей, пользователей и групп, идентифицирующая
разрешенных пользователей Web-приложения (или набора Web-приложений).
Управление ролями и пользователями

4.7.2. Добавление ролей при помощи admintool


Чтобы настроить роли для управляемой контейнером безопасности выполните следующие
действия. Добавления, удаления и изменения, сделанные в admintool, записываются в
файл tomcat-users.xml.
• Прокрутите вниз левую панель admintool до элемента User and Group Administration.
• Выберите Role Administration.
• Из списка Roles List выберите Create New Role.
• Введите Role Name и Description, например Customer или User.

Web-

Rendered by www.RenderX.com
Стр. 68 из 626 Начало работы с Tomcat

• Выберите Save.

4.7.3. Добавление пользователей при помощи admintool


Чтобы настроить пользователей для управляемой контейнером безопасности, выполните
следующие действия. Добавления, удаления и изменения, сделанные в admintool,
записываются в файл tomcat-users.xml.
• Прокрутите вниз левую панель admintool до элемента User and Group Administration.
• Выберите User Administration.
• Из списка Users List выберите Create New User.
• Введите User Name, Password и выберите Role для нового пользователя. Если вы
выберете роль admin для нового пользователя, он получит доступ к admintool.
• Выберите Save.

4.8. Модификация приложения


Поскольку Java WSDP предназначен для экспериментов, он поддерживает итеративную
разработку. Если вы изменили приложение, вы должны его повторно разместить и
перезагрузить. Задания, которые мы определили в файле build.xml, упрощают размещение
измененных ConverterBean и JSP-страницы.
В файле build.xml настраивается задание для установки приложения на работающем
сервере Tomcat и задание для перезагрузки приложения на работающем сервере Tomcat.
Эти задания назначаются при помощи программы Tomcat Server Manager Tool, называемой
Web-приложением manager. Вы можете использовать комбинацию имя
пользователя/пароль, которую вы установили при инсталляции Java WSDP, поскольку эта
комбинация будет иметь назначенную ей роль manager. Если вы забыли имя пользователя
и пароль, использовавшиеся при инсталляции, можно посмотреть файл
<JWSDP_HOME>/conf/tomcat-users.xml при помощи любого текстового редактора.
Справочная информация по Tomcat, поставляемая вместе с Java WSDP, содержит
документацию по приложению manager.

4.8.1. Модификация файла классов


Для изменения файла классов Java-компонента нужно изменить исходный код,
перекомпилировать его и повторно разместить приложение. При использовании Web-
приложения manager необязательно останавливать и снова запускать Tomcat для
повторного размещения измененного приложения. Например, предположим, что вы хотите
изменить курс валюты в свойстве yenRate компонента ConverterBean.
1. Отредактируйте файл ConverterBean.java в каталоге с исходными кодами.
2. Перекомпилируйте ConverterBean.java при помощи команды ant build.
3. Повторно разместите ConverterBean.java при помощи команды ant reload.
4. Перезагрузите JSP-страницу в Web-броузере.

Web-

Rendered by www.RenderX.com
Общие проблемы и их решение Стр. 69 из 626

4.8.2. Модификация Web-клиента


Для изменения JSP-страницы нужно изменить исходный код и повторно разместить
приложение. При использовании Web-приложения manager необязательно останавливать
и снова запускать Tomcat для повторного размещения измененного Web-клиента. Например,
предположим, что вы хотите изменить шрифт или добавить дополнительный описательный
текст в JSP-страницу. Для изменения Web-клиента:
1. Отредактируйте файл index.jsp в каталоге с исходными кодами.
2. Перезагрузите Web-приложение при помощи команды ant reload.
3. Перезагрузите JSP-страницу в Web-броузере.

4.9. Общие проблемы и их решение


Используйте приведенные ниже рекомендации для поиска неисправностей при
возникновении любой проблемы во время создания, компиляции, установки, размещения
и выполнения приложения примера.

4.9.1. Ошибки при запуске Tomcat


4.9.1.1. Ошибка "Out of Environment Space" ("Не хватает пространства окружения")
Симптом: Ошибка "out of environment space" при выполнении пакетных файлов startup и
shutdown в операционных системах Microsoft Windows 9X/ME.
Решение: В проводнике нажмите правой кнопкой мыши на файлах startup.bat и shutdown.bat.
Выберите Properties, затем закладку Memory. Увеличьте поле Initial Environment до значения,
например, 4096. Выберите Apply.
После выбора Apply в каталоге, используемом для запуска и остановки контейнера,
создадутся файлы для быстрого запуска этих программ.

4.9.1.2. Ошибка "Unable to Locate the Server localhost:8080" ("Невозможно обнаружить


сервер localhost:8080")
Симптом: ошибка "unable to locate the server" при попытке загрузить Web-приложение в
броузер.
Решение: Полная загрузка Tomcat может занять некоторое время, так что убедитесь, что
вы дали серверу по крайней мере 5 минут, прежде чем продолжить исправление
неисправностей. Для проверки выполнения Tomcat введите в ваш броузер URL
http://localhost:8080. После отображения начальной страницы Tomcat можно продолжать
работу. Если начальный экран не загрузился сразу, подождите несколько минут и повторите
попытку. Если Tomcat снова не загружается, проверьте файлы журналов (log-файлы), как
поясняется ниже, для получения дальнейшей информации по неисправности.
При запуске Tomcat он инициализируется и загружает Web-приложения из
<JWSDP_HOME>/webapps. Если вы запускаете Tomcat при помощи сценария startup.sh,
сообщения сервера записываются в файл <JWSDP_HOME>/logs/catalina.out. Процесс
загрузки Web-приложений можно посмотреть в файле
<JWSDP_HOME>/logs/jwsdp_log.<date>.txt.

Web-

Rendered by www.RenderX.com
Стр. 70 из 626 Начало работы с Tomcat

4.9.2. Ошибки компиляции


4.9.2.1. Server returned HTTP response code: 401 for URL : (Сервер возвратил код ответа
HTTP: 401 для URL :)
Симптом: После выполнения команды ant install появляются следующие сообщения:

BUILD FAILED
/home/you/gs/build.xml:44:
java.io.IOException: Server returned HTTP response code: 401
for URL: http://localhost:8080/manager/install?path= ...
Решение: Проверьте, что имя пользователя и пароль в вашем файле build.properties
соответствуют имени пользователя и паролю с назначенной ролью manager в файле
tomcat-users.xml. Дополнительная информация по настройке этой информации находится
в разделе "Создание файла свойств компоновки".

4.9.2.2. Ant Cannot Locate the Build File (ant не может найти файл компоновки)
Симптом: После выполнения команды ant build появляются следующие сообщения:

Buildfile: build.xml does not exist!


Build failed.
Решение: Запустите ant из каталога <JWSDP_HOME>/docs/tutorial/gs/, или из каталога с
созданным вами приложением. Если вы хотите запустить ant из текущего каталога, вы
должны указать файл компоновки в командной строке. Например, вы могли бы выполнить
следующую команду:

ant -buildfile

<JWSDP_HOME>/docs/tutorial/examples/gs/build.xml

build

4.9.2.3. The Compiler Cannot Resolve Symbols (компилятор не может разрешить символы)
Симптом: После выполнения команды ant build компилятор отображает множество ошибок,
в том числе и эти:

cannot resolve symbol


. . .
BUILD FAILED
. . .
Compile failed, messages should have been provided

Web-

Rendered by www.RenderX.com
Общие проблемы и их решение Стр. 71 из 626

Решение: Убедитесь, что вы используете версию ant, поставляемую с Java WSDP. Лучшим
способом дать гарантию, что вы используете нужную версию, является задание полного
пути к файлу ant при построении приложения <JWSDP_HOME>/bin/ant build. Другие версии
могут не иметь функциональности, ожидаемой файлами компоновки приложения примера.

4.9.2.4. Ошибка "Connection refused" ("В соединении отказано")


Симптом: После выполнения команды ant install из командной строки вы получаете
следующее сообщение:

<JWSDP_HOME>/docs/tutorial/examples/gs/build.xml:82:

java.net.ConnectException: Connection refused

Решение: Tomcat не полностью запустился. Подождите несколько минут, затем повторите


попытку установки приложения. Более подробная информация по этой проблеме находится
в разделе "Ошибка Unable to Locate the Server localhost:8080".

4.9.2.5. При попытке выполнения задания на установку система, по всем признакам, виснет.
Симптом: После выполнения команды ant install система зависает.
Решение: Начальный сценарий Tomcat запускает сервер в фоновом режиме и сразу же
возвращает пользователя к приглашению командной строки. Даже если вы вернулись в
командную строку, начальный сценарий может не запустить Tomcat полностью. Если
задание по установке не запускается мгновенно, подождите несколько минут и повторите
установку. Для проверки выполнения Tomcat перейдите в вашем броузере на страницу
http://localhost:8080. Когда отобразится начальный экран Tomcat, вы можете продолжать
работу. Если начальный экран не загрузился сразу, подождите несколько минут и повторите
попытку. Если Tomcat все равно не загружается, проверьте log-файлы, как описано ниже,
для получения дальнейшей информации по неисправности.
При запуске Tomcat он инициализируется и загружает Web-приложения из
<JWSDP_HOME>/webapps. Если вы запускаете Tomcat при помощи сценария startup.sh,
сообщения сервера записываются в файл <JWSDP_HOME>/logs/catalina.out. Процесс
загрузки Web-приложений можно посмотреть в файле
<JWSDP_HOME>/logs/jwsdp_log.<date>.txt.

4.9.3. Ошибки размещения


4.9.3.1. Failure to run client application (Ошибка при выполнении клиентского приложения)
Симптом: Броузер отвечает, что страница не может быть найдена (HTTP 404).
Решение: Начальный сценарий Tomcat запускает сервер в фоновом режиме и сразу же
возвращает пользователя к командной строке. Даже если вы вернулись в командную
строку, начальный сценарий может не запустить Tomcat полностью. Если Web-клиент не
запускается мгновенно, подождите несколько минут и повторите загрузку Web-клиента.
Более подробная информация по этой проблеме находится в разделе "Ошибка Unable to
Locate the Server localhost:8080".

Web-

Rendered by www.RenderX.com
Стр. 72 из 626 Начало работы с Tomcat

4.9.3.2. The localhost Machine Is Not Found (Компьютер localhost не найден)


Симптом: Броузер сообщает, что страница не может быть найдена (HTTP 404).
Решение: Иногда, если вы работаете с прокси, брандмауэр не разрешает вам получить
доступ к localhost. Для устранения этой ошибки измените настройки прокси так, чтобы он
не использовался при доступе к localhost.
Для этого, например, в броузере Netscape Navigator™ выберите Edit->Preferences-
>Advanced->Proxies и отметьте No Proxy for: localhost. В Internet Explorer выберите Tools-
>Internet Options->Connections->LAN Settings.

4.9.3.3. The Application Has Not Been Deployed (Приложение не размещено)


Симптом: Броузер сообщает, что страница не может быть найдена (HTTP 404).
Решение: Разместите приложение. Детально об этом - в разделе "Размещение приложения".

4.9.3.4. Ошибка "Build Failed: Application Already Exist at Path" (Компоновка неудачна:
приложение уже существует)
Симптом: После выполнения команды ant install в терминальном окне отображается такое
сообщение:

[install] FAIL - Application already exists at path /GSApp

BUILD FAILED

<JWSDP_HOME>/docs/tutorial/examples/gs/build.xml:82: FAIL -

Application already exists at path /GSApp

Это приложение уже установлено. Если вы сделали изменения в приложение после его
установки, используйте команду ant reload для обновления приложения в Tomcat.

4.9.3.5. HTTP 500: No Context Error (HTTP 500: Ошибка: нет контекста)
Симптом: Отображается сообщение No Context Error при попытке запуска размещенного
приложения.
Решение: Эта ошибка означает, что Tomcat загружен, но не знает о вашем приложении.
Если вы не разместили приложение - это будет вашим первым действием. Если вы успешно
разместили приложение при помощи команды ant remove, ant build, ant install и все еще
получаете ошибку - продолжайте чтение.

Web-

Rendered by www.RenderX.com
Дополнительная информация Стр. 73 из 626

Если Tomcat загружен, но не загрузил еще все свои существующие контексты, вы тоже
получите эту ошибку. Продолжайте нажимать кнопки Reload или Refresh вашего броузера,
пока приложение не загрузится или вы не получите какое-либо другое сообщение об
ошибке.

4.10. Дополнительная информация


• Средство администрирования Tomcat. Обратитесь к разделу "Программа
администрирования Tomcat" для дополнительной информации по использованию
admintool при конфигурации поведения Tomcat без его остановки и перезапуска.
• Справочник по конфигурации Tomcat. Для дополнительной информации по элементам,
которые можно использовать для настройки поведения Tomcat, обратитесь к Справочнику
по конфигурации Tomcat, который можно найти на странице
<JWSDP_HOME>/docs/tomcat/config/index.html.
• Class Loader How-To. В этом документе обсуждаются решения, которые прикладные
разработчики и установщики должны следовать в вопросе месторасположения файлов
классов и ресурсов, чтобы сделать их доступными для Web-приложений. Этот документ
находится на странице <JWSDP_HOME>/docs/tomcat/class-loader-howto.html.
• JNDI Resources How-To. В этом документе обсуждается конфигурирование JNDI-
ресурсов, Tomcat Standard Resource Factories, JDBC Data Sources и Custom Resource
Factories. Этот документ находится на странице <JWSDP_HOME>/docs/tomcat/jndi-
resources-howto.html.
• Manager Application How-To. В этом документе рассматривается использование Manager
Application для размещения нового Web-приложения, снятия существующего приложения,
или перезагрузки существующего приложения без необходимости остановки и
перезапуска Tomcat. Этот документ находится на странице
<JWSDP_HOME>/docs/tomcat/manager-howto.html.
• Proxy Support How-To. В этом документе рассмотрена работа с прокси-сервером (или
Web-сервером, который настроен на выполнение функций прокси-сервера). В частности,
в этом документе обсуждаются вопросы управления значениями, возвращаемыми
вызовами из Web-приложения, которые запрашивают имя сервера и номер порта, на
которые запрос перенаправляется для обработки. Этот документ может быть найден
на странице <JWSDP_HOME>/docs/tomcat/proxy-howto.html.
• Realm Configuration How-To. В этом документе рассматриваются вопросы настройки
Tomcat для поддержки управляемой контейнером безопасности при помощи соединения
с существующей базой данных имен пользователей, паролей и ролей пользователей.
Этот документ находится на странице <JWSDP_HOME>/docs/tomcat/realm-howto.html.
• Security Manager How-To. В этом документе рассматриваются вопросы использования
SecurityManager при работе Tomcat для защиты сервера от несанкционированных
сервлетов, JSP-страниц, JSP-компонентов и библиотек тегов. Этот документ находится
на <JWSDP_HOME>/docs/tomcat/security-manager-howto.html.
• SSL Configuration How-To. В этом документе рассмотрены вопросы установки и настройка
поддержки SSL в Tomcat. Настройка поддержки SSL в Tomcat при помощи Java WSDP
рассмотрена в разделе "Установка и настройка поддержки SSL в Tomcat". Документация
Tomcat в <JWSDP_HOME>/docs/tomcat/ssl-howto.html тоже обсуждает этот вопрос,

Web-

Rendered by www.RenderX.com
Стр. 74 из 626 Web-приложения

однако, информация в данном руководстве является более новой для версии Tomcat,
поставляемой с Java WSDP.

5. Web-приложения
Web-приложение представляет собой динамическое расширение Web-сервера. Существует
два типа Web-приложений:
• Ориентированные на представление. Ориентированное на представление Web-
приложение в ответ на запрос генерирует динамические Web-страницы, содержащие
различные типы языка разметки (HTML, XML и т.д.).
• Ориентированные на службы. Ориентированное на службы Web-приложение реализует
конечную точку для разделенной на модули Web-службы. Ориентированное на службы
Web-приложение часто вызывается ориентированными на представление приложениями.
В платформе динамическое расширение возможностей Web-сервера Java 2 обеспечивают
Web-компоненты. Web-компонентами являются либо Java-сервлеты, либо JSP-страницы.
Сервлеты представляют собой классы языка программирования Java, которые динамически
обрабатывают запросы и генерируют ответы. JSP-страницы представляют собой текстовые
документы, которые выполняются как сервлеты, но обеспечивают более естественный
подход к созданию статического содержимого. Хотя сервлеты и JSP-страницы
взаимозаменяемы, каждая из этих технологий имеет свои преимущества. Сервлеты больше
подходят для ориентированных на службы Web-приложения и для управления некоторыми
функциями ориентированных на представление приложений, такими как распределение
запросов и обработка нетекстовых данных. JSP-страницы больше подходят для генерации
текстовой разметки, такой как HTML, SVG, WML и XML.
Web-компоненты поддерживаются службами исполняющей платформы, называемой Web-
контейнером. В Java WSDP Web-компоненты выполняются в Web-контейнере Tomcat.
Web-контейнер обеспечивает такие службы как распределение запросов, безопасность,
параллельная работа и управление циклом жизни. Он также предоставляет Web-
компонентам доступ к таким API как служба имен, транзакции и электронная почта.
В этой главе описываются процедуры организации, конфигурации, установки и размещения
Web-приложений. В главах 9 и 10 рассматривается разработка Web-компонентов для
ориентированных на службы Web-приложений. В главах 12 и 13 рассматривается разработка
Web-компонентов для ориентированных на представление Web-приложений. Многие из
возможностей технологии JSP определяются технологией Java Servlet, поэтому вы должны
изучить этот материал, даже если не планируете писать сервлеты.
Большинство Web-приложений используют протокол HTTP, и поддержка HTTP является
важнейшим аспектом Web-компонентов. Краткая сводка возможностей протокола HTTP
приведена в разделе "Обзор HTTP".

5.1. Жизненный цикл Web-приложения


Web-приложение состоит из Web-компонентов, файлов статических ресурсов, таких как
изображения, и вспомогательных классов и библиотек. Java WSDP предоставляет много
служб поддержки, расширяющих возможности Web-компонентов и облегчающих их
разработку. Однако, из-за существования этих служб, процессы создания и выполнения

Web-

Rendered by www.RenderX.com
Жизненный цикл Web-приложения Стр. 75 из 626

Web-приложений отличаются от процессов создания и выполнения обычных автономных


Java-классов.
Некоторые аспекты поведения Web-приложения могут быть настроены во время его
размещения. Информация по конфигурации хранится в текстовом файле в XML-формате,
называемом дескриптором размещения Web-приложения. Дескриптор размещения должен
соответствовать схеме, описанной в спецификации сервлетов Java.
Процесс создания, размещения и выполнения Web-приложения может быть кратко описан
следующим образом:
1. Разработать код Web-компонента (возможно, включая дескриптор размещения)
2. Скомпоновать компоненты Web-приложения вместе со всеми статическими ресурсами
(например, изображениями) и вспомогательными классами, к которым обращается
компонент.
3. Установить, или разместить, приложение в Web-контейнере.
4. Обратиться к URL, ссылающемуся на Web-приложение.
Разработка кода Web-компонента рассматривается в следующих главах. Шаги 2, 3 и 4
более подробно рассматриваются в следующих разделах и иллюстрируются с помощью
ориентированного на представление приложения Hello. Это приложение позволяет
пользователю ввести имя в HTML-форму (рисунок 4-1) и отобразить приветствие после
подтверждения имени (рисунок 4-2):

Рисунок 4-1 Форма приветствия

Рисунок 4-2 Ответ

Web-

Rendered by www.RenderX.com
Стр. 76 из 626 Web-приложения

Приложение "Hello, World" состоит из двух Web-компонентов, генерирующих приветствие


и ответ. В данном руководстве имеется два варианта этого приложения: версия с
сервлетами Hello1, в которой компоненты реализуются двумя классами сервлетов, Greet-
ingServlet.java и ResponseServlet.java, и JSP-версия Hello2, в которой компоненты
реализуются двумя JSP-страницами, greetings.jsp и response.jsp. Эти два варианта
используются также для иллюстрации задач, возникающих при пакетировании, размещении
и выполнении приложения, содержащего Web-компоненты. Если вы просматриваете это
руководство в интерактивном режиме, вам необходимо загрузить полный пакет руководства
для получения исходных кодов примера. Обратитесь к разделу "Запуск примеров".

5.2. Архивы Web-приложения


Для распространения Web-приложения его надо спакетировать в архив Web-приложения
(WAR), похожий на JAR-архив, используемый при пакетировании библиотек Java-классов.
Кроме Web-компонентов архив Web-приложения может содержать другие файлы, включая
следующие:
• Серверные классы утилит (компоненты баз данных, корзины покупок и т.д.). Часто эти
классы соответствуют архитектуре компонентов JavaBeans.
• Статическое содержимое (HTML, изображения, звуковые файлы и т.д.)
• Клиентские классы (апплеты и классы утилит).
Web-компоненты и файлы статического содержимого называются Web-ресурсами.
Web-приложение может запускаться из WAR-файла или из неупакованного каталога,
организованного в таком же формате, что и WAR.

5.2.1. Структура каталога WAR


Каталогом верхнего уровня в WAR является корневой каталог документов приложения.
Корневой каталог документов представляет собой место, где хранятся JSP-страницы,
клиентские классы и архивы, а также статические Web-ресурсы.
Корневой каталог документов содержит подкаталог WEB-INF, который содержит следующие
файлы и каталоги:
• web.xml - дескриптор размещения Web-приложения
• Файлы дескрипторов библиотек тегов (см. раздел "Дескрипторы библиотек тегов")
• clases - каталог, содержащий серверные классы: сервлеты, классы утилит и компоненты
JavaBeans
• lib - каталог, содержащий JAR-архивы и библиотеки (библиотеки тегов и все библиотеки
утилит, вызываемые серверными классами)
Вы можете также создавать свои собственные подкаталоги (то есть, каталоги пакета) либо
в корневом каталоге документов, либо в каталоге WEB-INF/classes.

5.2.2. Структура каталога примера


В целях облегчения итеративной разработки и хранения исходных файлов Web-приложения
отдельно от компилированных файлов исходный код примеров руководства хранится в
каталоге mywebapp каждого приложения следующей структуры:

Web-

Rendered by www.RenderX.com
Архивы Web-приложения Стр. 77 из 626

• build.xml - файл компоновки для ant


• context.xml - необязательный конфигурационный файл приложения
• src - исходный Java-код сервлетов и компонентов JavaBeans
• web - JSP-страницы и HTML-страницы, изображения
Файл компоновки для ant (build.xml), распространяемый с примерами, содержит задания
для создания неупакованной WAR-структуры в подкаталоге build каталога mywebapp,
копирования и компиляции файлов в этот каталог, а также вызова команд manager (см.
раздел "Менеджер Web-приложений Tomcat") при помощи специальных команд ant для
установки, перезагрузки, удаления, размещения и отмены размещения приложений. Такими
заданиями ant для примеров руководства являются:
• prepare - Создает каталог build и подкаталоги WAR.
• build - Компилирует и копирует файлы Web-приложения mywebapp в каталог build.
• install - Указывает Tomcat установить приложение (см. раздел "Установка Web-
приложений") при помощи команды ant install.
• reload - Указывает Tomcat перезагрузить приложение (см. раздел "Обновление Web-
приложений") при помощи команды ant reload.
• deploy - Указывает Tomcat разместить приложение (см. раздел "Размещение Web-
приложений") при помощи команды ant deploy.
• undeploy - Указывает Tomcat отменить размещение приложения (см. раздел "Отмена
размещения Web-приложений") при помощи команды ant undeploy.
• remove - Указывает Tomcat удалить приложение (см. раздел "Удаление Web-
приложений") при помощи команды ant remove.

5.2.3. Создание WAR


Вы можете вручную создать WAR двумя способами:
• При помощи программы JAR, поставляемой с J2SE SDK. Просто выполните следующую
команду в каталоге build примера:

jar cvf mywebapp.war


• При помощи команды ant war
Оба эти метода требуют создания дескриптора размещения Web-приложения.
Можно спакетировать приложение в WAR при помощи deploytool. При использовании
deploytool он создает дескриптор размещения Web-приложения, основываясь на
информации, введенной в мастерах и инспекторах deploytool. Для компоновки и
пакетирования приложения Hello1 в WAR с именем hello1.war:
1. В терминальном окне перейдите в каталог <JWSDP_HOME>/docs/tutorial/exam-
ples/web/hello1.
2. Выполните команду ant build. Задание build вызовет все необходимые компиляции и
скопирует файлы в каталог <JWSDP_HOME>/docs/tutorial/examples/web/hello1/build.

Web-

Rendered by www.RenderX.com
Стр. 78 из 626 Web-приложения

3. Запустите deploytool.
4. Создайте Web-приложение с именем hello1.
A. Выберите File->New Web Application.
B. Выберите Create New Stand-Alone WAR Module.
C. Нажмите Browse и окне выбора файлов перейдите в <JWSDP_HOME>/docs/tuto-
rial/examples/web/hello1.
D. В поле File Name введите hello1.
E. Нажмите Choose Module File.
F. В поле WAR Display Name введите hello1.

5. Добавьте Web-компонент greeting и все содержимое приложения Hello1.


A. Нажмите Edit для добавления файлов содержимого.
B. В диалоговом окне Edit Contents выберите <JWSDP_HOME>/docs/tutorial/exam-
ples/web/hello1/build/duke.waving.gif и нажмите Add. Перейдите в WEB-INF/classes
и выберите greetingServlet.class и ResponseServlet.class и нажмите Add. Нажмите
OK.
C. Нажмите Next.
D. Выберите переключатель Servlet.
E. Нажмите Next.
F. Выберите GreetingServlet из поля списка Servlet Class.
G. Нажмите Finish.

6. Добавьте Web-компонент response.


A. Выберите File->Edit Web Application.
B. Нажмите переключатель Add to Existing WAR Module и выберите hello1 из поля
списка. Поскольку WAR содержит все классы сервлетов, вам больше не нужно
добавлять какое-либо содержимое.
C. Нажмите Next.
D. Выберите переключатель Servlet.
E. Нажмите Next.
F. Выберите ResponseServlet из поля списка Servlet Class.
G. Нажмите Finish.

5.3. Настройка Web-приложений


Web-приложения настраиваются при помощи элементов, содержащихся в дескрипторах
размещения Web-приложения. Вы можете создавать дескрипторы либо вручную при
помощи текстового редактора, либо используя deploytool для их автоматической генерации.

Web-

Rendered by www.RenderX.com
Настройка Web-приложений Стр. 79 из 626

В следующих разделах руководства приведено краткое введение в свойства Web-


приложения, которые обычно нужно настраивать. Несколько настраиваемых параметров
безопасности рассмотрены в разделе "Безопасность Web-приложений". Полный список и
описание свойств приведен на странице "Спецификация сервлетов Java".
В следующих разделах несколько примеров демонстрируют процедуры настройки
приложения "Hello, World". Если это приложение не использует определенные функции
настройки, используются другие примеры для демонстрации элементов дескриптора
размещения и описываются стандартные процедуры для установки свойств при помощи
deploytool. Более сложные примеры, демонстрирующие использование deploytool,
приводятся в разделах "Пример сервлетов" и "Пример JSP-страниц".
Примечание: Элементы дескриптора должны появляться в дескрипторе размещения в
следующем порядке: icon, display-name, description, distributable, context-param, filter, filter-
mapping, listener, servlet, servlet-mapping, session-config, mime-mapping, welcome-file-list,
error-page, taglib, resource-env-ref, resource-ref, security-constraint, login-config, security-role,
env-entry.

5.3.1. Пролог
Поскольку дескриптор размещения представляет собой XML-документ, для него необходим
пролог. Пролог дескриптора размещения Web-приложения выглядит следующим образом:

<?xml version="1.0" encoding="ISO-8859-1"?>


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

5.3.2. Пути псевдонимов


Когда Tomcat получает запрос, он должен определить, какой Web-компонент должен его
обработать. Tomcat делает это путем отображения пути URL, содержащегося в запросе,
в Web-компонент. Путь URL содержит корневой каталог контекста (описанный в разделе
"Установка Web-приложений") и путь псевдонима

http://<host>:8080/context_root/alias_path
Перед тем как к сервлету можно будет получить доступ, Web-контейнер должен иметь по
крайней мере один путь псевдонима для компонента. Путь псевдонима должен начинаться
со знака / и заканчиваться строкой или шаблоном с расширением (*.jsp, например).
Поскольку Web-контейнер автоматически отображает путь псевдонима, который
заканчивается *.jsp, вам не обязательно указывать путь псевдонима для JSP-страницы,
пока вы не захотите обратиться к странице по имени, отличному от имени ее файла. В
примере, рассмотренном в разделе "Обновление Web-приложений", страница приветствия
имеет псевдоним, а обращение к response.jsp происходит по имени файла.
Для настройки отображения сервлет-версии приложения Hello в дескрипторе размещения
вы должны добавить в него следующие элементы servlet и servlet-mapping. Чтобы
определить псевдоним для JSP-страницы вы должны заменить субэлемент servlet-class
субэлементом jsp-file в элементе servlet.

Web-

Rendered by www.RenderX.com
Стр. 80 из 626 Web-приложения

<servlet>
<servlet-name>greeting</servlet-name>
<display-name>greeting</display-name>
<description>no description</description>
<servlet-class>GreetingServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>response</servlet-name>
<display-name>response</display-name>
<description>no description</description>
<servlet-class>ResponseServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greeting</servlet-name>
<url-pattern>/greeting</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>response</servlet-name>
<url-pattern>/response</url-pattern>
</servlet-mapping>
Для настройки отображения сервлет-версии приложения Hello выполните следующие
действия в deploytool:
1. Выберите WAR hello1.
2. Выберите Web-компонент GreetingServlet.
3. Выберите закладку Aliases.
4. Нажмите Add для добавления нового отображения.
5. Введите /greeting в списке псевдонимов.
6. Выберите Web-компонент ResponseServlet.
7. Нажмите Add.
8. Введите /response в списке псевдонимов.

5.3.3. Параметры контекста и инициализации


Web-компоненты в WAR совместно используют объект, представляющий их контекст
приложения (см. раздел "Получение доступа к Web-контексту"). Вы можете передать
параметры в контекст или Web-компонент. Для этого необходимо добавить элемент context-
param или init-param в дескриптор размещения Web-приложения. context-param является
субэлементом элемента web-app верхнего уровня. init-param является субэлементом
элемента servlet. Ниже приведен элемент, используемый для объявления параметра

Web-

Rendered by www.RenderX.com
Настройка Web-приложений Стр. 81 из 626

контекста, который устанавливает пакет ресурсов для примера, рассматриваемого в главе


16:

<web-app>
<context-param>
<param-name>
javax.servlet.jsp.jstl.fmt.localizationContext
</param-name>
<param-value>messages.BookstoreMessages</param-value>
</context-param>
...
</web-app>
Для добавления параметра контекста в deploytool выполните следующие действия:
1. Выберите WAR.
2. Выберите закладку Context.
3. Нажмите Add.
Для добавления параметра инициализации в deploytool выполните следующие действия:
1. Выберите Web-компонент.
2. Выберите закладку Init Param.
3. Нажмите Add.

5.3.4. Перехватчики событий


Чтобы добавить класс перехватчика событий (описанного в разделе "Обработка событий
жизненного цикла сервлета"), необходимо добавить элемент listener в дескриптор
размещения Web-приложения. Ниже приведен элемент, который объявляет класс
перехватчика событий, используемого в главах 12 и 16:

<listener>
<listener-class>listeners.ContextListener</listener-class>
</listener>
Для добавления перехватчика событий в deploytool выполните следующие действия:
1. Выберите WAR.
2. Выберите закладку Event Listeners.
3. Нажмите Add.
4. Выберите класс перехватчика из нового поля в области Event Listener Classes.

Web-

Rendered by www.RenderX.com
Стр. 82 из 626 Web-приложения

5.3.5. Отображения фильтров


Web-контейнер использует объявления отображений фильтров для принятия решения,
какие фильтры применить к запросу и в какой последовательности (см. раздел "Установка
отображений фильтров"). Контейнер согласует URI запроса с сервлетом, как описано в
разделе "Пути псевдонимов". Для определения того, какие фильтры применить, он согласует
объявления отображений фильтров по имени сервлета или по шаблону URL. Порядок
вызова фильтров определяется порядком, в котором объявления отображений фильтров,
соответствующих URI запроса для сервлета, появляются в списке.
Для установки отображения фильтров необходимо добавить элементы filter и filter-mapping
в дескриптор размещения Web-приложения. Вот элементы, используемые для объявления
порядка фильтров и их отображения в примере ReceiptServlet, обсуждаемом в главе 12:

<filter>
<filter-name>OrderFilter<filter-name>
<filter-class>filters.OrderFilter<filter-class>
</filter>
<filter-mapping>
<filter-name>OrderFilter</filter-name>
<url-pattern>/receipt</url-pattern>
</filter-mapping>
Чтобы добавить фильтр в deploytool, выполните следующие действия:
1. Выберите WAR.
2. Выберите закладку Filter Mapping.
3. Добавьте фильтр.
A. Нажмите Edit Filter List.
B. Нажмите Add.
C. Выберите класс фильтра.
D. Выберите имя фильтра.
E. Добавьте параметры инициализации фильтра.
F. Нажмите OK.

4. Отобразите фильтр.
A. Нажмите Add.
B. Выберите название фильтра.
C. Выберите тип назначения. Фильтр может быть отображен на конкретный сервлет
или на все сервлеты, соответствующие указанному шаблону URL.
D. Укажите назначение. Если назначение является сервлетом, выберите сервлет из
разворачивающегося списка. Если назначение является шаблоном URL, введите
шаблон.

Web-

Rendered by www.RenderX.com
Настройка Web-приложений Стр. 83 из 626

5.3.6. Отображение ошибок


Вы можете установить отображение между кодом состояния, возвращаемым в HTTP-
ответе, или исключительной ситуацией языка программирования Java, возвращаемой
каким-либо Web-компонентом и Web-ресурсом(см. раздел "Обработка ошибок"). Для
настройки отображения необходимо добавить элемент <error-page> в дескриптор
размещения. Вот элемент, используемый для отображения OrderException на страницу
errorpage.html, которая рассматривается в главе 12:

<error-page>
<exception-type>exception.OrderException</exception-type>
<location>/errorpage.html</location>
</error-page>
Чтобы добавить отображение ошибок в deploytool выполните следующие действия:
1. Выберите WAR.
2. Выберите закладку File Refs.
3. Нажмите Add в области Error Mapping.
4. Введите статус кода HTTP (см. раздел "Ответы HTTP") или полностью указанное имя
класса исключительной ситуации в поле Error/Exception.
5. Введите имя ресурса, который должен быть вызван при возврате кода статуса или
исключительной ситуации. Имя должно начинаться с символа /.
Примечание: Вы можете также определить страницы ошибок для JSP-страницы,
содержащейся в WAR. Если страницы ошибок определены и для WAR, и для JSP-страницы,
страница ошибок для JSP-страницы имеет преимущество.

5.3.7. Ссылки на элементы окружения, на элементы окружения ресурсов, или на


ресурсы
Если ваш Web-компонент обращается на элементы окружения, на элементы окружения
ресурсов, или на ресурсы, например базы данных, необходимо объявить ссылки при
помощи элементов <env-entry>, <resource-env-ref> или <resource-ref> в дескрипторе
размещения Web-приложения. Вот элемент, объявляющий ссылку на источник данных,
используемый в главах по технологии Web этого руководства:

<resource-ref>
<res-ref-name>jdbc/BookDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Чтобы добавить ссылку в deploytool выполните следующие действия:
1. Выберите WAR.

Web-

Rendered by www.RenderX.com
Стр. 84 из 626 Web-приложения

2. Выберите закладку Environment, Enterprise Bean Refs, Resource Env. Refs, или Resource
Refs.
3. Нажмите Add для добавления нового ресурса.

5.4. Установка Web-приложений


Контекст - это имя, которое отображается на Web-приложение. Например, контекстом
приложения Hello1 является /hello1. Для установки приложения в Tomcat необходимо
указать ему, что доступен новый контекст.
Уведомить Tomcat о новом контексте можно при помощи команды ant install. Обратите
внимание, что установленное приложение не доступно после перезагрузки Tomcat. Чтобы
разместить приложение постоянно, обратитесь к разделу "Размещение Web-приложений".
Команда ant install указывает программе manager, выполняющейся в указанном в атрибуте
url месте, установить приложение, файлы которого расположены в указанном в атрибуте
war месте, в указанном в атрибуте path контексте. Значением атрибута war может быть
WAR-файл jar:file:/path/to/bar.war!/ или неупакованный каталог file:/path/to/foo.

<install url="url" path="mywebapp" war="file:build"


username="username" password="password" />
Атрибуты username и password обсуждаются в разделе "Менеджер Web-приложений
Tomcat".
Вместо использования атрибута war информацию по конфигурации можно указать в
атрибуте config:

<install url="url"
path="mywebapp" config="file:build/context.xml"
username="username" password="password"/>
Атрибут config указывает файл конфигурации, содержащий элемент context в виде:

<Context path="/bookstore1"
docBase="../docs/tutorial/examples/web/bookstore1/build"
debug="0">
Обратите внимание, что элемент context полностью указывает месторасположение файлов
Web-приложения через свой атрибут docBase.
Файлы компоновки примера руководства содержат задание ant install, которое вызывает
команду ant install:

<target name="install"
description="Install web application" depends="build">
<install url="${url}" path="${mywebapp}"

Web-

Rendered by www.RenderX.com
Размещение Web-приложений Стр. 85 из 626

config="file:build/context.xml"
username="${username}" password="${password}"/>
</target>
Команда ant install требует доступности дескриптора размещения Web-приложения
(web.xml). Все приложения примеров руководства поставляются с дескрипторами
размещения.
Для установки приложения Hello1, описанного в разделе "Жизненный цикл Web-
приложения":
1. В терминальном окне перейдите в каталог <JWSDP_HOME>/docs/tutorial/exam-
ples/web/hello1.
2. Убедитесь, что Tomcat выполняется.
3. Выполните команду ant install. Задание install уведомляет Tomcat о доступности нового
контекста.

5.5. Размещение Web-приложений


Существует несколько способов постоянно разместить контекст в Tomcat во время его
работы:
• При помощи команды ant deploy:

<deploy url="url" path="mywebapp"


war="file:/path/to/mywebapp.war"
username="username" password="password" />
В отличие от команды install, которая может обращаться к неупакованному каталогу,
команда deploy требует WAR-файл. Команда deploy загружает WAR-файл в Tomcat и
запускает приложение. С помощью этой команды вы можете разместить приложение
на удаленном сервере.
• При помощи deploytool. При выборе операции deploy, программа копирует созданный
ею WAR-файл в Tomcat и информирует его о новом контексте.
Для размещения приложения Hello1 с помощью deploytool выполните следующие
действия:
1. Выберите WAR hello1.
2. Выберите Tools->Deploy.
3. Нажмите OK для выбора пути контекста по умолчанию /hello1.
4. Введите имя пользователя и пароль, указанный вами при установке Java WSDP.
5. Нажмите Finish.
6. Закройте окно Deploy Console нажав Close.

Доступны, также, еще два метода размещения, но они требуют перезапуска Tomcat:
• Скопируйте каталог Web-приложения или WAR в <JWSDP_HOME>/webapps.

Web-

Rendered by www.RenderX.com
Стр. 86 из 626 Web-приложения

• Скопируйте конфигурационный файл с именем mywebapp.xml, содержаший элемент


context, в каталог <JWSDP_HOME>/webapps. Формат элемента context описан в
документе "Server Configuration Reference" в
<JWSDP_HOME>/docs/tomcat/config/context.html. Обратите внимание, что элемент
context полностью указывает расположение файлов Web-приложения в атрибуте
docBase. Вот, например, элемент context для приложения, рассматриваемого в главе
12:

<Context path="/bookstore1"
docBase="../docs/tutorial/examples/web/
bookstore1/build" debug="0">
Некоторые файлы компоновки примеров содержат задание ant deploy, которое вызывает
команду ant deploy.

5.6. Просмотр списка установленных и размещенных Web-приложений


Если вы хотите увидеть список всех Web-приложений, доступных на текущий момент в
Tomcat, используйте команду ant list:

<list url="url" username="username" password="password" />


Файлы компоновки примеров руководства содержат задание ant list, которое вызывает
команду ant list.
Вы можете, также, увидеть список приложений, запустив менеджер приложений:

http://<host>:8080/manager/list
И, наконец, вы можете просмотреть список выполняющихся на сервере Web-приложений
при помощи deploytool, выбирая сервер из списка Server на левой панели.

5.7. Выполнение Web-приложений


Web-приложение выполняется при обращении в Web-броузере к URL, который отображается
на компонент. После установки и размещения приложения Hello1 вы можете запустить
Web-приложение указав в адресной строке броузера

http://<host>:8080/hello1/greeting
Замените <host> именем хоста, на котором выполняется Tomcat. Если ваш броузер
выполняется на том же самом хосте, что и Tomcat, вы можете заменить <host> на localhost.

5.8. Обновление Web-приложений


Во время разработки часто необходимо сделать изменения в Web-приложение. После
модификации сервлета вы должны:

Web-

Rendered by www.RenderX.com
Обновление Web-приложений Стр. 87 из 626

1. Перекомпилировать класс сервлета.


2. Обновить приложение на сервере.
3. Перезагрузить URL на клиенте.
После обновления JSP-страницы нет необходимости перекомпилировать или перезагружать
приложение, поскольку Tomcat выполняет это автоматически.
Чтобы попробовать эту возможность, измените сервлет-версию приложения Hello.
Например, вы можете изменить приветствие, возвращаемое сервлетом GreetingServlet,
следующим образом:

<h2>Hi, my name is Duke. What's yours?</h2>


Для обновления файла:
1. Отредактируйте GreetingServlet.java в каталоге с исходными файлами
<JWSDP_HOME>/docs/tutorial/examples/web/hello1/src.
2. Выполните команду ant build. Эта команда перекомпилирует сервлет в каталог build.
Процедура обновления приложения на сервере зависит от того, устанавливали ли вы его
при помощи команды ant install, или размещали при помощи команды ant deploy или в
deploytool.

5.8.1. Перезагрузка Web-приложений


Если вы устанавливали приложение при помощи команды ant install, обновление
приложения на сервере производится путем выполнения команды ant reload:

<reload url="url" path="mywebapp"


username="username" password="password" />
Файлы компоновки примеров содержат задание ant remove, которое вызывает команду
ant remove. Таким образом, для обновления приложения Hello1 на сервере выполните
команду ant reload. Для просмотра обновленного приложения перезагрузите URL Hello1 в
броузере клиента. Обратите внимание, что команда reload замечает изменения только в
классах Java, а не в файле web.xml. Для перезагрузки web.xml удалите приложение (см.
раздел "Удаление Web-приложений") и установите его снова.
В окне броузера вы должны увидеть экран, изображенный на рисунке 4-3.

Web-

Rendered by www.RenderX.com
Стр. 88 из 626 Web-приложения

Рисунок 4-3 Новое приветствие

Чтобы попробовать возможности обновления для JSP-версии примера, прежде всего


скомпонуйте и разместите ее:
1. В терминальном окне перейдите в каталог <JWSDP_HOME>/docs/tutorial/exam-
ples/web/hello2.
2. Выполните команду ant build. Задание build вызовет все необходимые компиляции и
скопирует файлы в каталог <JWSDP_HOME>/docs/tutorial/examples/web/hello2/build.
3. Выполните команду ant install. Задание install скопирует каталог build в каталог
<JWSDP_HOME>/webapps и укажет Tomcat, что доступно новое приложение.
ant buildкопированияdocs/tutorial/examples/web/hello2/buildHello2

5.8.2. Повторное размещение Web-приложений


Если Web-приложение было размещено с использованием deploytool, его можно обновить
следующим образом:
1. Выберите WAR hello1.
2. Выберите Tools->Update Files.
3. Появится диалоговое окно, показывающее измененный файл. Проверьте, что это
GreetingServlet.class, и дважды нажмите OK.
4. Выберите Tools->Update and Redeploy.
5. Появится диалоговое окно. Выберите /hello1 из поля списка Select Webapp to redeploy
и нажмите OK.
6. Закройте окно Redeploy Console, нажав Close.
Если приложение было размещено с использованием команды ant deploy, его можно
обновить при помощи команды ant undeploy, а затем ant deploy.

Web-

Rendered by www.RenderX.com
Удаление Web-приложений Стр. 89 из 626

5.9. Удаление Web-приложений


Для прекращения работы Web-приложения выполните команду ant remove:

<remove url="url" path="mywebapp"


username="username" password="password" />
Файлы компоновки примеров содержат задание ant remove, вызывающее команду ant
remove.

5.10. Отмена размещения Web-приложений


Для отмены размещения Web-приложения используйте команду ant undeploy:

<undeploy url="url" path="mywebapp"


username="username" password="password" />
или команду Undeploy в deploytool. Например, для отмены размещения приложения Hello1
с помощью deploytool:
1. Выберите WAR hello1.
2. Выберите Tools->Undeploy.
3. Появится диалоговое окно. Выберите /hello1 из поля списка Select Webapp to undeploy
и нажмите OK.
4. Закройте окно Undeploy Console, нажав Close.
или
1. Выберите сервер из списка Server в левой панели.
2. Выберите приложение hello1 в панели Deployed Applications.
3. Нажмите Undeploy.
Некоторые из файлов компоновки примеров содержат задание ant undeploy, вызывающее
команду ant undeploy.

5.11. Интернационализация и локализация Web-приложений


Интернационализация - это процесс подготовки приложения к поддержке различных языков
и форматов дат. Локализация - это процесс адаптирования интернационализированного
приложения к поддержке конкретного языка и местности. Хотя все клиентские
пользовательские интерфейсы должны быть интернационализированы и локализованы,
для Web-приложений это особенно актуально из-за природы Web. Хороший обзор процессов
интернационализации и локализации приведен в статье
http://java.sun.com/docs/books/tutorial/i18n/index.html
Существует два подхода к интернационализации Web-приложений:
• Предоставить версию JSP-страницы для каждой местности и дать контроллеру сервлетов
перенаправить запрос к соответствующей странице (в зависимости от местности). Этот

Web-

Rendered by www.RenderX.com
Стр. 90 из 626 Web-приложения

подход полезен при необходимости интернационализации большого количества данных


на странице или Web-приложения полностью.
• Выделить все чувствительные к местности данные на странице (такие как сообщения
об ошибках, строковые константы или метки кнопок) в пакеты ресурсов и обращаться
к данным так, чтобы соответствующие сообщения автоматически извлекались и
вставлялись в страницу. Таким образом, вместо создания строк непосредственно в
коде, вы создаете пакет ресурсов, содержащий переведенный текст, и читаете этот
текст из этого пакета при помощи соответствующего ключа. Пакет ресурсов может
сохраняться как текстовый файл (пакет ресурсов свойств) или класс (пакет ресурсов
списков), содержащий отображения.
В следующих главах по технологии Web пример "Duke's Bookstore" интернационализирован
и локализован для английского и испанского языков. Пары ключ/значение содержатся в
пакете ресурсов списков с именем messages.BookMessage_*.class. Чтобы показать вам,
как выглядят пары ключ/значение в пакете ресурсов, приведем несколько строк из файла
messages.BookMessages.java.

{"TitleCashier", "Cashier"},
{"TitleBookDescription", "Book Description"},
{"Visitor", "You are visitor number "},
{"What", "What We"re Reading"},
{"Talk", " talks about how Web components can transform the way
you develop applications for the Web. This is a must read for
any self respecting Web developer!"},
{"Start", "Start Shopping"},
Для получения нужных строк для данного пользователя Web-компонент извлекает из
запроса значение местности (установленное в настройках языковых предпочтений в
броузере), открывает пакет ресурсов для этой местности и затем сохраняет пакет как
атрибут сессии (см. раздел "Назначение атрибутов сессии"):

ResourceBundle messages = (ResourceBundle)session.


getAttribute("messages");
if (messages == null) {
Locale locale=request.getLocale();
messages = ResourceBundle.getBundle("WebMessages",
locale);
session.setAttribute("messages", messages);
}
Web-компонент извлекает пакет ресурсов из сессии:

ResourceBundle messages =
(ResourceBundle)session.getAttribute("messages");

Web-

Rendered by www.RenderX.com
Получение доступа к базам данных из Web-приложений Стр. 91 из 626

и ищет строку, связанную с ключом TitleCashier следующим образом:

messages.getString("TitleCashier");
Это очень краткое введение в интернационализацию Web-приложений. Для дополнительной
информации по этому вопросу обратитесь к Java BluePrints:
http://java.sun.com/blueprints

5.12. Получение доступа к базам данных из Web-приложений


Данные, которые используются различными Web-компонентами и остающиеся постоянными
между вызовами Web-приложения, обычно хранятся в базе данных. Web-приложения
используют JDBC 2.0 API для доступа к реляционным базам данных. Информация по этому
API находится на странице
http://java.sun.com/docs/books/tutorial/jdbc

5.12.1. Примеры
Примеры, рассматриваемые в главах 12, 13, 15 и 16 используют базу данных. Для этой
редакции мы проверили примеры с базой данных PointBase 4.3 и предоставили файл
компоновки ant для создания таблиц базы данных и заполнения их. Оставшаяся часть
этого раздела описывает как:
• Установить и запустить сервер баз данных PointBase
• Заполнить таблицы примеров
• Настроить Web-приложение для обращения к источнику данных
• Определить источник данных в Tomcat
• Настроить Tomcat для отображения ссылки на источник данных

5.12.2. Установка и запуск сервера баз данных


Вы можете загрузить пробную копию базы данных PointBase 4.3 с
http://www.poinbase.com
Проверьте, что вы выбрали установочный пакет, предназначенный для вашей платформы
(UNIX или Windows). Установите компоненты клиента и сервера. После загрузки и установки
базы данных PointBase выполните следующие действия:
1. Добавьте свойство pb.home в ваш файл build.properties (рассмотрено в разделе
"Управление примерами"), указывающее на каталог с установленной PointBase. В
системе Windows синтаксис этой записи может выглядеть так:

pb.home=drive:\\<PB_HOME>
2. Скопируйте файл <PB_HOME>/lib/pbclient43.jar в каталог <JWSDP_HOME>/common/lib
для того, чтобы библиотека клиента PointBase стала доступна для приложений

Web-

Rendered by www.RenderX.com
Стр. 92 из 626 Web-приложения

примеров. Если Tomcat работает, перезапустите его для загрузки клиентской


библиотеки.
3. В терминальном окне перейдите в каталог <PB_HOME>/tools/server.
4. Запустите сервер PointBase при помощи команды start_server в UNIX или startserver в
Windows.

5.12.3. Заполнение базы данных


1. В терминальном окне перейдите в каталог <JWSDP_HOME>/docs/tutorial/examples/web.
2. Запустите ant. Команда ant по умолчанию, create-book-db, использует консольную
программу PointBase для выполнения SQL-команд в books.sql. В конце ее работы вы
должны увидеть на экране следующую информацию:

[java] ID
[java] ----------
[java] 201
[java] 202
[java] 203
[java] 204
[java] 205
[java] 206
[java] 207
[java]
[java] 7 Rows Selected.
[java]
[java] SQL>
[java]
[java] COMMIT;
[java] OK

5.12.4. Настройка в Web-приложении ссылки на источник данных


Для доступа к базе данных из Web-приложения необходимо объявить ссылку на ресурс в
дескрипторе размещения этого Web-приложения (см. раздел "Ссылки на элементы
окружения, на элементы окружения ресурсов, или на ресурсы"). Ссылка на ресурс объявляет
JNDI-имя, тип ресурса данных и вид аутентификации, используемой при доступе к ресурсу:

<resource-ref>
<res-ref-name>jdbc/BookDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

Web-

Rendered by www.RenderX.com
Получение доступа к базам данных из Web-приложений Стр. 93 из 626

JNDI-имя используется для создания объекта источника данных во вспомогательном


классе базы данных database.BookDB, используемом примерами этого руководства.
Элемент res-auth указывает, что контейнер будет управлять регистрацией в базе данных.
Для указания ссылки на ресурс в deploytool выполните следующие действия:
1. Выберите WAR.
2. Выберите закладку Resource Refs.
3. Нажмите Add.
4. Введите jdbc/BookDB в поле Coded Name.

5.12.5. Определение источника данных в Tomcat


Для использования базы данных необходимо создать источник данных в Tomcat. Источник
данных содержит информацию о классе драйвера и URL, использующихся для подключения
к базе данных, а также параметры регистрации. Для определения источника данных в
Tomcat используйте admintool (см. "Настройка источников данных") следующим образом:
1. Запустите admintool указав в броузере:

http://localhost:8080/admin/index.jsp
2. Зарегистрируйтесь с именем пользователя и паролем, указанными вами при установке
Java WSDP.
3. Выберите запись Data Source в Resources.
4. Выберите Available Actions->Create New Data Source.
5. Введите pointbase в поле JNDI Name.
6. Введите jdbc:pointbase:server://localhost/sample в поле Data Source URL.
7. Введите com.pointbase.jdbc.jdbcUniversalDriver в поле JDBC Driver Class.
8. Введите public в полях User Name и Password.
9. Нажмите кнопку Save.
10. Нажмите кнопку Commit.

5.12.6. Настройка в Tomcat отображения JNDI-имени в источник данных


Поскольку ссылка на ресурс, объявленная в дескрипторе размещения Web-приложения,
использует JNDI-имя для обращения к источнику данных, необходимо соединить имя с
источником данных при помощи элемента resourceLink в конфигурации Tomcat. Ниже
приведена запись, использующаяся в приложениях, рассмотренных в главах по Web-
технологии:

<Context path="/bookstore1"
docBase="../docs/tutorial/examples/web/bookstore1/build"
debug="0">

Web-

Rendered by www.RenderX.com
Стр. 94 из 626 Java API for XML Processing

<ResourceLink name="jdbc/BookDB" global="pointbase"/>


</Context>
Поскольку ResourceLink является подэлементом элемента context, описанного в разделах
"Установка Web-приложений" и "Размещение Web-приложений", добавлять эту запись в
конфигурацию Tomcat нужно также, как добавляют элемент context: путем передачи имени
конфигурационного файла, содержащего запись, в атрибут config команды ant install, или
путем копирования конфигурационного файла с именем mywebapp.xml, содержащего
элемент context, в каталог <JWSDP_HOME>/webapps.
При размещении приложения с использованием команды ant deploy вы должны
спакетировать конфигурационный файл с именем context.xml, содержащий элемент context,
в каталог META-INF файла WAR.
При размещении приложения с использованием deploytool для подключения выполните
следующие действия:
1. Выберите WAR.
2. Выберите закладку Resource Refs.
3. Выберите источник данных, который вы определили в разделе "Настройка в Web-
приложении ссылки на источник данных".
4. Нажмите кнопку Import Data Sources.
5. Закройте диалоговое окно подтверждения.
6. Выберите pointbase из ниспадающего списка.
Примеры, рассмотренные в главах 12, 13, 15 и 16, иллюстрируют два последних механизма
размещения.

5.13. Дополнительная информация


Дополнительная информация по Web-приложениям и Tomcat находится в:
• Спецификация Java Servlet 3.2 - подробности настройки Web-приложений.
• Справочная документация по Tomcat, поставляемая с Java WSDP в
<JWSDP_HOME>/docs/tomcat/index.html.

6. Java API for XML Processing


Java API for XML Processing (JAXP) предназначен для обработки XML-данных в
приложениях, написанных на языке программирования Java. JAXP использует стандарты
анализаторов SAX (Simple API for XML Parsing) и DOM (Document Object Model), так что
вы можете выбирать между анализом данных как потока событий или построением их
объектного представления. JAXP поддерживает также стандарт XSLT (XML Stylesheet
Language Transformations), предоставляющий вам контроль над представлением данных
и позволяющий преобразование данных в другие XML-документы или в другие форматы,
такие как HTML. JAXP обеспечивает также поддержку пространства имен, позволяя вам
работать с DTD, которые могли бы в противном случае вызвать конфликт имен.

Web-

Rendered by www.RenderX.com
JAXP API Стр. 95 из 626

JAXP позволяет вам использовать любой XML-совместимый анализатор в вашем


приложении. Это обеспечивается при помощи так называемого уровня подключений,
который разрешает подключать реализации SAX или DOM API. Уровень подключений
позволяет также подключить XSL-процессор, дающий вам контроль над способом
отображения ваших XML-данных.

6.1. JAXP API


Основные JAXP API определены в пакете javax.xml.parsers. Этот пакет содержит два
независимых от поставщиков класса генераторов: SAXParserFactory и DocumentBuilderFac-
tory, которые предоставляют вам соответственно SAXParser и DocumentBuilder. Document-
Builder, в свою очередь, создает DOM-совместимый объект Document.
Эти API дают вам возможность подключить XML-реализацию, предлагаемую другим
поставщиком, без изменения вашего исходного кода. Какая именно используется
реализация, зависит от настройки системных свойств javax.xml.parsers.SAXParserFactory
и javax.xml.parsers.DocumentBuilderFactory. Значения по умолчанию (пока они не
переопределены во время выполнения) указывают на справочную реализацию.
В оставшейся части этого раздела показано, как работают различные JAXP API в
приложениях.

6.2. Обзор пакетов


SAX и DOM API определяются группой XML-DEV и W3C соответственно. Библиотеками,
определяющими эти API являются:
javax.xml.parsers
Это JAXP API, обеспечивающие общий интерфейс для SAX и DOM-анализаторов различных
поставщиков.
org.w3c.dom
Определяет класс Document (DOM), а также классы для всех компонентов DOM.
org.xml.sax
Определяет основные SAX API.
javax.xml.transform
"Simple API" for XML (SAX) представляет собой основанный на событиях механизм
последовательного доступа, осуществляющий обработку "элемент-за-элементом". API
этого уровня читает и записывает XML в хранилище данных или Web. Для серверных и
высокопроизводительных приложений вы должны полностью понимать этот уровень. Но
для многих приложений достаточно минимальных знаний.
DOM API обычно легче в использовании. Он обеспечивает относительно знакомую
древовидную структуру объектов. Вы можете использовать DOM API для управления
иерархией объектов приложения, которые он объединяет. DOM API является идеальным
для интерактивных приложений, поскольку в памяти присутствует полная модель объектов,
к ней можно получить доступ и пользователь может управлять ею.

Web-

Rendered by www.RenderX.com
Стр. 96 из 626 Java API for XML Processing

С другой стороны, создание DOM требует чтения полной XML-структуры и хранения дерева
объектов в памяти, то есть этот метод использует значительно больше ресурсов CPU и
памяти. По этой причине SAX API более предпочтителен для серверных приложений и
фильтров данных, которые не требуют наличия данных в памяти.
И, наконец, XSL API, определенный в javax.xml.transform, позволяет вам записывать XML-
данные в файл или преобразовывать их в другие форматы. И, как вы увидите в разделе
по XSLT этого руководства, вы можете даже использовать его совместно с SAX API для
преобразования обычных данных в XML.

6.3. The Simple API for XML (SAX)


Основная схема API SAX-анализа приведена ниже. В начале процесса анализа для
генерации экземпляра анализатора используется экземпляр класса SAXParserFactory.

Рисунок 5-1 SAX API

Анализатор содержит в себе объект SAXReader. При вызове метода анализатора parse()
считыватель вызывает один из нескольких методов обратного вызова, реализованных в
приложении. Эти методы определяются интерфейсами ContentHandler, ErrorHandler,
DTDHandler и EntityResolver.
Вот сводка ключевых SAX API:
SAXParserFactory
Объект SAXParserFactory создает экземпляр анализатора, определенного системным
свойством javax.xml.parsers.SAXParserFactory.
SAXParser
Интерфейс SAXParser определяет методы parse() нескольких типов. В обычном случае,
вы передаете источник XML-данных и объект DefaultHandler анализатору, который
обрабатывает XML и вызывает соответствующие методы объекта handler.
SAXReader
SAXParser включает в себя SAXReader. Обычно, вам не надо беспокоиться об этом, но
изредка необходимо использовать метод getXMLReader() объекта SAXParser для настройки

Web-

Rendered by www.RenderX.com
The Simple API for XML (SAX) Стр. 97 из 626

объекта SAXReader. Именно SAXReader осуществляет общение с обработчиками SAX-


событий, которые вы определяете.
DefaultHandler
DefaultHandler, не показанный на рисунке, реализует интерфейсы ContentHandler,
ErrorHandler, DTDHandler и EntityResolver (с пустыми методами), так что вы можете
переопределить только необходимые.
ContentHandler
При распознавании XML-тега вызываются такие методы как startDocument, endDocument,
startElement и endElement. Этот интерфейс также определяет методы characters и
processingInstruction, которые вызываются при встрече текста в XML-элементе или
встроенной команды обработки соответственно.
ErrorHandler
Методы error, fatalError и warning вызываются в ответ на различные ошибки анализа.
Обработчик ошибок по умолчанию генерирует исключительную ситуацию для фатальных
ошибок и игнорирует остальные ошибки (включая ошибки верификации). Это одна из
причин, из-за которой вы должны знать SAX-анализатор, даже если используете DOM.
Иногда приложение может восстановиться после ошибки верификации. Иногда требуется
сгенерировать исключительную ситуацию. Для гарантии корректной обработки вы должны
предоставить для анализатора ваш собственный обработчик ошибок.
DTDHandler
Определяет методы, которые вы обычно никогда не будете вызывать для использования.
Используется при обработке DTD для распознавания и обработки объявлений для
неанализируемой сущности.
EntityResolver
Метод resolveEntity вызывается тогда, когда анализатор должен идентифицировать данные,
указанные в URI. В большинстве случаев URI представляет собой URL, указывающий
расположение документа, но в некоторых случаях документ может идентифицироваться
при помощи URN - общедоступным идентификатором, или именем, уникальным в Web-
пространстве. Общедоступный идентификатор может быть указан как дополнение к URL.
EntityResolver может затем использовать общедоступный идентификатор вместо URL для
обнаружения документа, например, для доступа к локальной копии документа, если она
существует.
Обычное приложение как минимум реализует большинство из методов ContentHandler.
Поскольку реализации интерфейсов по умолчанию игнорируют весь входной поток, за
исключением фатальных ошибок, надежное приложение может также реализовать методы
ErrorHandler.

6.3.1. Пакеты SAX


SAX-анализатор определяется в пакетах, перечисленных в таблице 5-1.
Таблица 5-1 SAX-пакеты

Web-

Rendered by www.RenderX.com
Стр. 98 из 626 Java API for XML Processing

Пакет Описание
org.xml.sax Определяет SAX-интерфейсы. Имя org.xml является
префиксом пакета, который был разработан группой,
определившей SAX API.
org.xml.sax.ext Определяет расширение SAX, использующееся при более
сложной SAX-обработке, например, для обработки
определений типа документа (DTD) или для просмотра
детального синтаксиса файла.
org.xml.sax.helpers Содержит вспомогательные классы, облегчающие
использование SAX - например, определяя обработчик по
умолчанию, который имеет null-методы для всех
интерфейсов, так что вам необходимо переопределить только
те из них, которые действительно нужны.
javax.xml.parsers Определяет класс SAXParserFactory, возвращающий
SAXParser. Также определяет классы исключительных
ситуаций для вывода ошибок.

6.4. The Document Object Model API (DOM)


На рисунке 5-2 показаны JAXP API в действии:

Рисунок 5-2 DOM API

Для получения экземпляра DocumentBuilder используется класс javax.xml.parsers.Document-


BuilderFactory. DocumentBuilder используется для генерации объекта Document (DOM),
соответствующего спецификации DOM. Фактический построитель, получаемый вами,
определяется в системном свойстве javax.xml.parsers.DocumentBuilderFactory, в котором
выбирается реализация генератора. (Значение по умолчанию может быть переопределено
в командной строке.)
Можно использовать также метод newDocument() объекта DocumentBuilder для создания
пустого Document, реализующего интерфейс org.w3c.dom.Document. В качестве
альтернативы для создания объекта Document из существующих XML-данных вы можете
использовать один из методов parse построителя. Результатом является DOM-дерево,
подобное показанному на рисунке.
Примечание: Хотя элементы DOM-дерева называются объектами, фактически они являются
в некоторой степени низкоуровневыми структурами данных. Например, в каждом узле
element (который соответствует XML-элементу) существует узел text, содержащий имя
тега элемента! Этот вопрос будет рассмотрен в разделе DOM данного руководства, но

Web-

Rendered by www.RenderX.com
XML Stylesheet Language Transformations API (XSLT) Стр. 99 из 626

пользователи, ожидающие объекты, обычно удивлены, когда при вызове метода text()
объекта element ничего не возвращается. Действительно объектно-ориентированное
дерево используется в JDOM API, информацию по которому можно найти на сайте
http://www.jdom.org.

6.4.1. Пакеты DOM


Реализация Document Object Model определяется в пакетах, перечисленных в таблице 5-
2.
Таблица 5-2 Пакеты DOM
Пакет Описание
org.w3c.dom Определяет программные интерфейсы DOM для XML-
документов (и, необязательно, HTML), как определено
спецификацией W3C.
javax.xml.parsers Определяет класс DocumentBuilderFactory и класс Document-
Builder, возвращающий объект, который реализует интерфейс
W3C DOM. Генератор, используемый для создания
построителя, определяется в системном свойстве
javax.xml.parsers, которое можно установить из командной
строки или путем переопределения при вызове метода new
Instance. Также определяет класс ParserConfigurationException
для вывода ошибок.

6.5. XML Stylesheet Language Transformations API (XSLT)


На рисунке 5-3 показаны XSLT API в действии.

Рисунок 5-3 XSLT API

Создается экземпляр объекта TransformerFactory, который используется для создания


Transformer. Объект source является входным для процесса преобразования. Объект
source может быть создан из SAXReader, из DOM, или из входного потока.

Web-

Rendered by www.RenderX.com
Стр. 100 из 626 Java API for XML Processing

Объект result представляет собой результат процесса преобразования. Этот объект может
быть обработчиком событий SAX, DOM, или выходным потоком.
Объект transformer может быть создан из набора инструкций преобразования, в этом
случае проводятся указанные преобразования. Если transformer создан без указания каких-
либо инструкций, то он просто копирует source в result.

6.5.1. Пакеты XSLT


XSLT API определены в следующих пакетах:
Таблица 5-3 Пакеты XSLT
Пакет Описание
javax.xml.transform Определяет классы TransformerFactory и Transformer, которые
используются для получения объекта, способного к
выполнению преобразований. После создания объекта
transformer вызывается его метод transform(), которому
указываются входной (source) и выходной (result) объекты.
javax.xml.transform.dom Классы для создания входного (source) и выходного (result)
объектов из DOM.
javax.xml.transform.sax Классы для создания входного (source) объекта из SAX-
анализатора и выходного (result) объекта из обработчика
событий SAX.
javax.xml.transform.stream Классы для создания входного (source) и выходного (result)
объектов из потока ввода/вывода.

6.6. Компиляция и выполнение программ


В Java WSDP JAXP-библиотеки располагаются в каталоге <JWSDP_HOME>/common/lib.
Для компиляции и выполнения программ примеров прежде всего необходимо установить
JAXP-библиотеки в соответствующее место. (Месторасположение зависит от используемой
версии JVM). Дополнительная информация приведена в инструкции по текущей редакции
JAXP в файле <JWSDP_HOME>/docs/jaxp/ReleaseNotes.xml.

6.7. Куда идти дальше?


Теперь вы имеете достаточно информации для начала изучения JAXP-библиотек. Ваше
следующее действие зависит от того, что именно вы хотите изучить. Вы можете перейти
к:
XML-темы
Если вы хотите узнать больше про XML, тратя минимум времени на Java API. Вы увидите
все разделы по XML в курсе руководства. Следуйте по следующим ссылкам, если хотите
пропустить шаги по программным API:
• Освоение XML
• Написание простого XML-файла
• Замена и вставка текста
• Создание DTD
• Определение атрибутов и сущностей в DTD

Web-

Rendered by www.RenderX.com
Куда идти дальше? Стр. 101 из 626

• Обращение к двоичным сущностям


• Определение сущностей-параметров и условных секций
Разработка структуры XML-данных
Если вы создаете структуру XML-данных для приложения и хотите получить несколько
советов по этому процессу.
Simple API for XML
Если структуры данных уже определены, и вы пишете серверное приложение или XML-
фильтр, которые требуют максимально быстрой обработки. Этот раздел также проведет
вас шаг за шагом через процесс создания XML-документа.
Document Object Model
Если вам необходимо построить дерево объектов из XML-данных, для того чтобы можно
было управлять ими из приложения или преобразовать дерево объектов в XML. Эта часть
руководства заканчивается разделом по пространству имен.
XML Stylesheet Language for Transformations
Если вам необходимо преобразовать XML-теги в какую-то другую форму, если вы хотите
сгенерировать выходные данные в XML-формате, или если вы хотите преобразовать
обычные структуры данных в XML.

7. Simple API for XML


В этой главе мы рассмотрим Simple API for XML (SAX) - управляемый событиями механизм
последовательного доступа к XML-документам. Он является протоколом, который будет,
возможно, использоваться в большинстве сервлетов и сетевых программ для передачи и
приема XML-документов, поскольку это наиболее быстрый и наименее требовательный к
памяти механизм, доступный в настоящее время для работы с XML-документами.
SAX-протокол требует гораздо большего объема программирования, чем Document Object
Model (DOM). Это управляемая событиями модель (вы обеспечиваете методы обратного
вызова, а анализатор вызывает их по мере чтения XML-данных), которая затрудняет
визуализацию данных. И, наконец, вы не можете вернуться к предыдущей части документа
или реорганизовать его, точно также, как не можете вернуться к предыдущим данным в
последовательном потоке данных, или реорганизовать символы, прочитанные из потока.
По этим причинам разработчики, создающие ориентированное на пользователя приложение,
которое отображает XML-документ и, возможно, модифицирует его, будут, вероятно,
использовать DOM-механизм, описанный в следующей части этого руководства - "Document
Object Model".
Однако даже если вы планируете работать исключительно с DOM, существует несколько
важных причин знакомства с моделью SAX:
• Одинаковая обработка ошибок
При анализе документа для DOM генерируются те же самые типы исключительных
ситуаций, так что обработка ошибок в JAXP SAX- и DOM-приложениях идентична.
• Обработка ошибок верификации

Web-

Rendered by www.RenderX.com
Стр. 102 из 626 Simple API for XML

По умолчанию спецификация требует, чтобы ошибки верификации (которые вы изучите


в этой части руководства) игнорировались. Если вы хотите генерировать исключительную
ситуацию при ошибке верификации (а возможно вы так и сделаете), то необходимо
понимать обработку ошибок в SAX.
• Преобразование существующих данных
Как вы узнаете при изучении DOM, существует механизм, используемый для
преобразования существующих данных в XML. Однако использование преимуществ
этого механизма требует понимания модели SAX.
Примечание: Примеры этой главы расположены в каталоге <JWSDP_HOME>/docs/tuto-
rial/examples/jaxp/sax/samples.

7.1. Когда используется SAX


Когда нужно быстрое, эффективное чтение XML-данных, SAX трудно превзойти. Он требует
меньше памяти, поскольку не требуется построения внутреннего представления
(древовидной структуры) XML-данных. Вместо этого он просто передает данные в
приложение по мере чтения - ваше приложение может затем делать все что необходимо
с данными, которые ему доступны.
В сущности, SAX API действует как последовательный поток ввода/вывода. Вы видите
данные по мере их поступления, но вы не можете перейти назад к предыдущей части, или
перепрыгнуть вперед на другую позицию. Обычно все работает хорошо, если вам нужно
просто прочитать данные, и приложение должно что-либо выполнить.
Также полезно понимать модель событий SAX при преобразовании существующих данных
в XML. Как вы увидите в разделе "Генерация XML из произвольной структуры данных",
ключевым моментом процесса преобразования является модификация существующего
приложения для приема соответствующих SAX-событий по мере чтения данных.
Но когда необходимо изменить XML-структуру, особенно если это нужно сделать в
интерактивном режиме, больший смысл имеет применение структуры, находящейся в
памяти, такой как DOM.
Однако, в то время как DOM предоставляет много мощных возможностей для больших
документов (таких как книги и статьи), он также требует много сложного кодирования.
(Подробности этого процесса рассмотрены в разделе "Когда используется DOM").
Для более простых приложений такая сложность может быть нежелательной. Для быстрой
разработки и для более простых приложений может иметь смысл использование одного
из объектно-ориентированных стандартов XML-программирования, как описано в разделе
"JDOM и dom4j".

7.2. Написание простого XML-файла


Давайте начнем писать простую версию XML-данных, которые можно применить для показа
слайдов. В этом упражнении при создании данных используйте ваш текстовый редактор,
для того чтобы ознакомиться с основным форматом XML-файла. Вы будете использовать
этот файл и изменять его в следующих упражнениях.

Web-

Rendered by www.RenderX.com
Написание простого XML-файла Стр. 103 из 626

7.2.1. Создание файла


Используя стандартный текстовый редактор, создайте файл под названием slideSample.xml.
Примечание: Здесь расположена готовый файл: slideSample01.xml. (Версия для броузера
- slideSample01-xml.html.) Вы можете использовать эту версию для сравнения с вашей, а
также для просмотра при чтении этого руководства.

7.2.2. Написание объявления


Далее напишите объявление, которое идентифицирует файл как XML-документ. Объявление
начинается с символов "<?", являющихся стандартным XML-идентификатором для
инструкций обработки. (Вы увидите другие инструкции обработки далее в этом руководстве.)

<?xml version='1.0' encoding='utf-8'?>


Эта строка идентифицирует документ как XML-документ, соответствующий версии 1.0
спецификации XML, и указывает, что в нем используется таблица кодировки символов -
8-битный Unicode. (Информация по таблицам кодировки находится в разделе "Таблицы
кодировки для Java".)
Поскольку документ не был определен как "standalone", анализатор считает, что в нем
могут содержаться ссылки на другие документы. Чтобы увидеть, как указать документ
"standalone", обратитесь к разделу "XML-пролог".

7.2.3. Добавление комментария


Комментарии игнорируются XML-анализаторами. И вы в действительности их никогда не
видите до тех пор, пока не активизируете специальные установки в анализаторе. Вы
увидите, как это сделать далее, когда будет обсуждаться тема "Обработка лексических
событий". А сейчас добавьте выделенный ниже текст, чтобы вставить комментарий в файл.

<?xml version='1.0' encoding='utf-8'?>

<!-- A SAMPLE set of slides -->

7.2.4. Определение корневого элемента


После объявления каждый XML-файл определяет ровно один элемент, известный как
корневой элемент. Все другие элементы в файле содержатся внутри этого элемента.
Введите выделенный ниже текст, чтобы определить корневой элемент этого файла -
slideShow:

<?xml version='1.0' encoding='utf-8'?>

<!-- A SAMPLE set of slides -->

Web-

Rendered by www.RenderX.com
Стр. 104 из 626 Simple API for XML

<slideshow>

</slideshow>
Примечание: Имена XML-элементов чувствительны к регистру символов. Завершающий
тег должен в точности соответствовать начальному тегу.

7.2.5. Добавление атрибутов к элементу


Приложение показа слайдов имеет несколько связанных элементов данных, ни один из
которых не требует какой-либо структуры. Так что вполне естественно определить их как
атрибуты элемента slideshow. Добавьте выделенный ниже текст, чтобы установить
некоторые атрибуты:

...
<slideshow

title="Sample Slide Show"


date="Date of publication"
author="Yours Truly"

>
</slideshow>
При создании имени тега или атрибута можно использовать дефисы ("-"), знаки
подчеркивания ("_"), двоеточия (":") и точку (".") в дополнение к символам и цифрам. В
отличие от HTML значения XML-атрибутов всегда находятся в кавычках, а несколько
атрибутов никогда не разделяются запятой.
Примечание: Двоеточия должны использоваться с осторожностью или вообще не
использоваться, поскольку они применяются при определении пространства имен для
XML-документа.

7.2.6. Добавление вложенных элементов


XML позволяет записывать иерархически структурированные данные. Это означает, что
элемент может содержать другие элементы. Добавьте выделенный ниже текст, чтобы
определить элемент slide и элемент title, находящийся внутри его:

<slideshow
...
>

<!-- TITLE SLIDE -->

Web-

Rendered by www.RenderX.com
Написание простого XML-файла Стр. 105 из 626

<slide type="all">
<title>Wake up to WonderWidgets!</title>
</slide>

</slideshow>
Здесь также был добавлен атрибут type к элементу slide. Назначение этого атрибута
следующее - слайды могут быть отмечены для показа технической или исполнительной
аудитории (type="tech" или type="exec"), а также идентифицированы подходящими обеим
аудиториям (type="all").
Более важно, что этот пример иллюстрирует различие между объектами, которые лучше
определить элементами (элемент title), и объектами, которые лучше определить атрибутами
(атрибут type). Здесь работает эвристический подход, основанный на видимости. title - это
то, что аудитория будет видеть. Поэтому он является элементом. type, с другой стороны,
- это то, что никогда не будет показано, поэтому это - атрибут. Другим способом это
различие можно объяснить так - элемент является контейнером, наподобие бутылки. type
- это характеристика контейнера (длинный он или короткий, широкий или узкий). title - это
характеристика содержимого (вода, молоко или чай). Это, естественно, не жесткие, быстро
применимые правила, но они могут помочь вам при разработке своих собственных XML-
структур.

7.2.7. Добавление HTML-текста


Поскольку XML разрешает определение любых тегов, имеет смысл определить набор
тегов, выглядящих как HTML. Фактически, стандарт XHTML делает именно это. Вы
прочитаете подробнее об этом далее в настоящем руководстве по SAX. А сейчас введите
выделенный ниже текст, чтобы определить slide с парами записей элементов списка,
которые используют тег <em> HTML-стиля для выделения (обычно отображаемого в виде
наклонного текста):

...
<!-- TITLE SLIDE -->
<slide type="all">
<title>Wake up to WonderWidgets!</title>
</slide>

<!-- OVERVIEW -->


<slide type="all">
<title>Overview</title>
<item>Why <em>WonderWidgets</em> are great</item>
<item>Who <em>buys</em> WonderWidgets</item>
</slide>

Web-

Rendered by www.RenderX.com
Стр. 106 из 626 Simple API for XML

</slideshow>
Далее мы увидим, что определение элемента title вступает в конфликт с элементом XHTML,
использующим такое же имя. Мы рассмотрим механизм, вызывающий конфликт (DTD), и
несколько возможных решений в разделе "Анализ и параметризованные DTD".

7.2.8. Добавление пустого элемента


Одним из основных отличий между XML и HTML является то, что все XML-документы
должны быть фомально-правильными - это означает, что каждый тег должен иметь
завершающий тег или быть пустым тегом. Вы уже хорошо знакомы с завершающими
тегами. Добавьте выделенный ниже текст, чтобы определить пустой элемент списка без
содержимого:

...
<!-- OVERVIEW -->
<slide type="all">
<title>Overview</title>
<item>Why <em>WonderWidgets</em> are great</item>

<item/>

<item>Who <em>buys</em> WonderWidgets</item>


</slide>

</slideshow>
Обратите внимание, что любой элемент может быть пустым элементом. Все что для этого
необходимо - закончить тег знаками "/>", а не ">". Можно сделать то же самое путем ввода
<item></item>, что является эквивалентом.
Примечание: Другим фактором, делающим XML-файл формально-правильным, является
правильное вложение. То есть, <b><i>some_text</i></b> является формально-правильным,
поскольку последовательность <i>…</i> полностью вложена в тег <b>…</b>. Следующая
последовательность не является формально-правильной: <b><i>some_text</b></i>.

7.2.9. Законченный продукт


Вот полная версия XML-файла:

<?xml version='1.0' encoding='utf-8'?>

<!-- A SAMPLE set of slides -->

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 107 из 626

<slideshow
title="Sample Slide Show"
date="Date of publication"
author="Yours Truly"
>

<!-- TITLE SLIDE -->


<slide type="all">
<title>Wake up to WonderWidgets!</title>
</slide>

<!-- OVERVIEW -->


<slide type="all">
<title>Overview</title>
<item>Why <em>WonderWidgets</em> are great</item>
<item/>
<item>Who <em>buys</em> WonderWidgets</item>
</slide
</slideshow>
Теперь, когда вы создали файл для работы, вы готовы написать программу, дублирующую
этот файл при помощи SAX-анализатора. Вы сделаете это в следующем разделе.

7.3. Дублирование XML-файла при помощи SAX-анализатора


В реальной жизни вам вряд ли понадобится дублирование XML-файла с использованием
SAX-анализатора. Обычно нужно обработать данные каким-либо образом, для того чтобы
сделать что-то полезное с ними. (Если надо продублировать XML-данные, легче построить
DOM-дерево и использовать его для вывода.) Но дублирование XML-структуры является
хорошим способом увидеть SAX-анализатор в действии и может быть полезно для отладки.
В этом упражнении события SAX-анализатора направляются в System.out. Будем считать
его версией "Hello World" программы XML-обработки. В упражнении демонстрируется
использование SAX-анализатора для получения данных и их отображения.
Примечание: Исходный код, рассматриваемый в этом разделе, находится в файле
Echo01.java. Файл, с которым он работает - slideSample01.xml. (Версия для броузера -
slideSample01-xml.html.)

7.3.1. Создание скелета программы


Начните с создания файла с именем Echo.java и введите скелет приложения:

public class Echo


{
public static void main(String argv[])

Web-

Rendered by www.RenderX.com
Стр. 108 из 626 Simple API for XML

}
Поскольку мы собираемся выполнять ее автономно, нам необходим метод main. И нам
необходимы аргументы командной строки, чтобы указать приложению, в какой файл
осуществлять вывод.

7.3.2. Импорт классов


Далее, добавьте операторы import для классов, которые будет использовать приложение:

import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;

public class Echo


{
...
Классы в java.io, естественно, нужны для вывода. Пакет org.xml.sax определяет все
используемые для SAX-анализатора интерфейсы. Класс SAXParserFactory создает
используемый нами экземпляр. Он генерирует ParserConfigurationException, если не может
создать анализатор, удовлетворяющий указанным настройкам конфигурации. (Более
детально о настройках конфигурации будет сказано ниже.) Генератор создает SAXParser
для анализа, а DefaultHandler определяет класс, который будет обрабатывать SAX-события,
генерируемые анализатором.

7.3.3. Настройка ввода/вывода


Первоначальный порядок действий - обработать аргумент командной строки, получить
имя файла для вывода и настроить выходной поток. Добавьте выделенный ниже текст,
чтобы выполнить эти задачи, а также некоторые дополнительные служебные действия:

public static void main(String argv[])

if (argv.length != 1) {
System.err.println("Usage: cmd filename");

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 109 из 626

System.exit(1);
}
try {
//
out = new OutputStreamWriter(System.out, "UTF8");
}
catch (Throwable t) {
t.printStackTrace();
}
System.exit(0);

static private Writer out;

При создании OutputStreamWriter мы выбираем кодировку символов UTF-8. Можно было


выбрать и кодировку US-ASCII или UTF-16, также поддерживаемые платформой Java.
Дополнительная информация по этим кодировкам символов приведена в разделе "Таблицы
кодировок в Java".

7.3.4. Реализация интерфейса ContentHandler


Наиболее важным интерфейсом для наших текущих задач является интерфейс
ContentHandler. Этот интерфейс требует нескольких методов, которые вызывает SAX-
анализатор в ответ на различные события анализа. Основными методами обработки
событий являются: startDocument, endDocument, startElement, endElement и characters.
Самый простой способ реализовать этот интерфейс - расширить класс DefaultHandler,
определенный в пакете org.xml.sax.helpers. Этот класс предоставляет ничего не делающие
методы для всех событий ContentHandler. Введите выделенный ниже код для расширения
класса:

public class Echo extends DefaultHandler

{
...
}

Примечание: DefaultHandler предоставляет также пустые методы для других основных


событий, определенных в интерфейсах DTDHandler, EntityResolver и ErrorHandler. Вы
изучите эти методы по мере продвижения вперед.

Web-

Rendered by www.RenderX.com
Стр. 110 из 626 Simple API for XML

Каждый из этих методов необходим интерфейсу для генерации SAXException. Генерируемая


здесь исключительная ситуация передается назад в анализатор, который передает ее в
код, вызвавший анализатор. В данной программе это означает, что она возвращается в
обработчик исключительных ситуаций Throwable в конце метода main.
При обнаружении начального или завершающего тега его имя передается как String в
метод startElement или endElement соответственно. При обнаружении начального тега все
определенные в нем атрибуты также передаются в списке Attributes. Символы, найденные
внутри элемента, передаются в виде массива символов вместе с их количеством (length)
и смещением в массиве, указывающим на первый символ.

7.3.5. Настройка анализатора


Теперь, наконец, вы готовы настроить анализатор. Для этого добавьте выделенный ниже
текст:

public static void main(String argv[])


{
if (argv.length != 1) {
System.err.println("Usage: cmd filename");
System.exit(1);
}

//
SAX-
DefaultHandler handler = new Echo();

//
( )
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
//
out = new OutputStreamWriter(System.out, "UTF8");

//
SAXParser saxParser = factory.newSAXParser();
saxParser.parse( new File(argv[0]), handler );

} catch (Throwable t) {
t.printStackTrace();
}

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 111 из 626

System.exit(0);
}
При помощи этих строк кода вы создали экземпляр SAXParserFactory, как определено в
установках системного свойства javax.xml.parsers.SAXParserFactory. Затем вы получили
экземпляр анализатора этого класса для обработки событий анализа и указали входной
файл для обработки.
Примечание: Класс javax.xml.parsers.SAXParser является оболочкой, в которой определяется
несколько удобных методов. Он включает в себя (немного менее дружественный) объект
org.xml.sax.Parser. При необходимости можно получить этот анализатор при помощи метода
getParser() объекта SAXParser.
Теперь вы просто перехватываете любые исключительные ситуации, которые анализатор
может сгенерировать. Более подробно обработку ошибок вы изучите в последнем разделе
этого руководства "Обработка ошибок неверифицирующим анализатором".

7.3.6. Вывод результата


Методы ContentHandler генерируют SAXExcetion, а не IOException, которые могут возникнуть
во время записи. Однако SAXException может включить в себя другую исключительную
ситуацию, так что имеет смысл осуществить вывод в методе, который позаботится о
деталях обработки исключительных ситуаций. Добавьте выделенный ниже код для
определения метода emit, который делает это:

static private Writer out;

private void emit(String s)


throws SAXException
{
try {
out.write(s);
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}

...
При вызове emit любая ошибка ввода/вывода перехватывается в SAXException вместе с
сообщением, идентифицирующим ее. Затем эта исключительная ситуация передается
назад в SAX-анализатор. Далее вы изучите исключительные ситуации SAX более подробно.
А пока имейте в виду, что emit - это маленький метод, который обрабатывает вывод строк.
(Вы увидите, что он часто вызывается в коде.)

Web-

Rendered by www.RenderX.com
Стр. 112 из 626 Simple API for XML

7.3.7. Расстановка разделителей при выводе


Вот еще небольшой фрагмент кода, необходимый нам перед выполнением какой-либо
реальной обработки. Добавьте выделенный ниже код для определения метода nl(), который
записывает символ конца строки, используемый в данной системе:

private void emit(String s)


...
}

private void nl()


throws SAXException
{
String lineEnd = System.getProperty("line.separator");
try {
out.write(lineEnd);
} catch (IOException e) {
throw new SAXException("I/O error", e);
}

}
Примечание: Немного досадно, но вам придется вызывать nl() много раз. Определение
его сейчас упростит код в дальнейшем. Он также обеспечивает место для вставки отступов
при выводе.

7.3.8. Обработка событий содержимого


И, наконец, напишем код, который действительно обрабатывает события ContentHandler.

7.3.8.1. События документа


Добавьте выделенный ниже код для обработки событий start-document и end-document:

static private Writer out;

public void startDocument()


throws SAXException
{
emit("<?xml version='1.0' encoding='UTF-8'?>");
nl();
}

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 113 из 626

public void endDocument()


throws SAXException
{
try {
nl();
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}

private void echoText()


...
Здесь вы дублируете XML-объявление при обнаружении анализатором начала документа.
Поскольку вы настроили OutputStreamWriter на использование кодировки UTF-8, вы
включаете эту спецификацию как часть объявления.
Примечание: IO-классы не понимают имен кодировок с дефисом, поэтому вы указали
"UTF8", а не "UTF-8".
В конце документа вы просто выводите последнюю newline и сбрасываете выходной поток.
Не так уж много чего здесь происходит.

7.3.8.2. События элементов


А теперь - интересная вещь. Добавьте выделенный ниже код для обработки событий start-
element и end-element:

public void startElement(String namespaceURI,


String sName, //
String qName, //
Attributes attrs)
throws SAXException
{
String eName = sName; //
if ("".equals(eName)) eName = qName; // not namespaceAware
emit("<"+eName);
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aName = attrs.getLocalName(i); //
if ("".equals(aName)) aName = attrs.getQName(i);
emit(" ");
emit(aName+"=\""+attrs.getValue(i)+"\"");

Web-

Rendered by www.RenderX.com
Стр. 114 из 626 Simple API for XML

}
}
emit(">");
}

public void endElement(String namespaceURI,


String sName, //
String qName //
)
throws SAXException
{
String eName = sName; //
if ("".equals(eName)) eName = qName; // not namespaceAware
emit("<"+eName+">");
}

private void emit(String s)


...
При помощи этого кода вы дублируете теги элементов, включая все атрибуты,
определенные в начальном теге. Обратите внимание на то, что когда вызывается метод
startElement(), простое имя ("локальное имя") элементов и атрибутов можно считать пустой
строкой, если обработка пространства имен не разрешена. Код обрабатывает этот случай,
используя полное имя, когда простое имя представляет собой пустую строку.

7.3.8.3. События для символов


Для завершения обработки событий содержимого необходимо обработать символы,
которые анализатор передает в ваше приложение.
От анализаторов не требуется возвращать какое-то конкретное количество символов за
какое-то время. Анализатор может вернуть все, начиная от одного символа до нескольких
тысяч, и все-таки быть соответствующей стандартам реализацией. Таким образом, если
в приложении нужно обработать символы, которые оно видит, желательно собрать символы
в буфер, и работать с ними только в случае полной уверенности в том, что все они были
найдены.
Добавьте выделенный ниже код для определения текстового буфера:

public class Echo01 extends DefaultHandler


{

StringBuffer textBuffer;

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 115 из 626

public static void main(String argv[])


{

...
Затем добавьте выделенный ниже код для сбора символов, переданных анализатором, в
буфер:

public void endElement(...)


throws SAXException
{
...
}

public void characters(char buf[], int offset, int len)


throws SAXException
{
String s = new String(buf, offset, len);
if (textBuffer == null) {
textBuffer = new StringBuffer(s);
} else {
textBuffer.append(s);
}
}

private void emit(String s)


...
Далее, добавьте метод, выделенный ниже, для передачи содержимого буфера в выходной
поток.

public void characters(char buf[], int offset, int len)


throws SAXException
{
...
}

private void echoText()


throws SAXException
{

Web-

Rendered by www.RenderX.com
Стр. 116 из 626 Simple API for XML

if (textBuffer == null) return;


String s = ""+textBuffer
emit(s);
textBuffer = null;
}

private void emit(String s)


...
После вызова этого метода дважды на строку (что будет происходить вовремя, как мы
увидим далее), буфер станет нулевым. В этом случае метод просто возвращает управление.
Если буфер не пуст, его содержимое передается в выходной поток.
И, наконец, добавьте выделенный ниже код для дублирования содержимого буфера в
начале элемента и в конце:

public void startElement(...)


throws SAXException
{
echoText();
String eName = sName; //
...
}

public void endElement(...)


throws SAXException
{
echoText();
String eName = sName; //
...
}
Сбор текста завершается, когда заканчивается элемент. То есть, в этот момент времени
вы выводите его в выходной поток, и буфер очищается перед началом следующего
элемента.
Но вы хотите выводить собранный текст и в начале элемента! Это необходимо для данных,
составляющих документ, которые могут содержать XML-элементы, смешанные с текстом.
Например, как в этом фрагменте документа:

<para>This paragraph contains <bold>important</bold>


ideas.</para>
В начале текст "This paragraph contains" завершается начальным элементом <bold>. Текст
"important" заканчивается завершающим тегом </bold>, а оставшийся текст "ideas."
заканчивается тегом </para>.

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 117 из 626

Примечание: В большинстве случаев собранный текст будет выводиться при возникновении


события endElement(). Когда после этого возникает событие startElement(), буфер еще
пуст. В первой строке метода echoText() проверяется эта ситуация и производится возврат
из метода.
Поздравляем! Вы написали полное приложение SAX-анализатора. Следующим действием
является его компиляция и выполнение.
Примечание: Чтобы быть абсолютно точным, обработчик символов должен просматривать
буфер в поисках символов амперсанда ("&") и левой угловой скобки ("<") и заменять их
строками "&amp;" или "&lt;" соответственно. Более подробно об этом типе обработки мы
расскажем в разделе "Замена и вставка текста".

7.3.9. Компиляция и выполнение программы


В Java WSDP JAXP-библиотеки находятся в каталоге <JWSDP_HOME>/common/lib. Для
компиляции программы необходимо прежде всего установить JAR-файлы JAXR в
соответствующее место. (Названия JAR-файлов зависят от используемой версии JAXP,
а их месторасположение зависит от используемой версии платформы Java. Для получения
самой последней информации обратитесь к файлу
<JWSDP_HOME>/docs/jaxp/ReleaseNotes.html.)
Примечание: Поскольку JAXP 1.1 встроен в версию 1.4 платформы Java 2, вы можете,
также, выполнить большинство примеров разделов JAXP этого руководства (SAX, DOM и
XSLT) без какой-либо специальной установки JAR-файлов. Однако, для использования
дополнительных возможностей в JAXP - XML Schema и компилирующего транслятора
XSLTC вам необходимо установить JAXP 1.2.
В версиях 1.2 и 1.3 платформы Java 2 для компиляции и запуска программы можно
выполнить следующие команды:

javac -classpath jaxp-jar-files Echo.java


java -cp jaxp-jar-files Echo slideSample.xml
В качестве альтернативы, можно разместить JAR-файлы в каталоге расширений платформы
Java и использовать более простые команды:

javac Echo.java
java Echo slideSample.xml
В версии 1.4 платформы Java 2 необходимо идентифицировать JAR-файлы как более
новые версии "рекомендованных стандартов", которые встроены в платформу Java 2. Для
этого разместите JAR-файлы в каталоге рекомендованных стандартов - jre/lib/endorsed.
(Скопируйте все JAR-файлы, кроме jaxp-api.jar. Его можно проигнорировать, поскольку
JAXP API уже встроен в платформу Java 2 версии 1.4.)
Затем можно откомпилировать и запустить программу при помощи следующих команд:

javac Echo.java
java Echo slideSample.xml

Web-

Rendered by www.RenderX.com
Стр. 118 из 626 Simple API for XML

Примечание: Можно, также, установить системное свойство java.endorced.dirs из командной


строки таким образом, чтобы он указывал на каталог, содержащий необходимые JAR-
файлы, используя следующий параметр командной строки: -D"java.endorsed.dirs=somePath".

7.3.10. Проверка выводимой информации


Вот часть выводимой программой информации, содержащей некоторые непонятные
разделители:

...
<slideshow title="Sample Slide Show" date="Date of publication"
author="Yours Truly">

<slide type="all">
<title>Wake up to WonderWidgets!</title>
</slide>
...
Примечание: Выводимая программой информация находится в файле Echo01-01.txt.
(Версия для броузера - Echo01.01.html.)
При взгляде на эту информацию возникает несколько вопросов. А именно, откуда
появляются лишние пустые строки? И почему элементы располагаются с правильными
отступами, хотя в коде для этого ничего не делалось? Мы ответим на эти вопросы. Прежде
всего, необходимо сделать несколько замечаний о выводимой информации:
• Комментарии, определенные в начале файла
<!-- A SAMPLE set of slides -->
не появляются в листинге. Комментарии будут игнорироваться до тех пор, пока вы не
реализуете LexicalHandler. Более подробно этот вопрос рассмотрен ниже.
• Атрибуты элемента перечисляются все вместе на одной строке. Если ваше окно
недостаточно широко, вы можете их всех не увидеть.
• Определенный вами пустой элемент (<item/>) выводится как пустой элемент из двух
тегов (<item></item>). Они в любых случаях идентичны. (Просто первый легче набирать
и он занимает меньше места.)

7.3.11. Идентификация событий


Данная версия программы дублирования может быть полезна для отображения XML-
файла, но она не много расскажет вам о том, что происходит в анализаторе. Следующим
шагом является изменение программы таким образом, чтобы можно было определить,
откуда появляются пробелы и вертикальные линии.
Примечание: Исходный код, приведенный в этом разделе, находится в файле Echo02.java.
Выходная информация, которую он отображает, находится в файле Echo02-01.txt. (Версия
для броузера - Echo02-01.html.)

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 119 из 626

Сделайте выделенные ниже изменения для идентификации событий по мере их


возникновения:

public void startDocument()


throws SAXException
{
nl();
nl();
emit("START DOCUMENT");
nl();
emit("<?xml version='1.0' encoding='UTF-8'?>");
nl();
}

public void endDocument()


throws SAXException
{
nl();
emit("END DOCUMENT");
try {
...
}

public void startElement(...)


throws SAXException
{
echoText();
nl();
emit("ELEMENT: ");
String eName = sName; //
if ("".equals(eName)) eName = qName; // not namespaceAware
emit("<"+eName);
if (attrs != null) {
for (int i = 0; i < attrs.getLength(); i++) {
String aName = attrs.getLocalName(i); //
if ("".equals(aName)) aName = attrs.getQName(i);
emit(" ");
emit(aName+"=\""+attrs.getValue(i)+"\"");
nl();
emit(" ATTR: ");
emit(aName);

Web-

Rendered by www.RenderX.com
Стр. 120 из 626 Simple API for XML

emit("\t\"");
emit(attrs.getValue(i));
emit("\"");
}
}
if (attrs.getLength() > 0) nl();
emit(">");
}

public void endElement(...)


throws SAXException
{
echoText();
nl();
emit("END_ELM: ");
String eName = sName; //
if ("".equals(eName)) eName = qName; // not namespaceAware
emit("<"+eName+">");
}

...

private void echoText()


throws SAXException
{
if (textBuffer == null) return;
nl();
emit("CHARS: |");
String s = ""+textBuffer
emit(s);
emit("|");
textBuffer = null;
}
Откомпилируйте и выполните эту версию программы для создания более информативного
выходного листинга. Атрибуты показываются по одному на строку, и это уже неплохо. Но,
что более важно, такие строки как, например:

CHARS: |

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 121 из 626

показывают, что и отступы и символы новой строки, разделяющие атрибуты, происходят


от данных, которые анализатор передает в метод characters().
Примечание: Спецификация XML требует, чтобы все разделители строки были приведены
к одинарному символу новой строки. Символ новой строки определяется также, как в
языках Java, С и системах UNIX, но в системах Windows известен под псевдонимом "перевод
строки".

7.3.12. Сжатие выводимой информации


Чтобы сделать выводимую информацию более удобной для чтения, измените программу
так, чтобы она выводила только символы, отличные от пробелов.
Примечание: Исходный код, приведенный в этом разделе, находится в файле Echo03.java.
Сделайте выделенные ниже изменения для подавления вывода пробелов:

public void echoText()


throws SAXException
{
nl();
emit("CHARS: |");
emit("CHARS: ");
String s = ""+textBuffer;
if (!s.trim().equals("")) emit(s);
emit("|");
}
Далее, добавьте выделенный ниже код для вывода каждого набора символов, переданных
анализатором:

public void characters(char buf[], int offset, int len)


throws SAXException
{
if (textBuffer != null) {
echoText();
textBuffer = null;
}
String s = new String(buf, offset, len);
...
}
Если выполнить программу сейчас, можно увидеть, что табуляции также были удалены,
поскольку они являются частью пробелов перед началом элемента. Добавьте выделенный
ниже код для управления табуляцией:

static private Writer out;

Web-

Rendered by www.RenderX.com
Стр. 122 из 626 Simple API for XML

private String indentString = " "; //

private int indentLevel = 0;

...

public void startElement(...)


throws SAXException
{
indentLevel++;
nl();
emit("ELEMENT: ");
...
}

public void endElement(...)


throws SAXException
{
nl();
emit("END_ELM: ");
emit("</"+sName+">");
indentLevel--;
}
...
private void nl()
throws SAXException
{
...
try {
out.write(lineEnd);
for (int i=0; i < indentLevel; i++)
out.write(indentString);
} catch (IOException e) {
...
}
В этом фрагменте устанавливается строка с пробелами для табуляции, отслеживается
текущий уровень табуляции и эта строка выводится в каждом методе n1. Если установить
строку табуляции в "", то информация будет выводиться без табуляций. (Попробуйте. Вы
увидите, что добавление табуляции было не лишней работой.)

Web-

Rendered by www.RenderX.com
Дублирование XML-файла при помощи SAX-анализатора Стр. 123 из 626

Вы, наверно, будете счастливы узнать, что вы достигли конца "механического" кода,
который нужно было добавить в программу Echo. С этого момента вы будете выполнять
работу, которая позволит понять внутреннюю работу анализатора, хотя действия, которые
вы уже выполнили, дали понимание того, как анализатор видит обрабатываемые XML-
данные. Вы также научились использовать полезное средство отладки для просмотра
того, что видит анализатор.

7.3.13. Исследование выходной информации


Вот часть выходной информации этой версии программы:

ELEMENT: <slideshow
...
>
CHARS:
CHARS:
ELEMENT: <slide
...
END_ELM: </slide>
CHARS:
CHARS:
Примечание: Выходная информация в полном виде находится в файле Echo03-01.txt.
(Версия для броузера - Echo03-01.html).
Обратите внимание на то, что метод characters вызывается дважды для каждой строки.
Исследование исходного файла slideSample01.xml показывает, что перед первым слайдом
есть комментарий. Первый вызов characters приходит перед этим комментарием. Второй
вызов - после. (Далее вы увидите, как можно получить уведомление о встрече анализатором
комментария, хотя в большинстве случаев оно вам не нужно.)
Обратите внимание, что метод characters вызывается после первого элемента slide, так
же как и перед ним. Если рассуждать с точки зрения иерархически структурированных
данных - это кажется странным. В конце концов, вы ожидали, что элемент slideshow
содержит элементы slide, а не текст. Дальше вы увидите, как ограничить элемент slideshow
при помощи DTD. После этого метод characters не будет больше вызываться.
При отсутствии DTD анализатор должен предположить, что любой элемент, который он
видит, содержит текст, как первый элемент item в рассматриваемом примере:

<item>Why <em>WonderWidgets</em> are great</item>


Вот как примерно выглядит иерархическая структура:

ELEMENT: <item>
CHARS: Why
ELEMENT: <em>
CHARS: WonderWidgets

Web-

Rendered by www.RenderX.com
Стр. 124 из 626 Simple API for XML

END_ELM: </em>
CHARS: are great
END_ELM: </item>

7.3.14. Документы и данные


В данном примере видно, что символы смешаны с иерархической структурой элементов.
Тот факт, что текст может окружать элементы (если это не запрещено в DTD или в схеме)
помогает объяснить, почему вы иногда слышите разговоры о "XML-данных", а иногда - о
"XML-документах". XML прекрасно справляется и со структурированными данными и с
текстовыми документами, содержащими разметку. Единственным различием между ними
является то, разрешен или нет текст между элементами.
Примечание: В следующем разделе руководства вы будете работать с методом ignorable-
Whitespace интерфейса ContentHandler. Этот метод может быть вызван только при наличии
DTD. Если в DTD указано, что slideshow не содержит текст, то все пробелы, окружающие
элементы slide, игнорируются по определению. С другой стороны, если slideshow может
содержать текст (что должно предполагаться истинным при отсутствии DTD), то анализатор
должен предположить, что видимые им пробелы и линии между элементами slide являются
важными частями документа.

7.4. Добавление дополнительных обработчиков событий


Кроме метода ignorableWhitespace существуют еще два метода ContentHandler, которые
могут найти применение даже в простых приложениях: setDocumentLocator и processingIn-
struction. В этом разделе руководства вы реализуете эти два обработчика событий.

7.4.1. Указание месторасположения документа


Локатор - это объект, содержащий информацию, необходимую для поиска документа.
Класс Locator инкапсулирует либо системный ID (URL), либо общедоступный идентификатор
(URN), либо оба сразу. Вам может понадобиться эта информация при поиске чего-нибудь
относительно текущего документа (точно так же, как HTML-броузер обрабатывает атрибут
href= "anotherFile" в теге anchor - броузер использует месторасположение текущего
документа для поиска anotherFile).
Также вы могли бы использовать локатор для распечатки хороших диагностических
сообщений. Кроме месторасположения документа и общедоступного идентификатора
локатор содержит методы, выдающие номер строки и столбца самого последнего
обработанного события. Метод setDocumentLocator вызывается только один раз в начале
анализа. Для получения номеров текущей строки и столбца вы должны сохранить локатор
при вызове setDocumentLocator и затем использовать его в других методах обработки
событий.
Примечание: Обсуждаемый в этом разделе код находится в файле Echo04.java. Выходная
информация - в Echo04-01.txt. (Версия для броузера - Echo04-01.html).
Начните с удаления дополнительного кода вывода символов, добавленного вами в
последнем примере:

public void characters(char buf[], int offset, int len)

Web-

Rendered by www.RenderX.com
Добавление дополнительных обработчиков событий Стр. 125 из 626

throws SAXException
{
if (textBuffer != null) {
echoText();
textBuffer = null;
}
String s = new String(buf, offset, len);
...
}
Затем добавьте выделенный ниже метод в программу Echo для получения локатора
документа и используйте его для вывода системного ID документа:

...
private String indentString = " "; //

private int indentLevel = 0;

public void setDocumentLocator(Locator l)


{
try {
out.write("LOCATOR");
out.write("SYS ID: " + l.getSystemId() );
out.flush();
} catch (IOException e) {
//
}
}

public void startDocument()


...
Примечания:
• Этот метод, в отличие от любого другого метода ContentHandler, не возвращает
SAXException. Так что вместо использования emit для вывода, этот код производит
запись непосредственно в System.out. (Этот метод обычно используется просто для
сохранения Locator для дальнейшего использования, а не для какой-либо обработки,
генерирующей исключительную ситуацию, как в данном случае.)
• Эти методы записываются через "Id", не "ID", то есть, getSystemId и getPublicId.
После компиляции и выполнения программы с файлом slideSample01.xml на экране среди
прочей информации отобразится:

Web-

Rendered by www.RenderX.com
Стр. 126 из 626 Simple API for XML

LOCATOR
SYS ID: file:<path>/../samples/slideSample01.xml

START DOCUMENT
<?xml version='1.0' encoding='UTF-8'?>
...
Отсюда видно, что setDocumentLocator вызывается перед startDocument. Это может иметь
значение в случаях, когда вы проводите какую-либо инициализацию в коде обработки
событий.

7.4.2. Управление командами обработки


Иногда имеет смысл закодировать команды обработки, зависящие от приложения, в XML-
данных. В этом упражнении вы добавите команду обработки в ваш файл slideSample.xml
и затем измените программу Echo для ее отображения.
Примечание: Код, обсуждаемый в этом разделе находится в файле Echo05.java. Данные
- в файле slideSample02.xml. Выходная информация - в файле Echo05-02.txt. (Версии для
броузера - slideSample02-xml.html и Echo05-02.html.)
Как вы увидели в разделе "Освоение XML", формат команд обработки: <?target data?>,
где "target" является приложением, которое должно выполнить обработку, а "data" - это
команда обработки или информация для нее. Добавьте выделенный ниже текст, чтобы
добавить команду обработки для мифической программы презентации слайдов,
запрашивающую пользователя, какие слайды показывать (для технического персонала,
для дирекции, или все):

<slideshow
...
>

<!-- PROCESSING INSTRUCTION -->


<?my.presentation.Program QUERY="exec, tech, all"?>

<!-- TITLE SLIDE -->


Примечания:
• Часть "data" команды обработки может содержать пробелы, или даже может быть
пустой. Но не должно быть каких-либо пробелов между начальным <? и
идентификатором target.
• Данные начинаются после первого пробела.
• Имеет смысл полное задание программы назначения с полным уникальным для Web
префиксом пакета, чтобы предотвратить какие-либо конфликты с другими программами,
которые могут обрабатывать те же самые данные.

Web-

Rendered by www.RenderX.com
Добавление дополнительных обработчиков событий Стр. 127 из 626

• Для улучшения читаемости хорошей идеей является помещение двоеточия (:) после
имени приложения, например:

<?my.presentation.Program: QUERY="..."?>
Двоеточие подчеркивает, что имя назначения является "меткой", указывающей
получателя команды. Однако, хотя спецификация w3c разрешает использование
двоеточия в имени назначения, некоторые версии IE5 считают это ошибкой. В данном
руководстве мы будем стараться не использовать двоеточия в имени назначения.
Теперь, когда вы имеете команду обработки, с которой можно работать, добавьте
выделенный ниже код в приложение Echo:

public void characters(char buf[], int offset, int len)


...
}

public void processingInstruction(String target, String data)


throws SAXException
{
nl();
emit("PROCESS: ");
emit("<?"+target+" "+data+"?>");
}

private void echoText()


...
Откомпилируйте и выполните программу. Интересующая нас часть выводимой информации
должна выглядеть примерно так:

ELEMENT: <slideshow
...
>
PROCESS: <?my.presentation.Program QUERY="exec, tech, all"?>
CHARS:
...

7.4.3. Резюме
За исключением метода ignorableWhitespace вы использовали большинство методов
ContentHandler, которые были необходимы для управления наиболее полезными SAX-
событиями. Вы изучите использование ignorableWhitespace немного позднее. Далее вы
получите более глубокие знания в обработке ошибок, возникающих в процессе SAX-анализа.

Web-

Rendered by www.RenderX.com
Стр. 128 из 626 Simple API for XML

7.5. Обработка ошибок в неверифицирующем анализаторе


Эта версия программы Echo использует неверифицирующий анализатор. Поэтому нельзя
определить, содержит ли XML-документ правильные теги, или в правильной ли
последовательности они расположены. Другими словами, нельзя определить, правильно
ли составлен документ. Однако можно определить, является ли документ формально-
правильным.
В этом разделе руководства вы измените файл программы презентации слайдов для
генерации различных типов ошибок и увидите, как анализатор обрабатывает их. Вы узнаете,
также, при каких условиях ошибки игнорируются и как их обработать в этих случаях.

7.5.1. Введение в ошибки


Анализатор может генерировать три типа ошибок: фатальные ошибки, ошибки и
предупреждения. В этом упражнении вы сделаете простое изменение в XML-файл для
генерации фатальной ошибки. Затем вы увидите, как она обрабатывается в приложении
Echo.
Примечание: XML-структура для этого упражнения находится в файле slideSampleBad1.xml.
Выводимая информация - в файле Echo05-Bad1.txt. (Версии для броузера - slideSampleBad1-
xml.html и Echo05-Bad1.html.)
Одним из простых способов получения фатальной ошибки является удаление
завершающего символа "/" из пустого элемента item для создания тега, не имеющего
соответствующего завершающего тега. Это создает фатальную ошибку, поскольку все
XML-документы должны быть формально-правильными. Выполните следующие действия:
1. Скопируйте slideSample.xml в badSample.xml.
2. Отредактируйте badSample.xml и удалите символ, как показано ниже:

...
<!-- OVERVIEW -->
<slide type="all">
<title>Overview</title>
<item>Why <em>WonderWidgets</em> are great</item>
<item/>
<item>Who <em>buys</em> WonderWidgets</item>
</slide>
...
в результате получится:

...
<item>Why <em>WonderWidgets</em> are great</item>
<item>
<item>Who <em>buys</em> WonderWidgets</item>
...

Web-

Rendered by www.RenderX.com
Обработка ошибок в неверифицирующем анализаторе Стр. 129 из 626

3. Выполните программу Echo с новым файлом.


На экране должно отобразиться сообщение об ошибке, которое выглядит примерно так
(отформатировано для лучшей читаемости):

org.xml.sax.SAXParseException:
The element type "item" must be terminated by the
matching end-tag "</item>".
...
at org.apache.xerces.parsers.AbstractSAXParser...
...
at Echo.main(...)
Примечание: Приведенное выше сообщение сгенерировано библиотеками JAXP 1.2. Если
вы используете другой анализатор, сообщение об ошибке, возможно, будет другим.
При возникновении фатальной ошибки анализатор не сможет продолжать работу. Поэтому,
если приложение не генерирует исключительную ситуацию (вы вскоре увидите, как это
сделать), то ее сгенерирует обработчик ошибок событий по умолчанию. Стек трассировки
генерируется обработчиком исключительных ситуаций Throwable в вашем методе main:

...
} catch (Throwable t) {
t.printStackTrace();
}
Этот стек трассировки не очень полезен. Далее вы увидите, как генерировать более
хорошую диагностику при возникновении ошибок.

7.5.2. Обработка SAXParseException


Когда анализатор встречает ошибку, он генерирует SAXParseException - подкласс
SAXException, которая указывает файл и место, где произошла ошибка.
Примечание: Код этого упражнения находится в файле Echo06.java. Выводимая информация
- в файле Echo06-Bad1.txt. (Версия для броузера - Echo06-Bad1.html.)
Добавьте выделенный ниже код для генерации более подробного диагностического
сообщения при возникновении исключительной ситуации:

...
} catch (SAXParseException spe) {
// ,
System.out.println("\n** Parsing error"
+ ", line " + spe.getLineNumber()
+ ", uri " + spe.getSystemId());
System.out.println(" " + spe.getMessage() );

Web-

Rendered by www.RenderX.com
Стр. 130 из 626 Simple API for XML

} catch (Throwable t) {
t.printStackTrace();
}
Сейчас при выполнении программы выдается немного более полезная информация об
ошибке:

** Parsing error, line 22, uri file:<path>/slideSampleBad1.xml


The element type "item" must be ...
Примечание: Текст сообщения об ошибке зависит от используемого анализатора.
Приведенное выше сообщение генерируется JAXP 1.2.
Примечание: Перехват всех исключительных ситуаций Throwable обычно не является
хорошей идеей при разработке приложений. Мы делаем это сейчас для того, чтобы
постепенно построить полную систему обработки ошибок. Кроме того, при таком решении
перехватываются все исключительные ситуации нулевого указателя, которые могут быть
сгенерированы при передаче анализатору значения null.

7.5.3. Обработка SAXException


Иногда анализатор может сгенерировать более общую SAXException, но чаще встречаются
случаи, когда ошибка в приложении возникает в одном из методов обработки событий.
Например, сигнатура метода stsrtDocument в интерфейсе ContentHandler определяется с
указанием возврата SAXException:

public void startDocument() throws SAXException


Все методы ContentHandler (за исключением setDocumentLocator) содержат это объявление
в сигнатуре.
SAXException может быть составлена с использованием сообщения, другой исключительной
ситуации или и того, и другого. Так, например, когда Echo.satrtDocument выводит строку в
методе emit, любая возможная исключительная ситуация ввода/вывода заключается в
SAXException и передается назад анализатору:

private void emit(String s)


throws SAXException
{
try {
out.write(s);
out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);
}
}

Web-

Rendered by www.RenderX.com
Обработка ошибок в неверифицирующем анализаторе Стр. 131 из 626

Примечание: Если вы при вызове setDocumentLocator сохранили объект Locator, вы можете


использовать его для генерации SAXParseException, указывая документ и место, вместо
генерации SAXException.
Когда анализатор передает исключительную ситуацию назад в вызвавший его код, имеет
смысл использовать оригинальную исключительную ситуацию для генерации стека
трассировки. Для этого добавьте выделенный ниже код:

...
} catch (SAXParseException err) {
System.out.println("\n** Parsing error"
+ ", line " + err.getLineNumber()
+ ", uri " + err.getSystemId());
System.out.println(" " + err.getMessage());

} catch (SAXException sxe) {


// ,
// ( )
Exception x = sxe;
if (sxe.getException() != null)
x = sxe.getException();
x.printStackTrace();

} catch (Throwable t) {
t.printStackTrace();
}
Этот код проверяет, содержит ли SAXException в себе другую исключительную ситуацию.
Если да, то генерирует стек трассировки, начиная с места, где произошла исключительная
ситуация, для точного определения кода, вызвавшего ошибку. Если исключительная
ситуация содержит только сообщение, код распечатывает стек трассировки начиная с
места, где была сгенерирована исключительная ситуация.

7.5.4. Усовершенствование обработчика SAXParseException


Поскольку SAXParseException может содержать в себе другую исключительную ситуацию,
добавьте выделенный ниже код, чтобы использовать вложенную исключительную ситуацию
для стека трассировки:

...
} catch (SAXParseException err) {
System.out.println("\n** Parsing error"
+ ", line " + err.getLineNumber()
+ ", uri " + err.getSystemId());
System.out.println(" " + err.getMessage());

Web-

Rendered by www.RenderX.com
Стр. 132 из 626 Simple API for XML

//
// ,
Exception x = spe;
if (spe.getException() != null)
x = spe.getException();
x.printStackTrace();

} catch (SAXException sxe) {


// ,

// ( )
Exception x = sxe;
if (sxe.getException() != null)
x = sxe.getException();
x.printStackTrace();

} catch (Throwable t) {
t.printStackTrace();
}
Теперь программа готова к обработке любой возможной исключительной ситуации при
SAX-анализе. Вы увидели, что для фатальных ошибок анализатор генерирует
исключительные ситуации. Но для не фатальных ошибок и предупреждений обработчик
ошибок по умолчанию никогда не генерирует исключительных ситуаций, и никакие
сообщения не выводятся. Через минуту вы изучите более подробно ошибки и
предупреждения, а также узнаете, как создавать обработчик ошибок для их обработки.

7.5.5. Обработка ParserConfigurationException


И, наконец, вспомните, что класс SAXParserFactory может генерировать исключительную
ситуацию при невозможности создания анализатора. Такая ошибка может произойти, если
генератор не может найти класс, необходимый для создания анализатора (ошибка "класс
не найден"), не имеет разрешения для доступа к нему (исключительная ситуация
"несанкционированный доступ"), или не может создать экземпляр анализатора (ошибка
создания экземпляра).
Добавьте выделенный ниже код для обработки таких ошибок:

} catch (SAXException sxe) {


Exception x = sxe;
if (sxe.getException() != null)
x = sxe.getException();
x.printStackTrace();

Web-

Rendered by www.RenderX.com
Обработка ошибок в неверифицирующем анализаторе Стр. 133 из 626

} catch (ParserConfigurationException pce) {


//

pce.printStackTrace();

} catch (Throwable t) {
t.printStackTrace();
Конечно, существует довольно много обработчиков ошибок. Но, по крайней мере, вы знаете
типы исключительных ситуаций, которые могут произойти.
Примечание: Если класс генератора, указанный в системном свойстве, не может быть
найден или создан, может сгенерироваться также javax.xml.parsers.FactoryConfigurationError.
Это неперехватываемая ошибка, поскольку программа не может продолжать выполнение
после нее.

7.5.6. Обработка IOException


Наконец, добавим обработчик для IOExceptions:

} catch (ParserConfigurationException pce) {


//

pce.printStackTrace();

} catch (IOException ioe) {


// I/O
ioe.printStackTrace();
}

} catch (Throwable t) {
...
Мы выйдем из обработчика для Throwables для перехвата ошибок нулевых указателей,
но обратите внимание, что в этом месте он делает то же самое, что и обработчик IOExcep-
tion. Здесь мы просто демонстрируем типы исключительных ситуаций, которые могут
произойти, в случае если после них ваше приложение способно продолжать выполнение.

7.5.7. Обработка нефатальных ошибок


Нефатальная ошибка возникает тогда, когда в XML-документе не выполняются ограничения
на правильность. Если анализатор обнаруживает, что документ является неправильным,
генерируется событие ошибки. Такие ошибки генерируются верифицирующим анализатором
при наличии DTD либо схемы, когда документ содержит неверный тег, либо тег обнаружен
в месте, где он не должен быть, либо (в случае схемы) если элемент содержит
неправильные данные.

Web-

Rendered by www.RenderX.com
Стр. 134 из 626 Simple API for XML

С вопросами верификации вы столкнетесь дальше в этом руководстве. Но, поскольку мы


обсуждаем обработку ошибок, вы напишете код обработки ошибок сейчас.
Наиболее важной чертой нефатальных ошибок, которую нужно понимать, является то, что
они по умолчанию игнорируются.
Но если в документе происходит ошибка верификации, вы, возможно, не захотите
продолжать обрабатывать его. Возможно, вы захотите считать такие ошибки фатальными.
В следующем коде вы настроите обработчик ошибок именно на такую работу.
Примечание: Код программы этого упражнения находится в файле Echo07.java.
Для контроля обработки ошибок вы переопределяете методы DefaultHandler, которые
обрабатывают фатальные ошибкит, нефатальные ошибки и предупреждения, как часть
интерфейса ErrorHandler. SAX-анализатор передает SAXParseException каждому из этих
методов, так что сгенерировать исключительную ситуацию при возникновении ошибки так
же легко, как и передать ее обратно.
Добавьте выделенный ниже код для переопределения обработчика ошибок:

public void processingInstruction(String target, String data)


throws SAXException
{
...
}

//
public void error(SAXParseException e)
throws SAXParseException
{
throw e;
}
Примечание: Полезно проанализировать методы обработки ошибок, определенные в
org.xml.sax.helpers.DefaultHandler. Вы увидите, что методы error() и warning() не делают
ничего, а fatalError() генерирует исключительную ситуацию. Кончено, вы всегда можете
переопределить метод fatalError() для генерации другой исключительной ситуации. Но
если ваш код не генерирует исключительную ситуацию при возникновении фатальной
ошибки, это сделает SAX-анализатор - так требует спецификация XML.

7.5.8. Обработка предупреждений


Предупреждения тоже по умолчанию игнорируются. Предупреждения содержат информацию
и требуют наличия DTD. Например, если элемент в DTD определен дважды, генерируется
предупреждение - это не является не правильным и не вызывает проблем, но возможно,
это может привести не к тем результатам, которых вы ожидали.
Добавьте выделенный ниже код для генерации сообщения при возникновении
предупреждения:

Web-

Rendered by www.RenderX.com
Замена и вставка текста Стр. 135 из 626

//
public void error(SAXParseException e)
throws SAXParseException
{
throw e;
}

//
public void warning(SAXParseException err)
throws SAXParseException
{
System.out.println("** Warning"
+ ", line " + err.getLineNumber()
+ ", uri " + err.getSystemId());
System.out.println(" " + err.getMessage());
}
Поскольку не существует нормального способа генерации сообщения без DTD или схемы,
вы пока еще ничего не сможете увидеть. Но как только это произойдет, вы уже будете
готовы!

7.6. Замена и вставка текста


На следующем шаге мы немного переделаем анализатор, так чтобы вы могли получить
информацию, которую он обычно игнорирует. Но перед этим вам необходимо изучить
несколько важных концепций XML. В этом разделе вы ознакомитесь с:
• Обработкой специальных символов ("<", "&" и т.д.)
• Обработкой текста с синтаксисом XML

7.6.1. Обработка специальных символов


В XML сущностью называется XML-структура (или простой текст), имеющая имя. Обращение
к сущности по имени приводит к вставке ее в то место документа, откуда производится
обращение. Для создания ссылки на сущность ее имя заключается между символами
амперсанда и точки с запятой, например:

&entityName;
Позже, при изучении DTD, вы узнаете, что можно определять свои собственные сущности,
так чтобы &yourEntityName; расширялся полностью в текст, определенный вами для этой
сущности. А сейчас мы рассмотрим предопределенные сущности и символьные ссылки,
не требующие какого-либо специального определения.

Web-

Rendered by www.RenderX.com
Стр. 136 из 626 Simple API for XML

7.6.1.1. Предопределенные сущности


Такая сущность, как, например, &amp; содержит имя (в данном случае "amp") между
начальным и конечным ограничителями. Текст, к которому ведет ссылка (&), замещает
имя подобно макросу в программах С или C++. В таблице 6-1 перечислены
предопределенные сущности для специальных символов.
Таблица 6-1 Предопределенные сущности
Символ Ссылка
& &amp;
< &lt;
> &gt;
" &quot;
' &apos;

7.6.1.2. Символьные ссылки


Символьная ссылка &#147; содержит символ "решетки" ("#"), после которого следует число.
Число представляет значение одного символа в кодировке Unicode, как, например, 65 для
символа "A", 147 для левых кавычек или 148 для правых кавычек. В данном случае "name"
сущности - знак решетки с числом, определяющим символ.
Примечание: XML считает, что значения записаны в десятичной системе. Однако, таблица
кодировки Unicode на сайте http://www.unicode.org/charts/ указывает значения в
шестнадцатиричном формате! Поэтому вам необходимо преобразовывать их для получения
правильного значения при вставке в XML-данные.

7.6.2. Использование ссылки на сущность в XML-документе


Предположим, что вы хотите вставить следующую строку в ваш XML-документ:

Market Size < predicted


Проблема при вставке этой строки прямо в XML-файл заключается в том, что когда
анализатор встречает знак левой угловой скобки (<), он начинает искать имя тега, что
нарушает анализ. Для решения этой проблемы вы помещаете в файл &lt; вместо "<".
Примечание: Результаты приведенной ниже модификации находятся в файле slideSam-
ple03.xml. Результаты обработки показаны в файле Echo07-03.txt. (Версии для броузера
- slideSample03-xml.html и Echo07-03.html.)
Если вы следуете указаниям руководства, добавьте выделенный ниже текст в ваш файл
slideSample.xml:

<!-- OVERVIEW -->


<slide type="all">
<title>Overview</title>
...
</slide>

Web-

Rendered by www.RenderX.com
Замена и вставка текста Стр. 137 из 626

<slide type="exec">
<title>Financial Forecast</title>
<item>Market Size &lt; predicted</item>
<item>Anticipated Penetration</item>
<item>Expected Revenues</item>
<item>Profit Margin </item>
</slide>

</slideshow>
После выполнения программы Echo с вашим XML-файлом вы увидите следующую
информацию на экране:

ELEMENT: <item>
CHARS: Market Size < predicted
END_ELM: </item>
Анализатор преобразовал ссылку на сущность в ее значение и передал в приложение.

7.6.3. Обработка текста с синтаксисом XML


При обработке больших частей XML или HTML, включающих большое количество
специальных символов, очень неудобно заменять каждый из них соответствующей ссылкой
на сущность. В этих ситуациях можно использовать секцию CDATA.
Примечание: Результаты приведенных ниже изменений находятся в файле slideSam-
ple04.xml. Результаты обработки - в файле Echo07-04.txt. (Версии для броузера -
slideSample04-xml.html и Echo07-04.html.)
Секция CDATA работает подобно <pre>…</pre> в HTML, только немного иначе - пробелы
в CDATA являются значимыми и символы внутри секции не интерпретируются как XML.
Секция CDATA начинается символами и завершается . Добавьте выделенный ниже текст
в ваш файл slideSample.xml, чтобы определить секцию CDATA для воображаемого
технического слайда:

...
<slide type="tech">
<title>How it Works</title>
<item>First we fozzle the frobmorten</item>
<item>Then we framboze the staten</item>
<item>Finally, we frenzle the fuznaten</item>
<item><![CDATA[Diagram:
frobmorten <--------------- fuznaten
| <3> ^
| <1> | <1> = fozzle

Web-

Rendered by www.RenderX.com
Стр. 138 из 626 Simple API for XML

V | <2> = framboze
Staten--------------------+ <3> = frenzle
<2>
]]></item>
</slide>
</slideshow>
После выполнения программы Echo с новым файлом вы увидите следующую информацию
на экране:

ELEMENT: <item>
CHARS: Diagram:

frobmorten <--------------fuznaten
| <3> ^
| <1> | <1> = fozzle
V | <2> = framboze
staten----------------------+ <3> = frenzle
<2>

END_ELM: </item>
Вы можете заметить, что текст в секции CDATA пришел в том же виде, в каком он был
написан. Поскольку анализатор не рассматривал угловые скобки как символы XML, не
были сгенерированы фатальные ошибки, что произошло бы в противном случае. (Если
бы угловых скобок не было бы в секции CDATA, документ не был бы формально-
правильным.)

7.6.4. Обработка CDATA и других символов


Существование секции CDATA несколько усложняет правильный вывод XML в программе
дублирования. Если выводимый текст не находится в секции CDATA, то любые угловые
скобки, амперсанды и другие специальные символы в тексте должны быть заменены
соответствующей ссылкой на сущность. (Замены левой угловой скобки и амперсанда
являются наиболее важными, другие символы будут интерпретироваться правильно без
введения анализатора в заблуждение.)
Но если выводимый текст находится в секции CDATA, то для вывода текста, подобного
приведенному выше, подстановок быть не должно. В простой программе, как в приложении
Echo, это не имеет большого значения. Но многие приложения XML-фильтров для
правильной трактовки специальных символов должны будут отслеживать, находится ли
текст в секции CDATA.
Необходимо также обратить внимание на атрибуты. Текст атрибута тоже может содержать
угловые скобки и точки с запятыми, которые необходимо заменять ссылками на сущности.
(Текст атрибута никогда не может быть в секции CDATA, поэтому не возникает никаких
вопросов при такой подстановке.)

Web-

Rendered by www.RenderX.com
Создание определения типа документа (DTD) Стр. 139 из 626

Далее в этом руководстве вы увидите, как используется LexicalHandler для определения


того, обрабатываете ли вы секцию CDATA. Затем вы узнаете, как определить DTD.

7.7. Создание определения типа документа (DTD)


После XML-объявления пролог документа может включать DTD, позволяющий указать
типы тегов, которые может содержать ваш XML-документ. Кроме указания
верифицирующему анализатору типов правильных тегов и порядка их следования DTD
может указать как верифицирующему, так и неверифицирующему анализаторам место,
где может находиться текст, что дает возможность анализатору определить, являются ли
встреченные им пробелы значимыми, или их можно проигнорировать.

7.7.1. Основные DTD-определения


При анализе программы презентации слайдов, например, вы видели, что метод characters
вызывается несколько раз перед и после комментариев и элементов slide. В том случае
пробелы состояли из концов строки и табуляции, окружающих разметку. Целью такой
разметки было повышение читаемости документа - пробелы никоим образом не были
частью содержимого документа. Перед началом изучения DTD-определений укажем
анализатору места, где пробелы нужно проигнорировать.
Примечание: Определенный в этом разделе DTD содержится в файле slideshow1a.dtd.
(Версия для броузера - slideshow1a-dtd.html.)
Сначала создадим файл с именем slideshow.dtd. Введите XML-объявление и комментарий
для идентификации файла, как показано ниже:

<?xml version='1.0' encoding='utf-8'?>

<!--
DTD for a simple "slide show".
-->
Затем добавьте выделенный ниже текст для указания того, что элемент slideshow содержит
элементы slide и ничего более:

<!-- DTD for a simple "slide show". -->

<!ELEMENT slideshow (slide+)>


Как видите, DTD-тег начинается с символов <!, после которых следует имя тега (ELEMENT).
После имени тега идет имя определяемого элемента (slideshow) и, в круглых скобках, один
или более элементов, определяющих правильное содержимое для этого элемента. В
данном случае запись указывает, что slideshow содержит один или более элементов slide.
Без знака плюс определение указывало бы, что slideshow состоит из одного элемента slide.
В таблице 6-2 перечислены квалификаторы, которые можно добавить в определение
элемента.
Таблица 6-2 Квалификаторы DTD-элемента

Web-

Rendered by www.RenderX.com
Стр. 140 из 626 Simple API for XML

Квалификатор Название Значение


? Знак вопроса Необязателен (ноль или один)
* Звездочка Ноль или более
+ Знак плюс Один или более

Вы можете заключить несколько элементов в круглые скобки, разделив их запятой, и


использовать квалификатор с каждым элементом, чтобы указать, сколько экземпляров
соответствующего элемента может встретиться. Разделенный запятыми список определяет,
какие элементы допустимы и в какой последовательности они должны быть расположены.
Вы можете также вкладывать круглые скобки для группировки нескольких элементов.
Например, после определения элемента image, вы можете объявить, что каждый элемент
image должен быть сгруппирован с элементом title, указав ((image, title)+). Здесь знак плюс
относится к паре image/title и указывает, что может встретиться одна или более таких пар.

7.7.2. Определение текста и вложенных элементов


Теперь, когда вы указали анализатору, где не должно быть текста, укажем, где текст может
быть. Добавьте выделенный ниже текст для определения элементов slide, title, item и list:

<!ELEMENT slideshow (slide+)>


<!ELEMENT slide (title, item*)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT item (#PCDATA | item)* >
В первой добавленной строке указывается, что slide содержит элемент title, после которого
идет ноль или более элементов item. Ничего нового. Следующая строка указывает, что
title полностью состоит из анализируемых символьных данных (PCDATA). Они называются
текстом в большинстве случаев, но в XML они называются "анализируемые символьные
данные". (Это отличает их от секций CDATA, которые содержат неанализируемые
символьные данные.) Знак "#" перед PCDATA указывает, что далее следует специальное
слово, а не имя элемента.
|PCDATAitemPCDATAitemмодели со смешанным содержимымitem#PCDATA|*

7.7.3. Ограничения DTD


Было бы неплохо, если бы мы могли указать, что item содержит либо только текст, либо
текст, за которым следует один или более элементов item. Но такой тип спецификации
тяжело определить в DTD. Например, вы можете соблазниться определить item так:

<!ELEMENT item (#PCDATA | (#PCDATA, item+)) >


Это было бы довольно точно, но как только анализатор увидит #PCDATA и вертикальную
линию, он будет ожидать конец определения для соответствия модели со смешанным
содержимым. Эта спецификация такой модели не соответствует, так что вы получите
ошибку: Illegal mixed content model for 'item'. Foun?#x28;… (Неверная модель со смешанным
содержимым для 'item'. Найден &#28;…), где шестнадцатиричный символ 28 является
угловой скобкой в конце определения.

Web-

Rendered by www.RenderX.com
Создание определения типа документа (DTD) Стр. 141 из 626

Попытка определить элемент item дважды тоже не работает. Спецификация, подобная


этой:

<!ELEMENT item (#PCDATA) >


<!ELEMENT item (#PCDATA, item+) >
выводит предупреждение "duplicate definition" ("двойное определение") при работе
верифицирующего анализатора. Фактически, второе определение игнорируется. По-
видимому, определение модели со смешанным содержимым (позволяющей элементам
item быть разбросанными по тексту) является хорошим настолько, насколько мы можем
его сделать.
Кроме ограничений модели со смешанным содержимым, упомянутых выше, не существует
способа дальнейшей квалификации типа текста, который может встретиться там, где было
указано PCDATA. Должно ли оно содержать только числа? Должно ли быть в формате
даты или денежном формате? Это невозможно указать в контексте DTD.
И, наконец, отметим, что DTD не предлагает никакой иерархии. Определение элемента
title одинаково относится и к заголовку элемента slide и к заголовку элемента item. При
расширении DTD для разрешения HTML-разметки в дополнение к обычному тексту могло
бы иметь смысл ограничение размера заголовка item по сравнению с заголовком slide,
например. Но единственным способом это сделать было бы назначение одному из них
другого имени, например, "item-title". Результатом отсутствия иерархии является то, что
DTD заставляет вас использовать "иерархию дефисов" (или ее эквивалент) в вашем
пространстве имен. Все эти ограничения являются основной движущей силой разработки
стандартов спецификации схем.

7.7.4. Значения специальных элементов в DTD


Вместо указания окруженного скобками списка элементов определение элемента может
использовать одно из двух специальных значений: ANY или EMPTY. Спецификация ANY
обозначает, что элемент может содержать любой другой определенный элемент, или
PCDATA. Эта спецификация обычно используется для корневого элемента XML-документа
общего назначения, такого как, например, создаваемого в текстовом редакторе. Текстовые
элементы могут встречаться в таком документе в любом порядке, поэтому имеет смысл
указывать ANY.
Спецификация EMPTY означает, что элемент не имеет содержимого. То есть DTD для
сообщений электронной почты, разрешающее вам "отмечать" сообщение при помощи тега
<flag/>, может иметь примерно такую строку:

<!ELEMENT flag EMPTY>

7.7.5. Ссылка на DTD


В данном случае определение DTD расположено в отдельном файле, а не в XML-документе.
Это значит, что вы должны поставить ссылку на DTD в таком документе, что сделает DTD-
файл частью внешнего подмножества полного DTD для XML-файла. Как вы увидите позже,
можно включить части DTD в документ. Такие определения составляют локальное
подмножество DTD.

Web-

Rendered by www.RenderX.com
Стр. 142 из 626 Simple API for XML

Примечание: XML-документ, написанный в этом разделе, содержится в файле slideSam-


ple05.xml. (Версия для броузера - slideSample05-xml.html.)
Для ссылки на только что созданный DTD добавьте выделенную ниже строку в ваш файл
slideSample.xml:

<!-- A SAMPLE set of slides -->

<!DOCTYPE slideshow SYSTEM "slideshow.dtd">

<slideshow
Опять DTD-тег начинается с "<!". В данном случае имя тега, DOCTYPE, указывает, что
документом является slideshow. Это означает, что документ состоит из элемента slideshow
и всего остального внутри его:

<slideshow>
...
</slideshow>
Этот тег определяет элемент slideshow в качестве корневого элемента документа. XML-
документ должен иметь только один корневой элемент. Именно здесь указывается этот
элемент. Другими словами, этот тег идентифицирует содержимое документа как slideshow.
Тег DOCTYPE располагается после XML-определения и перед корневым элементом.
Идентификатор SYSTEM указывает расположение DTD-файла. Поскольку он не начинается
с префикса типа http:/ или file:/, путь к расположению XML-документа является
относительным. Вспомнили метод setDocumentLocator? Анализатор использует эту
информацию для поиска DTD-файла, так же как делало бы ваше приложение для поиска
файла относительно XML-документа. Мог бы использоваться также идентификатор PUBLIC
для указания того, что DTD-файл использует уникальное имя, но анализатор должен был
быть способен разрешить это имя.
Спецификация DOCTYPE могла бы, также, содержать DTD-определения внутри XML-
документа, а не обращаться к внешнему DTD-файлу. Такие определения должны
заключаться в квадратные скобки, например:

<!DOCTYPE slideshow SYSTEM "slideshow1.dtd" [


...local subset definitions here...
]>
Вы будете использовать преимущества этой возможности позже, при определении
некоторых сущностей, которые могут использоваться в документе.

Web-

Rendered by www.RenderX.com
Влияние DTD на неверифицирующий анализатор Стр. 143 из 626

7.8. Влияние DTD на неверифицирующий анализатор


В последнем разделе вы определили элементарный тип документа и использовали его в
вашем XML-файле. В этом разделе вы будете использовать программу Echo для того,
чтобы увидеть, как данные представляются SAX-анализатору при использовании DTD.
Примечание: Выводимая информация содержится в файле Echo07-05.txt. (Версия для
броузера - в Echo07-05.html.)
Выполнение программы Echo с вашей последней версией slideSample.xml показывает, что
многие лишние вызовы метода characters исчезли.
Там где раньше вы видели:

...
>
PROCESS: ...
CHARS:
ELEMENT: <slide
ATTR: ...
>
ELEMENT: <title>
CHARS: Wake up to ...
END_ELM: </title>
END_ELM: </slide>
CHARS:
ELEMENT: <slide
ATTR: ...
>
...
Сейчас вы увидите:

...
>
PROCESS: ...
ELEMENT: <slide
ATTR: ...
>
ELEMENT: <title>
CHARS: Wake up to ...
END_ELM: </title>
END_ELM: </slide>
ELEMENT: <slide
ATTR: ...

Web-

Rendered by www.RenderX.com
Стр. 144 из 626 Simple API for XML

>
...
Очевидно, что символы пробела, которые раньше выводились вокруг элементов slide,
больше не передаются анализатором, поскольку DTD объявляет, что slideshow состоит
только из элементов slide:

<!ELEMENT slideshow (slide+)>

7.8.1. Отслеживание игнорируемых пробелов


Теперь из-за присутствия DTD анализатор больше не вызывает метод characters с
несущественными пробелами. С точки зрения приложения, которое занимается
исключительно обработкой XML-данных, это замечательно. Приложение никто не беспокоит
пробелами, которые существуют только для повышения читаемости XML-файла.
С другой стороны, если бы вы писали приложение, фильтрующее файл XML-данных, и
хотели бы выводить такую же читаемую версию файла, то эти пробелы уже не были бы
несущественными - они были бы важными. Для получения этих символов вы должны
добавить метод ignorableWhitespace в ваше приложение. Что мы сейчас и сделаем.
Примечание: Написанный в этом разделе код находится в файле Echo08.java. Выводимая
информация - в файле Echo08-05.txt. (Версия для броузера - в Echo08-05.html.)
Чтобы обработать обычно игнорируемые пробелы, которые встречаются анализатору,
добавьте выделенный ниже код для реализации обработчика события ignorableWhitespace
в вашу версию программы Echo:

public void characters (char buf[], int offset, int len)


...
}

public void ignorableWhitespace char buf[], int offset, int Len)


throws SAXException
{
nl();
emit("IGNORABLE");
}

public void processingInstruction(String target, String data)


...
Этот код просто генерирует сообщение, чтобы дать вам знать, что встретился игнорируемый
пробел.
Примечание: Опять же, не все анализаторы сделаны одинаково. Спецификация SAX не
требует, чтобы этот метод вызывался. Реализация Java XML делает это тогда, когда в
DTD указана такая возможность.

Web-

Rendered by www.RenderX.com
Влияние DTD на неверифицирующий анализатор Стр. 145 из 626

Если вы выполните приложение Echo сейчас, вы увидите примерно следующую


информацию:

ELEMENT: <slideshow
ATTR: ...
>
IGNORABLE
IGNORABLE
PROCESS: ...
IGNORABLE
IGNORABLE
ELEMENT: <slide
ATTR: ...
>
IGNORABLE
ELEMENT: <title>
CHARS: Wake up to ...
END_ELM: </title>
IGNORABLE
END_ELM: </slide>
IGNORABLE
IGNORABLE
ELEMENT: <slide
ATTR: ...
>
...
Отсюда очевидно, что ignorableWhitespace вызывается перед и после комментариев и
элементов slide тогда, когда вызывался метод characters при отсутствии DTD.

7.8.2. Очистка
Теперь, когда вы увидели отображение игнорируемых пробелов, удалите этот код из вашей
версии программы Echo - для следующих упражнений он вам больше не нужен.
Примечание: Это изменение сделано в файле Echo09.java.

7.8.3. Документы и данные


Раннее вы узнали, что одной из причин, по которой вы слышите то об XML-документах,
то об XML-данных, является то, что XML хорошо справляется с обоими, в зависимости от
того, разрешен или нет текст между элементами структуры.
В файле примера, с которым вы работаете, элемент slideshow является примером элемента
данных - он содержит только субэлементы без текста. Элемент item, с другой стороны,
может быть назван элементом документа, поскольку он может содержать и текст и
субэлементы.

Web-

Rendered by www.RenderX.com
Стр. 146 из 626 Simple API for XML

По мере работы с руководством вы увидите, как расширить определение элемента title


для включения HTML-разметки, что превратит его тоже в элемент документа.

7.8.4. Пустые элементы, пересмотренный вариант


Теперь, когда вы понимаете, как определенные экземпляры пробелов могут быть
проигнорированы, наступило время пересмотреть определение "пустого" элемента. Это
определение сейчас может быть расширено включением

<foo> </foo>
в котором существуют пробелы между тегами, а DTD определяет эти пробелы
игнорируемыми.

7.9. Определение атрибутов и сущностей в DTD


Определенный вами DTD пригоден для использования с неверифицирующим анализатором.
Он показывает, где ожидается текст, а где нет. Больше ни на что анализатор не обращает
внимания. Но для применения с верифицирующим анализатором DTD должен указать
правильные атрибуты для различных элементов. Вы сделаете это в данном разделе, после
чего определите одну внутреннюю сущность и одну внешнюю, к которым вы сможете
обратиться из XML-файла.

7.9.1. Определение атрибутов в DTD


Давайте определим атрибуты в программе презентации слайдов.
Примечание: Написанный в данном разделе XML содержится в файле slideshow1b.dtd.
(Версия для броузера - slideshow1b-dtd.html.)
Добавьте выделенный ниже текст, чтобы определить атрибуты для элемента slideshow:

<!ELEMENT slideshow (slide+)>


<!ATTLIST slideshow
title CDATA #REQUIRED
date CDATA #IMPLIED
author CDATA "unknown"
>
<!ELEMENT slide (title, item*)>
DTD-тег ATTLIST начинает последовательность определений атрибутов. Имя, следующее
после ATTLIST, указывает элемент, для которого определяются атрибуты. В данном случае
таким элементом является slideshow. (Обратите еще раз внимание на отсутствие иерархии
в спецификации DTD.)
Каждый атрибут определяется последовательностью из трех разделенных пробелами
значений. Запятые и другие разделители не разрешены, так что форматирование
определений, как показано выше, полезно для повышения читаемости. Первый элемент
в каждой строке - это имя атрибута: title, date или author в данном случае. Второй элемент
указывает тип данных: CDATA - это символьные данные, неанализируемые данные, в

Web-

Rendered by www.RenderX.com
Определение атрибутов и сущностей в DTD Стр. 147 из 626

которых левая угловая скобка (>) никогда не будет истолкована как часть XML-тега. В
таблице 6-3 перечислены правильные варианты для типов атрибутов.
Таблица 6-3 Типы атрибутов
Тип атрибута Указывает…
(value1 | value2 | … ) Список значений, разделенных вертикальными линиями.
(Пример находится ниже).
CDATA "Неанализируемые символьные данные". (Для нормальных
людей - текстовая строка.)
ID Имя, которое не имеет ни один другой атрибут ID.
IDREF Ссылка на ID, определенный где-то в документе.
IDREFS Разделенный пробелами список, содержащий один или более
ID-ссылок.
ENTITY Имя сущности, определенной в DTD.
ENTITIES Разделенный пробелами список сущностей.
NMTOKEN Правильное XML-имя, состоящее из букв, цифр, дефисов,
знаков подчеркивания и двоеточий.
NMTOKENS Разделенный пробелами список имен.
NOTATION Название DTD-определенной нотации, описывающей формат
не XML-данных, таких как файлы изображений.*

* Она является быстро отживающей спецификацией, которая будет рассмотрена подробно


в конце этого раздела.
Если тип атрибута состоит из заключенного в скобки списка вариантов, разделенных
вертикальными чертами, атрибут должен использовать одно из специфицированных
значений. Например, добавьте выделенный ниже текст в DTD:

<!ELEMENT slide (title, item*)>


<!ATTLIST slide
type (tech | exec | all) #IMPLIED
>
<!ELEMENT title (#PCDATA)>
<!ELEMENT item (#PCDATA | item)* >
Эта спецификация указывает, что атрибут type элемента slide должен быть записан как
tye="tech", type="exec" или type="all". Другие значения неприемлемы. (Использующие DTD
редакторы XML могут использовать такие спецификации для представления выпадающего
списка вариантов.)
В последней записи спецификации атрибута определяется значение атрибута по
умолчанию, если оно есть, и указывается, игнорируется либо нет атрибут. Таблица 6-4
показывает возможные варианты.
Таблица 6-4 Параметры спецификации атрибутов
Спецификация Указывает…
#REQUIRED Значение атрибута должно быть указано в документе.
#IMPLIED Значение не должно быть указано в документе. Если оно не
указано, приложение будет использовать значение по
умолчанию.

Web-

Rendered by www.RenderX.com
Стр. 148 из 626 Simple API for XML

Спецификация Указывает…
"defaultValue" Значение по умолчанию, если значение не указано в
документе.
#FIXED "fixedValue" Значение для использования. Если документ указывает любое
значение, оно должно быть таким же.

7.9.2. Определение сущностей в DTD


До настоящего времени мы рассматривали только предопределенные сущности, например
&amp;, и вы видели, что атрибут может ссылаться на сущность. Теперь наступило время
изучить, как определить свои собственные сущности.
Примечание: Определенный здесь XML находится в файле slideSample06.xml. Выводимая
информация - в файле Echo09-06.txt. (Версии для броузера - slideSample06-xml.html и
Echo09-06.html.)
Добавьте выделенный ниже текст в тег DOCTYPE вашего XML-файла.

<!DOCTYPE slideshow SYSTEM "slideshow.dtd" [


<!ENTITY product "WonderWidget">
<!ENTITY products "WonderWidgets">
]>
Имя тега ENTITY указывает, что вы определяете сущность. Далее идет имя сущности и
ее определение. В данном случае вы определяете сущность с именем "product", которая
будет замещать название продукта. В дальнейшем, когда название продукта изменится
(что определенно произойдет), вы должны будете лишь изменить название в одном месте,
и все ваши слайды будут отображать новое значение.
Последней частью является строка подстановки, которая замещает имя сущности везде,
где на нее встречается ссылка в XML-документе. Строка подстановки определяется в
кавычках, которые не включаются при вставке текста в документ.
Только лишь для удобства мы определили две версии: одну - для единственного числа,
другую - для множественного. Так что при использовании, например, в качестве названия
продукта "Wally" вы должны быть готовы ввести "Wallies" для множественного числа, и оно
будет подставлено корректно.
Примечание: По правде говоря, это тип сущности, который используется главным образом
во внешнем DTD. При этом все ваши документы могут обращаться к новому названию,
когда оно изменится. А это только пример…
Теперь, когда вы определили сущности, следующим шагом будет обращение к ним из
программы презентации слайдов. Выполните выделенные ниже изменения для этого:

<slideshow
title="WonderWidget&product; Slide Show"
...

<!-- TITLE SLIDE -->

Web-

Rendered by www.RenderX.com
Определение атрибутов и сущностей в DTD Стр. 149 из 626

<slide type="all">
<title>Wake up to WonderWidgets&products;!</title>
</slide>

<!-- OVERVIEW -->


<slide type="all">
<title>Overview</title>
<item>Why <em>WonderWidgets&products;</em> are
great</item>
<item/>
<item>Who <em>buys</em> WonderWidgets&products;</item>
</slide>
Обратите внимание, что на созданные вами сущности ссылаются при помощи такого же
синтаксиса (&entityName;), что и для предопределенных сущностей, и что на сущность
можно ссылаться в значении атрибута, так же как и в содержимом элемента.

7.9.3. Вывод ссылок на сущность


Если вы выполните программу Echo с новой версией файла, вот что вы увидите:

ELEMENT: <title>
CHARS: Wake up to WonderWidgets!
END_ELM: </title>
Обратите внимание, что название продукта было замещено ссылкой на сущность.

7.9.4. Дополнительные полезные сущности


Вот несколько других примеров определений сущностей, которые вы, возможно, найдете
полезными при написании XML-документа:

<!ENTITY ldquo "&#147;"> <!-- Left Double Quote -->


<!ENTITY rdquo "&#148;"> <!-- Right Double Quote -->
<!ENTITY trade "&#153;"> <!-- Trademark Symbol (TM) -->
<!ENTITY rtrade "&#174;"> <!-- Registered Trademark (R) -->
<!ENTITY copyr "&#169;"> <!-- Copyright Symbol -->

7.9.5. Ссылки на внешние сущности


Также можно использовать идентификаторы SYSTEM или PUBLIC для именования
сущности, определенной во внешнем файле. Сделаем это.
Примечание: Определенные здесь XML находятся в файлах slideSample07.xml и copy-
right.xml. Выводимая информация - в файле Echo09-07.txt. (Версии для броузера -
slideSample07-xml.html, copyright-xml.html и Echo09-07.html.)

Web-

Rendered by www.RenderX.com
Стр. 150 из 626 Simple API for XML

Добавьте выделенный ниже текст в предложение DOCTYPE вашего XML-файла для ссылки
на внешнюю сущность:

<!DOCTYPE slideshow SYSTEM "slideshow.dtd" [


<!ENTITY product "WonderWidget">
<!ENTITY products "WonderWidgets">
<!ENTITY copyright SYSTEM "copyright.xml">
]>
Это определение обращается к информации об авторских правах, содержащейся в файле
с именем copyright.xml. Создайте этот файл и запишите в него какой-то интересный текст,
возможно такой:

<!-- A SAMPLE copyright -->

This is the standard copyright message that our lawyers


make us put everywhere so we don'0t have to shell out a
million bucks every time someone spills hot coffee in their
lap...
И наконец, добавьте выделенный ниже текст в ваш файл slideSample.xml для ссылки на
внешнюю сущность:

<!-- TITLE SLIDE -->


...
</slide>

<!-- COPYRIGHT SLIDE -->


<slide type="all">
<item>&copyright;</item>
</slide>
Вы можете также объявить внешнюю сущность для получения доступа к сервлету, который
генерирует текущую дату, используя, например, такое определение:

<!ENTITY currentDate SYSTEM


"http://www.example.com/servlet/CurrentDate?fmt=dd-MMM-
yyyy">
Теперь вы можете обратиться к этой сущности, так же как и к любой другой:

Today's date is &currentDate;.

Web-

Rendered by www.RenderX.com
Обращение к двоичным сущностям Стр. 151 из 626

7.9.6. Отображение внешней сущности


После выполнения программы Echo с последней версией файла презентации слайдов вы
увидите следующую информацию:

...
END_ELM: </slide>
ELEMENT: <slide
ATTR: type "all"
>
ELEMENT: <item>
CHARS:
This is the standard copyright message that our lawyers
make us put everywhere so we don't have to shell out a
million bucks every time someone spills hot coffee in their
lap...
END_ELM: </item>
END_ELM: </slide>
...
Обратите внимание, что новая строка, за которой следует комментарий, отображается как
символ, но сам комментарий проигнорирован. По этой причине сообщение об авторских
правах начинается с новой строки после метки CHARS: вместо того, чтобы идти сразу
после метки - первый отображаемый символ является символом новой строки, после
которого следует комментарий.

7.9.7. Итоговая информация по сущностям


Внешняя или внутренняя сущность, на которую есть ссылка в содержимом документа,
называется сущностью общего назначения. Сущность, содержащая спецификацию DTD,
на которую есть обращение из DTD, называется сущностью-параметром. (Более подробно
об этом мы расскажем далее.)
Сущность, содержащая XML и являющаяся, таким образом, анализируемой, называется
анализируемой сущностью. Сущность, содержащая двоичные данные (например,
изображения), называется неанализируемой сущностью. (По своей природе она должна
быть внешней.) Мы рассмотрим ссылки на неанализируемые сущности в следующем
разделе руководства.

7.10. Обращение к двоичным сущностям


Этот раздел не содержит упражнений для программирования. В нем обсуждаются ссылки
на двоичные файлы, такие как изображения и файлы с мультимедийными данными.

7.10.1. Использование типа данных MIME


Существует два способа обратиться к неанализируемой сущности, например, к файлу
изображения. Первый использует механизм NOTATION спецификации DTD. Однако этот

Web-

Rendered by www.RenderX.com
Стр. 152 из 626 Simple API for XML

механизм является сложным, запутанным и существующим в основном для совместимости


с документами SGML. Мы будем иметь возможность рассмотреть его более детально при
обсуждении DTDHandler API, а сейчас достаточно сказать, что комбинация недавно
определенного стандарта пространства имен XML и типов данных MIME, определенных
для вложений электронных сообщений, обеспечивает намного более полезный, понятный
и расширяемый механизм для обращения к неанализируемым внешним сущностям.
Примечание: Описанный здесь XML находится в файле slideshow1b.xml. В действительности
мы не будем отображать никаких изображений. Это не входит в функции программы Echo.
В этом разделе просто рассмотрено, как такие ссылки можно сделать. Мы предполагаем,
что приложение, которое будет обрабатывать XML-данные, знает, как использовать эти
ссылки.
Добавьте выделенный ниже текст в ваш файл slideshow.dtd для настройки программы
slideshow на использование файлов изображений:

<!ELEMENT slide (image?, title, item*)>


<!ATTLIST slide
type (tech | exec | all) #IMPLIED
>
<!ELEMENT title (#PCDATA)>
<!ELEMENT item (#PCDATA | item)* >
<!ELEMENT image EMPTY>
<!ATTLIST image
alt CDATA #IMPLIED
src CDATA #REQUIRED
type CDATA "image/gif"
>
Эти изменения определяют image как необязательный элемент в slide, определяют его
как пустой элемент и определяют необходимые для него атрибуты. Тег image похож на
тег img HTML 4.0 с дополнением спецификатора типа изображения type. (Тег img определен
в спецификации HTML 4.0.)
Атрибуты тега image определяются в записи ATTLIST. Атрибут alt, определяющий
альтернативный текст для отображения при неудачном поиске изображения, принимает
символьные данные (CDATA). Он имеет "предполагаемое" значение, то есть является
необязательным, и программа, обрабатывающая данные, знает достаточно, чтобы
заместить его чем-то вроде "image not found" ("изображение не найдено"). С другой стороны,
атрибут src, который содержит имя изображения для вывода, является необходимым.
Атрибут type предназначен для спецификации типа данных MIME, как определено в
ftp://ftp.isi.edu/in-notes/iana/assignments/mediatypes/. Он имеет значение по умолчанию:
image/gif.
Примечание: Отсюда понятно, что символьные данные (CDATA), используемые для
атрибута type, должны быть одним из MIME-типов данных. Двумя наиболее общими