Академический Документы
Профессиональный Документы
Культура Документы
для WEB
Библиотека профессионала
WEB
PROGRAMMING
MARTY HALL
LARRY BROWN
Prentk» Hall PTR, Upper Saddle River, N J 07458 Sun Microsystems Press
www.phptr.com A Prentice Hall Title
ПРОГРАММИРОВАНИЕ
для WEB
Б и б л и о т е к а профессионала
МАРТИ ХОЛЛ
ЛЭРРИ БРАУН
ББК 32.973.26-018.2.75
Все названия программных продуктов являются зарегистрированными торговыми марками со
ответствующих фирм.
Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы
то ни было форме и какими бы то ни было средствами, будь то электронные или механические,
включая фотокопирование и запись на магнитный носитель, если на это нет письменного разреше
ния издательства Prentice Hall PTR.
Authoiized ti-anslation fiom the English language edition published by Prentice Hall PTR.
Copyiight © Sun Microsystem, Inc., 2001. All rights reseiTed. No pait of this book may be reproduced or
ti^ansmitted in any foiin or by any means, electionic or mechanical, including photocopying, recording or by any
infonnation storage retiieval system, without peiTnission from the Publisher.
Russian language edition published by Williams Publishing House according to the Agieement with
RM Enterprises International, Copyiight © 2002
Оглавление
Введение 25
Ч А С Т Ь III. П Р О Г Р А М М Ы , В Ы П О Л Н Я Ю Щ И Е С Я
Н А СТОРОНЕ СЕРВЕРА 779
Глава 18. HTML-формы 780
Глава 19. Java на стороне сервера: сервлеты 816
Глава 20. JavaServer Pages 900
Глава 21. Аплеты как интерфейс к программам на стороне сервера 990
Глава 22. JDBC 1016
Глава 23. Обработка XML-документов 1050
Ч А С Т Ь rv^, J A V A S C R I P T 1099
Глава 24. JavaScript: динамически изменяющиеся Web-страницы 1100
Глава 25. Краткое руководство по JavaScript 1172
Предметный указатель 1254
в Содержание
Содержание
Введение 25
Анимационные GIF-файлы 94
Элемент IMG 94
3.5. Карты изображений на стороне клиента 98
3.6. Включение объектов в документ 101
Встроенные аплеты 101
Встроенные аудио- и видеофрагменты, а также объекты
в других форматах 104
Управляющие элементы ActiveX 104
Бегущая строка 106
3.7. Управление переводом строк 108
Глава 4. Фреймы 110
4.1. Шаблон документа с фреймами 112
4.2. Разбиение окна броузера на фреймы 113
4.3. Определение содержимого фреймов 118
Примеры 120
4.4. Определение фрейма ддя отображения документа 122
Зарезервированные имена фреймов 124
4.5. Разрешение типичных проблем... 125
Создание закладок для фреймов 125
Вывод фреймов на печать 126
Одновременное обновление нескольких фреймов 126
Запрет вывода документа в составе фрейма 129
Создание пустого фрейма 130
4.6. Встроенные фреймы 130
Глава 5. Каскадные листы стилей 136
5.1. Правила стилей 138
5.2. Внешние и локальные листы стилей 140
Внешние листы стилей 140
Элемент STYLE и листы стилей JavaScript 142
Встроенные правила стилей 142
5.3. Селекторы 143
HTML-элементы 143
Классы, определяемые пользователем 144
Идентификаторы, определяемые пользователем 145
Псевдоклассы якоря 146
5.4. Предшествование правил 146
5.5. Свойства шрифтов 147
5.6. Свойства для определения фона и переднего плана 153
5.7. Текстовые свойства 156
5.8. Свойства блоков с обрамлением 159
Границы 160
Обрамление 160
Заполненная область 162
Типы отображения блока 163
5.9. Изображения и плавающие элементы 163
5.10. Свойства списков 165
8 Содержание
Ч А С Т Ь П . П Р О Г Р А М М И Р О В А Н И Е Н А Я З Ы К Е JAVA 177
Глава 6. О б щ и е с в е д е н и я о я з ы к е Java 178
6.1. Возможности Java 180
Средства сетевого взаимодействия и работа в Web 180
Кроссплатформенная поддержка Java 183
П р о с т о т а Java 186
Объектно-ориентированные средства Java 186
Стандартные библиотеки Java 187
6.2. Java: м и ф ы и реальность 188
Java предназначен исключительно для Web 189
Кроссплатформенная поддержка Java 189
Простота Java 190
Java — объектно-ориентированный язык (для тех,
кто придерживается соответствующего подхода) 191
Java — язык для разработки различных типов программ 191
6.3. Версии Java 192
Какой версии отдать предпочтение 193
О с н о в н ы е сведения о Java 194
6.4. Начинаем работу 194
Установка Java 195
Инсталляция броузера с поддержкой Java 196
Доступ к документации по Java API 196
Установка интегрированного пакета разработки
(необязательное действие) 197
Создание и запуск Java-программы 198
6.5. Несколько простых Java-программ 198
П р и л о ж е н и е Hello, World 199
П а р а м е т р ы командной строки 199
Аплет Hello, World 200
Параметры, передаваемые аплету 202
Глава 7. О б ъ е к т н о - о р и е н т и р о в а н н о е п р о г р а м м и р о в а н и е на Java 206
7.1. П е р е м е н н ы е экземпляра 207
7.2. Методы 210
7.3. Конструкторы и ссылка this 211
Статические инициализационные блоки 214
7.4. Деструкторы 214
7.5. Переопределение 215
7.6. Подготовка классов к повторному использованию 218
Содержание 9
7.7.Javadoc 223
Дескрипторы javadoc 224
Параметры командной строки javadoc 227
7.8. Наследование 230
7.9. Интерфейсы и абстрактные классы 233
7.10. Пакеты, CLASSPATH и JAR-архивы 242
Переменная окружения CLASSPATH 245
7.11. Модификаторы 247
Модификаторы области видимости 248
Прочие модификаторы 249
Глава 8. Синтаксис Java 252
8.1. Синтаксические правила 253
8.2. Простые типы 255
Преобразование простых типов 257
8.3. Операторы, условные операторы и циклы 258
Арифметические операторы 258
Условные операторы 259
Циклы 265
8.4. Класс Math 268
Константы 268
Методы общего назначения 268
- Тригонометрические методы 270
Biglnteger и BigDecimal 270
8.5. Ввод и вывод 271
Вывод в стандартный выходной поток 272
Вывод в стандартный поток ошибок 273
Чтение из стандартного входного потока 274
8.6. Выполнение программ, отличных от Java 274
8.7. Ссылки 280
Соглашения по передаче параметров 282
Оператор instanceof 283
8.8. Работа со строками 284
Методы класса String 285
Конструкторы 290
8.9. Массивы 291
Создание массива в два этапа 292
Создание массива в один этап 292
Многомерные массивы 294
8.10. Векторы 295
Конструкторы 295
Методы 295
8.11. Пример создания простого бинарного дерева 297
8.12. Исключения 302
Обработка исключения 302
Использование нескольких блоков catch 304
Выражение finally 305
10 Содержание
15.3.JTree 621
Простой объект J T r e e 621
Методы класса J T r e e 625
Обработка событий J T r e e 625
15.4.JTable 634
Простой способ создания JTable 634
Модели данных, используемые компонентом JTable 638
Визуализация ячеек таблицы 643
Обработка событий таблицы 645
15.5. Вывод на печать Swing-компонентов 649
Основы вывода на печать 649
Двойная буферизация и вывод на печать 651
Универсальная программа печати 652
Вывод на печать в JDK 1.3 656
15.6. Потоки Swing 658
Методы класса SwingUtilities 660
Глава 16. И с п о л ь з о в а н и е п о т о к о в 664
16.1. Запуск потоков 666
Выполнение действий в отдельном объекте Thread 666
Выполнение действий в классе, реализующем и н т е р ф е й с Runnable 668
16.2. Возникновение "гонок" 671
16.3. Синхронизация 673
Синхронизация фрагмента кода 673
Синхронизация метода 674
Ошибки, допускаемые п р и использовании синхронизации 675
16.4. Создание многопотоковых методов 677
16.5. Методы класса T h r e a d 681
Конструкторы 681
Константы 682
Методы 683
Остановка выполнения потока 688
16.6. Группы потоков 690
Конструкторы 690
Методы 690
16.7. Многопотоковая графика и двойная буферизация 692
Вывод графики в теле метода paint 693
Реализация динамической части изображения в виде отдельного
компонента 696
Рисование за пределами метода paint 696
Переопределение метода u p d a t e и использование метода
paint для инкрементного рисования 699
Использование двойной буферизации 703
16.8. Анимационные изображения 708
16.9. Таймеры 712
Конструктор 715
Методы класса Timer 716
16.10. Резюме 717
16 Содержание
Ч А С Т Ь III. П Р О Г Р А М М Ы , В Ы П О Л Н Я Ю Щ И Е С Я
Н А С Т О Р О Н Е СЕРВЕРА 779
Глава 18. H T M L - ф о р м ы 780
18.1. Передача данных с помощью HTML-форм 781
18.2. Элемент FORM 785
18.3. Управляющие элементы для обработки текста 790
Поля редактирования 790
Поле ввода пароля 792
Текстовые области 792
18.4. Кнопки 794
Кнопка Submit 795
Кнопка Reset 797
Содержание 17
Ч А С Т Ь rV^. J A V A S C R I P T 1099
Глава 24. JavaScript: д и н а м и ч е с к и и з м е н я ю щ и е с я Web-страницы 1100
24.1. Динамическая генерация HTML-документов 1103
Обеспечение совместимости с различными броузерами 1107
24.2. Обработка событий 1108
24.3. Синтаксис JavaScript 1109
Динамическая поддержка типов 1110
Объявление функций 1110
Объекты и классы 1111
Массивы 1116
24.4. Использование JavaScript при создании Web-страниц 1117
Определение размеров окна броузера 1117
Определение наличия дополнительных модулей 1120
24.5. Использование JavaScript для изменения... 1122
Динамическое изменение изображений 1122
Работа со слоями 1128
24.6. Использование JavaScript для проверки HTML-форм 1131
Индивидуальная обработка элементов ф о р м ы 1133
Проверка данных перед передачей на сервер 1135
24.8. Использование JavaScript для работы с фреймами 1144
Отображение во фрейхме ресурса с заданным URL 1144
Содержание 21
Свойства 1191
Методы 1192
Обработчики событий 1192
25.10. Объект H i d d e n 1192
Свойства 1193
Методы 1193
Обработчики событий 1193
25.11. Объект History 1193
Свойства 1193
Методы 1194
Обработчики событий 1194
25.12. Объект Image 1194
Конструктор 1194
Свойства 1195
Методы 1196
Обработчики событий 1196
25.13. Объект JavaObject 1196
25.14. Объект JavaPackage 1197
25.15. Объект Layer 1197
Конструкторы 1197
Свойства 1197
Методы 1199
Обработчики событий 1200
25.16. Объект Link 1200
Свойства 1201
Методы 1202
Обработчики событий 1202
25.17. Объект Location 1202
Свойства 1202
Методы 1203
Обработчики событий 1204
25.18. Объект Math 1204
Свойства 1204
Методы 1205
Обработчики событий 1206
25.19. Объект MimeType 1207
Свойства 1207
Методы 1207
Обработчики событий 1207
25.20. Объект Navigator 1208
Свойства 1208
Методы 1210
Обработчики событий 1210
25.21. Объект N u m b e r 1210
Конструкторы 1211
Свойства 1211
Методы 1211
Содержание 23
Свойства 1235
Методы 1236
Обработчики событий 1236
25.33. Объект Text 1237
Свойства 1237
Методы 1237
Обработчики событий 1238
25.34. Объект Textarea 1238
Свойства 1238
Методы 1239
Обработчики событий 1239
25.35. Объект Window 1240
Свойства 1240
Методы 1244
Обработчики событий 1249
П р е д м е т н ы й указатель 1254
Введение 25
ВВЕДЕНИЕ
В конце 1995 г. Марти Холл предложил новый курс для студентов, изучающих ком
пьютерные науки в университете Джонса Хопкинса. В нем он рассмотрел основные
вопросы, имеющие о т н о ш е н и е к поддержке Web, с точки зрения Java-технологии.
Предполагалось, что слушатели курса будут изучать HTML, Java, HTTP, CGI-
программирование и JavaScript и участвовать в выполнении простых учебных проек
тов. Вряд ли Марти представлял себе, какая судьба ожидает его курс. Появление пер
вой части курса летом 1996 г. совпало со всплеском популярности Java. Аудитория бь.
ла переполнена, а число желающих, записавшихся в очередь, намного превышало ко
личество мест в аудитории. Марти не успевал отвечать на т е л е ф о н н ы е звонки
студентов, пытавшихся доказать, что именно они непременно должны быть слушате
лями нового курса. От п р е д п р и я т и й приходили заявки на материалы курса. Успех был
абсолютный.
В дальнеР1шем, когда Марти занимался поисками материала для продолжения кур
са, он обнаружил, что, несмотря на обилие печатных изданий по каждому из рассмат
риваемых вопросов, для того, чтобы полностью охватить материал курса, понадобит
ся четыре или даже пять книг. В своей повседневной деятельности Марти постоянно
приходилось обращаться к огромному количеству собранных им публикаций. Напра
шивалось решение объединить основной материал, необходимый профессиональ
ным программистам, в одной книге.
Такова была предыстория первого издания книги Программирование для Web. Как и
следовало ожидать, она была очень популярна, но соответствующие технологии раз
вивалось чрезвычайно быстро. Вместо HTML 3.2 в броузерах была реализована под
держка HTML 4.0, была создана платформа Java 2, где появились средства, позволяю
щие повышать э ф ф е к т и в н о с т ь программ, и новые графические библиотеки. Это да
вало возможность создавать профессиональные коммерческие приложения. Раз
работка JSP 1.0 стимулировала интерес и к сервлетам, и к JSP, как альтернативе не
только традиционным CGI-программам, но также ASP и ASP и ColdFusion. Появился
язык XML. П о с т е п е н н о область применения Java переместилась с персональных ком
пьютеров на серверы.
По мере развития технологии стало ясно, что необходимо новое издание книги,
однако объем работы, требуемый для этого, был не по силам одному Марти. В про
цесс подготовки нового издания включился Л э р р и Браун, обладающий огромным
опытом разработки и преподавания в области Java-пограмм и Web-технологий. Его
знания по вопросам Java Foundation Classes и созданию многопотоковых программ,
26 Введение
Структура книги
Данная книга разделена на четыре части, посвященные HTML, программированию
на языке Java, написанию программ, выполняющихся на стороне сервера и JavaScript.
М е т о д и к а профессионалов
Web-узел
Материалы, имеющие отношение к данной книге, хранятся на Web-узле
http://www.corewebprogramming.com/
П о этому адресу вы найдете следующую информацию.
06 авторах
Марти Холл работает старшим научным сотрудником лаборатории прикладной фи
зики исследовательского центра при университете Джонса Хопкинса и ведет курсы по
распределенным вычислениям и Web-технологии. Иногда он также проводит курсы на
предприятиях по использованию сервлетов, JavaSen^er Pages, а также по другим темам,
связанным с Web-технологиями. Он автор книг Core Servlets and JavaServer Pages, a также
первого издания книги Программирование для Web. С Марти можно связаться по адресу
Благодарности
В подготовке книги к печати принимали участие очень многие. Без их помощи мы
вряд ли смогли бы выпустить даже первую часть. Д о н Олдридж, (Don Aldridge), Крис
Беннет (Chris B e n n e t t ) , Камил Белл ( С а т Ш е Bell), Пит Кларк (Pete Clark), Мария
Димеленте (Maria D i m a l a n t a ) , Нгуен-Хоа Дай ( N g u y e n - K h o a Duy), Дениз Еванс
(Denise E v a n s ) , Эми Карлсон (Amy K a r l s o n ) , Пол МакНеми (Paul M c N a m e e ) , Тодди
Норам (Toddi N o r u m ) , Уолтер Паскуинни (Walter P a s q u i n n i ) , Рич Слайвзек (Rich
Slywczak), Боб Т и н к е р (Bob Tinker) и Ким Топли (Kim Topley) указали нам на наши
ошибки и помогли советами. Без их участия данная книга вряд ли могла бы иметь ус
пех. Мэри Лоу Н о р (Магу Lou Nohr) затратила много времени на расстановку недос
тающих запятых и поис других ошибок. Благодаря ей текст книги стал таким, каким
вы его видите. Ванесса Мур ( V a n e s s a Moore) руководила подготовкой последней
версии. Ее работа осложнялась тем, чтоб н е к о т о р ы е изменения приходилось вносить
буквально в последний момент. Благодаря усилиям Ральфа Семмела ( R a l p h S e m m e l )
и Джулии Вессел ( J u l i e Wessel) был обеспечен гибкий график работы. Грег Д о н ч
(Greg D o e n c h ) из P r e n t i c e Hall всячески поощрял нашу работу над вторым издани
ем. Всем перечисленным выше мы выражаем искреннюю благодарность.
Я, Марти, в особенности благодарен B . J . , Линдси и Натану за их понимание и
поддержку. Я, Л э р р и , благодарю Ли за поддержку и т е р п е н и е в те долгие дни, кото
р ы е я проводил за компьютером.
Господь наградил нас обоих прекрасными семьями.
От издательства
Вы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим ва
ше мнение и хотим знать, что было сделано нами правильно, что можно было сделать
лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услышать и
любые другие замечания, которые вам хотелось бы высказать в наш адрес.
Мы ждем ваших комментариев и надеемся на них. Вы можете прислать электрон
ное письмо или просто посетить наш Web-сервер, оставив свои замечания, — одним
словом, любым удобным для вас способом дайте нам знать, нравится или нет вам эта
книга, а также выскажите свое мнение о том, как сделать наши книги более подходя
щими для вас.
Посылая письмо или сообщение, не забудьте указать название книги и ее авторов,
а также ваш e-mail. Мы внимательно ознакомимся с вашим мнением и обязательно уч
тем его при отборе и подготовке к изданию последующих книг. Наши координаты:
L-mail: i n f o @ w i l l i a i n s p u b l i s h i n g . com
WWW: h t t p : //www. w i l l i a m s p u b l i s h i n g . com
^:jzjs:-r±
ЯЗЫК HTML
Глава 1. Создание \/\/еЬ'Страниц с помощью HTML 4.0
Глава 2. Элементы блокового уровня HTML 4.0
Глава 3. Элементы текстового уровня HTML 4.0
Глава 4. Фреймы
Глава 5. Каскадные листы стилей
СОЗДАНИЕ
WEB-СТРАНИЦ
С ПОМОЩЬЮ
HTML 4.0
В ЭТОЙ главе...
еред вами первая из пяти глав, посвященных HTML (HyperText Markup Lan
ставленной на рис. 1.1. Если этот код непонятен вам, не беспокойтесь; элементы язы
ка HTML мы детально обсудим в последующих главах. Однако даже с первого взгляда
можно заметить некоторые особенности HTML-документа. Так, например, из данно
го листинга видно, что в нем содержится текст документа и набор дескрипторов, за
ключенных в угловые скобки. Некоторые (но не все) языковые элементы представ
ляют собой пары дескрипторов <ИМЯ> и </ИМЯ>.
На рис. 1.1 показано, как отображается Web-страница в окне конкретного броузера
(Internet Explorer 5.0), выполняющегося в операционной среде Windows 2000 Profes
sional. Основные установки для данного броузера (начертание, размер и цвет символов)
заданы пользователем. Характеристики отображения, не указанные пользователем, оп
ределяет сам броузер. Если Web-страница должна отображаться в броузерах различных
типов, попытки автора жестко задать внешний вид документа, как правило, заканчива
ются неудачей. В главе 5 вы познакомитесь с каскадными листами стилей, которые пре
доставляют авторам дополнительные возможности по управлению отображением Web-
страниц. Однако даже в этом случае автор не имеет полного контроля над внешним ви
дом своих документов.
d
Home Page for Lawrence M. Brown
Senior Network Engineer
Naval Surface Waifai-e Center
9500 MacArthor Boulevard
West Bethesda. Maryland. MD 20817-5700
email: lan7@corewebpro.eyttrmx^^ com
CAKOf KOcii^^oiYiSfON JNSI^f\/C^ Phone: (30 \) 277-4648
This IS my personal home page For more specific programmmg-related resoxirces pages, please see
'ёЗ
На з а м е т к у
H T M L 4.01
http://www.w3.org/TR/html401/
H T M L 4.0
h t t p : / / w w w . w 3 . o 3 r g / T R / 1 9 98/REC-html4 0 - 1 9 9 8 0 4 2 4 /
H T M L 3.2
http://www.w3.org/TR/REC-html32.html
Создание документа
Поскольку в HTML-файле содержится ASCII-текст, для создания HTML-документа
можно воспользоваться обычным текстовым редактором, н а п р и м е р Notepad,
UltraEdit, emacs или BBEdit. Также документ можно создать с помощью HTML-
редактора, например, HomeSite, FrontPage или Dreamweaver. Наконец, можно авто
матически преобразовать в HTML-формат документ, созданный в текстовом процес
соре, таком как Microsoft Word или WordPerfect. Поскольку H T M L — это не язык опи
сания страниц, а логический язык разметки, преобразованный документ может не
сколько отличаться от документа, созданного посредством текстового процессора, и
потребовать небольшой коррекции.
1.3. Порядок публикации документа в Web 39
Unix> cd
Unix> chmod a+x .
Unix> cd public_html
Unix> chmod a+x .
Unix> chmod a+r file
Поскольку Web-броузеры помимо HTML-документов позволяют также отображать
обычные текстовые ф а й л ы , для проверки доступа можно создать файл t e s t . t x t , со
держащий одну строку текста, например последовательность символов "Hello!". Этот
файл надо поместить в соответствующий подкаталог вашего рабочего каталога и по
пытаться обратиться к нему, задавая URL h t t p : / / y o u r . i s p . c o m / ' - y o u r -
a c c o u n t / t e s t . t x t . Если вы увидите в окне броузера содержимое данного файла, это
значит, что вам не надо предпринимать никаких действий по установке прав доступа.
Проверка документа
Разместив документ в Web, вам надо проверить, нет ли в нем синтаксических оши
бок. Полезно просмотреть Web-страниц)' в окне броузера, но этого недостаточно. Дело
в том, что, встретив некорректный HTML-документ, броузер пытается "угадать", как он
должен выглядеть на самом деле. Однако различные броузеры могут интерпретировать
такой документ по-рг1зному, и не исключено, что фрагменты Web-страницы, которая
выглядит нормально в одном броузере, отобразятся совсем по-другому или вовсе не бу
дут отображаться в другом. Так как HTML определяется посредством SGML (Standard
Generalized Markup Language— общий стандартный язык разметки), спецификация
SGML может быть использована для проверки соответствия документа синтаксису
HTML. Некоторые HTML-редакторы автоматически контролируют такое соответствие.
Кроме того, вы можете воспользоваться свободно распространяемыми программами
проверки. Самая популярная из них— W3C HTML Validator Service. Более подробная
информация расположена на следующих URL:
• http://validator.w3.org/
• http://www.htmlhelp.com/tools/validator/
• http://jigsaw.w3.org/css-validator/
М е т о д и к а профессионалов
pocument: Oortc
.,M .:^:..
Рис. 1.2. Шаблон HTML 4.0, отображаемый в окне
броузера Netscape 4.7, который выполняется в
среде Windows 2000 Professional
1.4. Структура НТМЬ-документа 43
<BODY>
<Hl>Main Heading</Hl>
<!-- Остальная часть Web-страницы -->
</BODY>
</HTML>
Декларация DOCTYPE
в зависимости от содержимого HTML-документа могут использоваться т р и вари
анта декларации DOCTYPE.
Строгая д е к л а р а ц и я H T M L 4.01 D O C T Y P E
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
П р о м е ж у т о ч н а я д е к л а р а ц и я H T M L 4.01 D O C T Y P E
Д е к л а р а ц и я H T M L 4.01 D O C T Y P E д л я р а б о т ы с ф р е й м а м и
Э л е м е н т ы H T M L 4.01
http://www.w3.org/TR/html4/index/elements.html
Атрибуты H T M L 4.01
http://www.w3.org/TR/html4/index/attributes.html
LANG
Атрибут LANG представляет в закодированном виде язык, на котором создан доку
мент. Современные броузеры интерпретир)тот атрибут LANG как источник дополни
тельной информации, не влияющей на порядок представления документа. Однако
сведениями, содержащимися в атрибуте LANG, могут воспользоваться поисковые
серверы и средства проверки орфографии. Список кодовых названий языков вы
найдете в документе RFC 1766. Чтобы скопировать RFC, можно обратиться к одном}^
из архивов, описанных в документе h t t p : //www. r f c - e d i t o r . o r g / .
DIR
Атрибут DIR определяет направление следования текста: LTR (left-to-right— слева
направо) или RTL (right-to-left— справа налево). Internet Explorer поддерживает
атриб)^ DIR, но в зависимости от кодировки направление ASCII-символов может
изменяться. Поскольку данный атрибут не поддерживается Netscape (в частности,
Netscape 4.7 и более ранними версиями), его следует использовать только в сетях
intranet, о р и е н т и р о в а н н ы х исключительно на Internet Explorer.
Внимание!
VERSION
Атрибут VERSION задает версию HTML для документа. Такая и н ф о р м а ц и я избы
точна и данный атрибут применяется редко. Версию H T M L броузер может опре-
1.5. Элемент HEAD — высокоуровневая информация... 45
<HEAD>
<TITLE>Why You Should Buy Windows 2000</TITLE>
<BASE HREF="http://www.microsoft.com/windows2000/">
<META NAME="author" CONTENT="Bill Gates">
<META NAME="keywords"
CONTENT="Windows,Advocacy,OS,Operating Systems">
<META NAME="description"
CONTENT="A summary of the advantages of Windows 2000.">
</HEAD>
<HEAD>
<TITLE>Why You Should Buy Windows 2000</TITLE>
<META HTTP-EQUIV="Refresh" CONTENT="1800">
</HEAD>
<HEAD>
<TITLE>Why You Should Buy Windows 2000 (New Address)</TITLE>
<META HTTP-EQUIV="Refresh"
C0NTENT="5;
URL=http://www.apple.com/Buy-Win2000.html">
</HEAD>
48 Глава 1 . Создание Web-страниц с помощью HTML 4.0
<МЕТА HTTP-EQUIV="Content-type"
CONTENT="text/html; CHARSET=GB2312">
Стандарты ISO определяют отображение символов для многих языков. Практиче
ски все наборы включают стандартные ASCII-символы, поэтому в составе документа,
составленного на любом языке, можно расположить английский текст. Если документ
содержит текст на нескольких языках, его надо представить с помощью символов в
16-битовом ф о р м а т е Unicode. В настоящее время широко распространен вариант
Unicode UTF-8, где каждый 16-битовый символ Unicode преобразуется в байтовую по
следовательность, причем ASCII-символ занимает лишь 8 бит. Дополнительную ин
ф о р м а ц и ю о применении Unicode для представления документов на нескольких язы
ках можно найти по адресу h t t p : //wwv/. U n i c o d e . o r g / .
С помощью HTTP-EQUIV можно управлять содержимым заголовка HTTP-ответа,
значение заголовка задается с помощью CONTENT. HTTP-EQUIV представляет собой
простое расширение (поддерживаемое как Netscape, так и Internet Explorer), которое
"устанавливает" заголовок, не прибегая к его генерации. Подробная и н ф о р м а ц и я о
HTTP-заголовках приведена в главе 19.
Атрибут SCHEME задает формат значения свойства, представленного с помощью
пары NAME-CONTENT дескриптора МЕТА. Здесь также NAME определяет имя свойства, а
CONTENT — его значение. В приведенном ниже примере атрибут SCHEME указывает,
что дата задана в формате месяц-день-год (SCHEME="Month-Day-Year"), в отличие
от европейского формата день-месяц-год.
<МЕТА SCHEME="Month-Day-Year"
NAME="Date"
VALUE="05-01-2000">
Атрибуты LANG и DIR элемента МЕТА игнорируются.
SRC
Атрибут SRC задает URL звукового файла, который должен быть представлен в
формате . wav, . a u или MIDI.
LOOP
Атрибут LOOP определяет, сколько раз должен быть воспроизведен звуковой файл.
По умолчанию принимается значение 1. Значение, равное - 1 , или INFINITE, приве
дет к тому, что воспроизведение файла будет повторяться непрерывно до тех пор,
пока пользователь не перейдет к другой странице или не завершит сеанс работы с
броузером.
BACKGROUND и BGCOLOR
Атрибут BACKGROUND задает URL графического файла. Изображение, содержа
щееся в этом файле, отображается в качестве ф о н а для Web-документа. Если раз
меры изображения меньше размера окна, оно многократно повторяется. Возмож
ность многократного воспроизведения изображения позволяет снизить время за
грузки фона. Так, например, если в качестве ф о н а используются оттенки цвета,
плавно изменяющиеся от левой границы окна до его правой границы, то в качест
ве фонового должно использоваться изображение большой ширины, но размер
его по высоте может быть равен одному пикселю. Помимо BACKGROUND, рекомен
дуется также задавать атрибут BGCOLOR, определяющий цвет фона. Использование
BGCOLOR— это своеобразная "страховка" на случай, если клиент-программа по ка
ким-то причинам не сможет скопировать ф о н о в о е изображение.
В большинстве броузеров по умолчанию используется белый (WHITE, или #FFFFFF)
либо светло-серый (SILVER, или #СОСОСО) фон. Несмотря на то что BACKGROUND и
BGCOLOR широко используются, и тот и другой атрибут не рекомендованы для при
менения. Фоновое изображение и цвет фона желательно задавать с помощью листов
стилей.
52 Глава 1 . Создание Web-страниц с помощью HTML 4.0
TITLE
Атрибут TITLE позволяет организовать отображение подсказки в случае, если кур
сор мыши приостанавливает свое движение в пределах документа. Д а н н ы й атри
бут поддерживается Internet Explorer 4.0 и более новыми версиями. Netscape (по
крайней мере версия 4.7 и более старые) не поддерживает TITLE.
1.6. BODY — основная часть документа 53
ONCLICK, ONDBLCLICK, O N M O U S E D O W N , O N M O U S E U P ,
O N M O U S E M O V E , O N M O U S E O U T , ONKEYPRESS, ONKEY-DOWN,
ONLOAD, ONUNLOAD, ONFOCUS, ONBLUR, ONERROR, ONMOVE,
ONRESIZE, O N D R A G D R O P
Данные атрибуты определяют код JavaScript, который должен быть выполнен при
возникновении события, связанного с клавиатурой, мышью или изменением фокуса.
BGPROPERTIES
Данный атрибут поддерживается Internet Explorer. Если задано выражение
BGPROPERTIES = "FIXED", это означает, что ф о н о в о е изображение не должно
прокручиваться при просмотре страницы. Это свойство иногда называют
"водяными знаками" (watermark).
И наконец, при использовании каскадных листов стилей со всеми HTML-эле
ментами могут использоваться атрибуты CLASS, ID и STYLE. Исключением являются
элементы BASE, BASEFONT (атрибут ID допустим), HEAD, HTML, МЕТА, PARAM (атрибут
ID допустим), SCRIPT, STYLE и TITLE. П р и рассмотрении конкретных HTML-эле
ментов атрибуты, связанные с листами стилей, обсуждаться не будут. И н ф о р м а ц и ю об
этих атрибутах вы найдете в главе 5, посвященной каскадным листам стилей.
1.7. Резюме
Язык HTML— это основное средство для создания профессиональных Web-
страниц. Независимо от того, предназначена Web-страница для технической под
держки некоторого продукта, отображения и н ф о р м а ц и и о котировке акций либо для
электронной коммерции, информация, содержащаяся в ней, представляет собой
HTML-документ. В данной главе описана общая структура HTML-дoк)^vIeнтa и рас
смотрен процесс создания, проверки и размещения Web-страницы в Internet.
В каждом документе, соответствук:)щем спецификации HTML 4.0, содержится декла
рация DOCTYPE, за которой следует элемент HTML, содержащий разделы HEAD и BODY. В
разделе HEAD всегда находится элемент TITLE, кроме того, HEAD может содержать
STYLE, МЕТА и др)^тие элементы, предоставляющие информацию об авторе, обеспечи
вающие перенаправление либо содержащие описание документа. Информация, нахо
дящаяся в элементе МЕТА, часто используется поисковыми серверами, которые поме
щают сведения о документе в свои базы данных. Как правило, дескриптор <BODY> зада
ется без атрибутов, однако при необходимости в него могут быть включены атрибуты,
которые задают фоновый цвет или фоновое изображение, а также JavaScript-команды,
которые должны быть выполнены при наступлении определенных событий.
В последующих главах будут рассмотрены вопросы оформления данных в составе
Web-страницы. В главе 2 обсуждаются основные т и п ы текстовых блоков, а в главе 3 —
элементы, которые мог)^' быть включены практически в любой блок. Глава 4 посвя
щена созданию документов с использованием ф р е й м о в . Автор Web-страницы может
разбить ее на "ячейки" и разместить в каждой ячейке отдельный документ. Пользова
тели, которые хотят задать особенности отображения различных элементов в окне
броузера, могут воспользоваться каскадными листами стилей, описанными в главе 5.
ЭЛЕМЕНТЫ
БЛОКОВОГО
УРОВНЯ HTML 4.0
В ЭТОЙ главе...
• Заголовки разделов.
• Основные типы абзацев.
• Маркированные и нумерованные списки.
• Таблицы.
• Горизонтальные разделительные линии.
• Типы выравнивания абзацев.
Й-1У\^^^
2 . 1 . Заголовки
Элементы: <Н1 .. .> . . </Н1>
<Н2 .. .> . . </Н2>
<НЗ .. .> . . </НЗ>
<Н4 .. .> . . </Н4>
<Н5 . . .> . . </Н5>
<Нб . . .> . . </Нб>
Атрибут: ALIGN
Элементы Н1-Н6 предназначены для определения заголовков различных уровней
в составе документа. HI задает заголовок первого, или верхнего, уровня, Н2 — заголо
вок второго уровня, НЗ — третьего уровня и т. д. Как правило, раздел BODY начинается
с заголовка первого уровня, содержащего тот же текст, что и элемент TITLE, находя
щийся в разделе HEAD. В остальной части документа заголовки второго уровня (Н2)
используются для определения заголовков разделов, НЗ — для подразделов и т. д.
В большинстве броузеров заголовки отобрг1жаются полужирным шрифтом: HI —
наибольшего размера, а Нб— наименьшего. П р и использовании заголовков низших
уровней следует соблюдать осторожность, поскольку не исключена ситуация, при ко
торой такой заголовок будет представлен ш р и ф т о м меньшего размера, чем обычный
текст абзаца. Текст, следующий за заголовком, оформляется как новый абзац. В отли
чие от многих элементов, заголовок не содержит элементов блокового уровня и не
входит в состав других элементов, за исключением таблиц (TABLE) и ф о р м ввода
(FORM). В составе заголовка могут находиться элементы текстового уровня. Два заго
ловка, показанные в листинге 2.1, созданы правильно, поскольку элементы текстово
го уровня полностью содержатся внутри соответствующего заголовка. Один из них
задает отображение курсивом, а другой формирует гипертекстовую ссылку.
<1><Н2>Ап I t a l i c Heading</H2></I>
<А NAME="Section5"><H2>Section Five</H2></A>
ALIGN
По умолчанию к заголовкам применяется выравнивание по левому краю, однако при
необходимости они могут быть расположены по центру либо выровнены по правому
краю документа. Тип выравнивания задается с помощью атрибута ALIGN, допусти
мыми значениями которого являются LEFT, RIGHT, CENTER и JUSTIFY. Если задано
значение JUSTIFY, то заголовки, длина которых превышает ширину окна броузера,
располагаются так, что их левая и правая границы совпадают с границами окна. Тип
выравнивания по умолчанию может быть изменен посредством дескриптора DIV,
который будет рассмотрен далее в этой главе. В спецификации HTML 4.0 не реко
мендуется использовать атрибут ALIGN при создании заголовков. Необходимое вы
равнивание желательно выполнять с помощью каскадных листов стилей.
П р и м е р ы заголовков различных уровней приведены в листинге 2.3. Заголовок
третьего уровня отобрг1жается с подчеркиванием. На рис. 2.1 показан внешний вид
этого документа в окне броузера Internet Explorer 5.0, выполняющегося в среде
Windows 2000 Professional.
^ч^l•нlNl^^•l-f^'^У4•l'llн^•'гl^'l^llll1u'•^n'^f'l——
^m\
:^ - -^r Jj}^ 'й^ ^ -y^-yj •
L c v d - 4 (H4)
Level-5(H5)
'
Level-6(H6)
J
1
^gjDorte 1^ My CoriipUtM
<H6>Level-6 (Нб)</Н6>
</BODY>
</HTML>
Основной абзац
Элемент: <Р . . . > . . . </Р>(закрь1ваю1ций дескриптор может отсутствовать)
Атрибут: ALIGN
Элемент Р определяет основной абзац — фрагмент текста, при отображении кото
рого броузер оставляет пустое пространство небольшого размера выше и ниже абза
ца. Несмотря на то что Р представляет собой контейнер, закрывающий дескриптор
указывать не обязательно. Если дескриптор < / Р > пропуш^ен, окончание абзаца опре
деляется по началу нового элемента блокового уровня. Если текст расположен за пре
делами всех элементов блокового уровня, считается, что он содержится в элементе Р.
Учитывая эти особенности, многие авторы используют Р как разделитель, хотя на са
мом деле он является контейнером. В листинге 2.4 показаны два варианта использо
вания дескриптора основного абзаца. В первом варианте (а) окончание абзаца указы
вается явно, а во втором варианте (б) закрывающий дескриптор пропущен.
Л и ш н и е пробелы в составе основного абзаца игнорируются, а текст располагается
в соответствии с размерами окна. Несколько последовательно расположенных деск
р и п т о р о в <Р> не приводят к увеличению пустого пространства над абзацем. Каскад
ные листы стилей (см, главу 5) позволяют непосредственно задавать верхнюю и ниж
нюю границы абзаца. Если при создании документа листы стилей не используются,
для включения пустых строк можно использовать элемент BR, который будет обсуж
даться в главе 3, либо элемент PRE, рассматриваемый далее в этой главе.
(а)
<BODY>
<Р>
Paragraph
</Р>
<Р>
Paragraph
</Р>
2 . 2 . Основные э л е м е н т ы . . . 59
<р>
Paragraph 3
</Р>
</BODY>
(б)
<BODY>
Paragraph 1
<Р>
Paragraph 2
<Р>
Paragraph 3
</BODY>
Внимание!
ALIGN
Атрибут ALIGN элемента Р применяется так же, как и соответствующий атрибут
заголовков. Подобно заголовкам, основной абзац по умолчанию выравнивается по
левой границе, но посредством атрибута ALIGN можно задать выравнивание по
центру либо по правой границе. Допустимыми значениями атрибута ALIGN явля
ются LEFT, RIGHT, CENTER и JUSTIFY. Если задано значение JUSTIFY, то содер
жимое абзаца, состоящего из нескольких строк, распределяется по всей ширине
окна броузера. Тип выравнивания по умолчанию можно изменить с помощью де
скриптора DIV (см. раздел 2.6) или каскадных листов стилей (см. главу 5). Как и для
заголовков, атрибут ALIGN не рекомендован для применения. Это сделано для то
го, чтобы стимулировать использование листов стилей.
Для представления любого из символов набора ISO 8859-1 (Latin-1) может использо
ваться последовательность "&#л;л:л^', где ххх— это десятичное представление символа в на
боре ISO Latin-1. Так, например, если в документе встретится последовательность б9,
на экране будет отображаться символ ©. Кроме того, для многих символов применяются
мнемонические обозначения, например символ © может быть задан как " &сору;". Полный
перечень символов Latin-1 и их мнемонических обозначений находится по адресу
h t t p : / / w w w . h t m l h e l p . c o m / r e f e r e n c e / h t m l 4 0 / e n t i t i e s / l a t i n l .html.
В табл. 2.1 перечислены некоторые обозначения, поддерживаемые всеми броузе
рами H T M L 4.0. Эти обозначения могут быть использованы в составе элемента TITLE
и при ф о р м и р о в а н и и надписи на кнопке SUBMIT, где элементы разметки запрещены.
WIDTH
Атрибут WIDTH в настоящее время не рекомендован для применения. С его помо
щью задается ширина текста в символах, что позволяет броузеру выбрать необхо
димый ш р и ф т и величину отступа.
Цитирование с отступом
Элемент: <BLOCKQUOTE> ... </BLOCKQUOTE>
Атрибут: CITE
Элемент BLOCKQUOTE представляет большой фрагмент цитируемого текста и ото
бражает его с отступом. Большинство броузеров формируют отступ как от левой, так и
от правой границы окна. Однако такие отступы не считаются обязательными, поэтому
авторы часто избегают включать BLOCKQUOTE в свои документы и применяют этот эле
мент в основном в сетях intranet, где известно, в каких броузерах будут отображаться
Web-страницы. Вместо BLOCKQUOTE можно использовать соответствующие возможно
сти листов стилей, а также таблиц)^ без обрамления. Атрибут CITE, не обрабатываемый
броузером, позволяет указывать URL документа, текст которого цитируется.
Методика профессионалов
Адрес
Элемент: <ADDRESS>... </ADDRESS>
Атрибуты: отсутствуют
Элемент ADDRESS позволяет включать в документ и н ф о р м а ц и ю об авторе. О б ы ч н о
эти данные отображаются в верхней или в н и ж н е й части документа; многие броузеры
выводят их курсивом. Как и в других блоковых элементах (за исключением PRE), бро
узер располагает текст по ширине окна. Ч т о б ы явным образом включить в текст раз
рыв строки, надо использовать элемент BR.
Нумерованные списки
Элемент: <OL ...>... </OL>
Атрибуты: TYPE, START, COMPACT
С помощью элемента 0L создаются нумерованные списки. Элемент LI (list item—
пункт списка) отмечает отдельные пункты нумерованного списка, которые могут со
держать элементы блокового уровня (например, таблицы и другие списки), за исклю
чением заголовков (HI — Нб) и элементов ADDRESS. П р и м е р простого нумерованного
списка приведен в листинге 2.5. На рис. 2.2 показано, как этот код отображается в
броузере Netscape 4.0, который выполняется на рабочей станции Sun/Solaris.
Листинг 2 . 5 . П р о с т о й н у м е р о в а н н ы й с п и с о к
А sample l i s t :
<0L>
< L I > L i s t I t e m One
< L I > L i s t I t e m Two
<LI>List Item Three
</0L>
A sample list:
TYPE
Атрибут TYPE определяет стиль нумерованного списка (тип нумерации). Допусти
мые значения данного атрибута приведены в табл. 2.2. Официально атрибут TYPE не
рекомендован для использования, однако многие авторы находят его очень удобным
и продолжают применять.
START
Атриб)т START также не рекомендован для применения. Его значением является
целое число, определяющее начало нумерации. Данный атрибут может быть ис
пользован с любым типом нумерации. В элементе 0L не предусмотрена возмож
ность непосредственно задавать префикс, отображаемый в начале каждого пункта.
COMPACT
Атрибут COMPACT указывает на то, что спи I. Headings
сок должен отображаться компактно (т.е. не II. Basic Text Sections
занимать лишнее пространство). Этот атри m Lists
бут не рекомендован для применения и ис A. Ordered
пользуется крайне редко. 1. The OL tag
a TYPE
В листинге 2.6 представлен более сложный b, START
нумерованный список. На рис. 2.3 показано, с COMPACT.
как этот список выглядит в окне броузера. За 2. The LI tag
метьте, что вложенные списки отображаются с B. Unordered
отступом и их нумерация начинается с 1, неза 1. The UL tag
висимо от нумерации включающего списка. 2. The LI tag
С Definition
1. The DL tag
2. The DT tag
Рис. 2.3. Вложенные списки 3. The DD tag
отображаются с отступом IV. Miscellaneous
2.3. Нумерованные, маркированные списки... 63
<0L TYPE="I">
<LI>Headings
<LI>Basic Text Sections
<LI>Lists
<0L TYPE="A">
<LI>Ordered
<0L TYPE="1">
<LI>The OL tag
<0L TYPE="a">
<LI>TYPE
<LI>START
<LI>COMPACT
</0L>
<LI>The LI tag
</0L>
<LI>Unordered
<0L TYPE="1">
<LI>The UL tag
<LI>The LI tag
</0L>
<LI>Definition
<0L TYPE="1">
<LI>The DL tag
<LI>The DT tag
<LI>The DD tag
</0L>
</0L>
<LI>Miscellaneous
</0L>
VALUE
Чтобы стимулировать применение листов стилей, атрибут VALUE не рекомендован
для использования. Этот атрибут определяет номер, которым помечается пункт
списка, и влияет не только на текущий, но и на все последующие пункты.
TYPE
В составе открывающего дескриптора <LI> может также указываться атрибут
ТУРЕ, который позволяет изменять тип нумерации в пределах списка. Необходи
мость в применении этого атрибута возникает крайне редко.
64 Глава 2. Элементы блокового уровня HTML 4.0
Маркированные списки
Элемент: <UL ...>.., < / U L >
Атрибуты: TYPE, COMPACT
Элемент UL создает маркированный список. Пункты списка формируются с помо
щью дескриптора < Ы > . П р и м е р простого маркированного списка приведен в лис
тинге 2.4. На рис. 2.7 показано, как этот список отображается в окне броузера
Netscape 4.0, выполняющегося на рабочей станции Sun/Solaris.
А sample l i s t :
<UL>
< L I > L i s t I t e m One
< L I > L i s t I t e m Two
<LI>List Item Three
</UL>
A sample list:
TYPE
Атрибут TYPE задает т и п маркера. Допустимые значения TYPE приведены в
табл. 2.3. Ч т о б ы стимулировать использование листов стилей, данный атрибут не
рекомендован для применения.
Значение Описание
DISC З а к р а ш е н н ы й круг. Часто используется по умолчанию для списков,
не являющихся вложенными
CIRCLE Незакрашенный круг. Обычно используется по умолчанию для вло
ж е н н ы х списков
SQUARE Квадрат. В зависимости от броузера, он может быть закрашен либо
не закрашен
2.3. Нумерованные, маркированные списки... 65
COMPACT
Как и TYPE, атрибут COMPACT не рекомендован для использования. Этот атрибут
указывает на то, что список должен отображаться компактно, и применяется дос
т а т о ч н о редко.
TYPE
Атрибут TYPE (не рекомендован для применения) задает тип маркера для кон
кретного пункта списка. Для атрибута TYPE допустимы те же значения, что и для
соответствующего атрибута дескриптора UL (т.е. DISC, CIRCLE и SQUARE).
Списки определений
Э л е м е н т : <DL . . .> ... </DL>
Атрибут: COMPACT
<DL>
<DT>Term One
<DD>The definition of term number one.
<DT>Term Two
<DD>The definition of term number two.
</DL>
Term One
The definition of term
number one.
Term Two
The aenniuon of term p^iQ^ 2.5. в списке определений элементы DD обычно
number two. отображаются с отступом
2.4. Таблицы
HTML-таблицы используются не только традиционным способом (т.е. для пред
ставления данных в виде двухмерной таблицы), они также применяются для управле
ния расположением и группировки элементов. В состав таблиц могут входить изо
бражения, фрагменты текста, включая списки, и даже другие таблицы. Автор Web-
страницы имеет возможность запретить отображение обрамления вокруг таблицы и
разграничительных л и н и й между ячейками, в результате содержимое таблицы выгля
дит как выровненные фрагменты данных. Создание сложных таблиц вручную — дли
тельная и р)а^инная работа, при выполнении которой легко допустить ошибку. Боль
шую помощь при создании Web-страниц оказывают HTML-редакторы, предостав
ляющие визуальные средства для ф о р м и р о в а н и я и заполнения таблиц. Особенно
полезны такие редакторы, которые позволяют редактировать исходный HTML-код и
включать в него атрибуты, не предусмотренные в графическом и н т е р ф е й с е
(например, атрибут BGCOLOR).
Структура таблицы
HTML-таблица создается с помощью элемента TABLE, который содержит необяза
тельный элемент CAPTION и описания строк, с ф о р м и р о в а н н ы е с помощью элементов
TR. В состав каждой строки таблицы могут входить элементы ТН (table heading — заго
ловок таблицы) и элементы TD (table data— данные таблицы). В составе элемента ТН
2.4. Таблицы 67
<TABLE B0RDER=1>
<CAPTION>Table Caption</CAPTION>
<TR><TH>Headingl</TH> <TH>Heading2</TH></TR>
<TR><TD>Rowl C o l l Data</TD><TD>Rowl Col2 Data</TD></TR>
<TR><TD>Row2 C o l l Data</TD><TD>Row2 Col2 Data</TD></TR>
<TR><TD>Row3 C o l l Data</TD><TD>Row3 Col2 Data</TD></TR>
</TABLE>
ALIGN
Атриб)т ALIGN (чтобы стимулировать использование листов стилей, он не реко
мендован для применения) определяет тип выравнивания всей таблицы по гори
зонтали. Допустимыми значениями являются LEFT, RIGHT и CENTER, значение
LEFT принимается по умолчанию. Заметьте, что текст, непосредственно следую
щий в документе за таблицей, в ы р о в н е н н о й вправо, будет отображаться слева от
нее. Чтобы текст выводился под таблицей, надо использовать выражение <BR
CLEAR="ALL">. Подробно элемент BR будет рассматриваться в главе 3.
68 Глава 2 . Э л е м е н т ы блокового уровня H T M L 4 . 0
BORDER
В основном атрибут BORDER предназначен для управления шириной обрамления,
отображаемого вокруг таблицы. Н о если данный атрибут будет установлен равным
нулю (значение по умолчанию), разделительные линии между ячейками таблицы
также не будут выводиться. Размеры, указанные с помощью атрибута BORDER, до
бавляются к размерам пустого пространства вокруг каждой ячейки (атрибут
CELLSPACING). Н е к о т о р ы е броузеры интерпретируют выражение <TABLE
BORDER> как <TABLE B0RDER=1>. Подобные выражения не следует использовать в
составе Web-страниц, поскольку они мешают проверять документы с помощью
специализированных программ.
На з а м е т к у
CELLSPACING
Атрибут CELLSPACING определяет расстояние в пикселях между соседними ячейка
ми таблицы. Если значение атрибута BORDER не равно нулю, разделительная линия
между ячейками отображается с имитацией трехмерного изображения, в противном
случае пустое пространство между ячейками закрашивается цветом фона. П о умол
чанию устанавливается расстояние между ячейками, равное трем пикселям.
CELLPADDING
Атрибут CELLSPACING определяет расстояние в пикселях между границей ячейки
и данными, отображаемыми в ней. П о умолчанию значение данного атрибута ус
танавливается равным одному пикселю.
FRAME
Атрибут FRAME введен в HTML 4.0 и определяет, какая часть внешнего обрамле
ния должна отображаться в окне броузера. Если данный атрибут не указан, все че
т ы р е части обрамления выводятся на экран. Допустимыми значениями FRAME яв
ляются BORDER, или BOX (отображаются все части обрамления), VOID (обрамление
не отображается), ABOVE (отображается верхняя л и н и я ) , BELOW (отображается
нижняя л и н и я ) , HSIDES (отображаются верхняя и нижняя линии, хотя по имени
атрибута можно предположить другое действие), VSIDES (отображаются левая и
правая л и н и и ) , LHS (отображается левая линия) и RHS (отображается правая ли
ния). П р о с т о й п р и м е р использования атрибута FRAME приведен в листинге 2.10.
На рис. 2.7 показано, как этот пример выглядит на экране броузера. Атрибут
FRAME не поддерживается Netscape, по крайней мере он не поддерживался в
Netscape 4.7 и более ранних версиях данного броузера.
2 . 4 . Таблицы 69
Листинг 2.10. T i c T a c T o e . h t m l
¥т^тштт*мт&жМШ1Шшшшт
||;1в||Ш1|Я||||Ж
|1иш11вай1Й11в& ^ '^7
2000 World Championship
Ш Щ
1 Final result in the 2000 world tic-tac-toe championsh^. Deep Green i5"X". '
1 Barry Kasparov is "0".
1 X jO X
X |0 X
OJX(0
ш^¥шт^^-^ш1шшшшшшшщшшш
Рис. 2.7. Таблица с отключенным внешним обрамлением
Внимание!
RULES
Новый атрибут H T M L 4.0, поддерживаемый Internet Explorer, но не поддержи
ваемый Netscape, определяет, какие из внутренних разделительных л и н и й табли
цы должны быть отображены на экране. Допустимыми значениями атрибута
RULES являются NONE, ROWS, COLS, ALL и GROUPS.
Внимание!
SUMARY
Атрибут SUMARY, введенный в HTML 4.0, предоставляет описание таблицы для
программ, воспроизводящих HTML-документы, в специальных средах, например с
помощью звука или в брайлевском представлении.
WIDTH
Атрибут WIDTH задает ширину таблицы в пикселях (<TABLE WIDTH=250>) либо в
процентах от ш и р и н ы окна броузера (<TABLE WIDTH="75%">). П р и использова
нии абсолютных размеров соблюдайте осторожность, так как вы не можете пред
положить, какой будет ширина окна при просмотре документа пользователем. За
давая ширину в процентах, следует поместить значение в двойные кавычки. П о
умолчанию ширина таблицы определяется исходя из размеров ее ячеек.
BGCOLOR
Цвет таблицы (либо ее отдельных строк или ячеек) существенно влияет на внеш
ний вид Web-страницы. Для определения цвета таблицы можно использовать ат
рибут BGCOLOR дескриптора <TABLE> (либо соответствующие средства листов
стилей, описанные в главе 5). Преимущество листов стилей состоит в том, что ес
ли вы захотите изменить цвет всех таблиц в составе Web-страницы, вам достаточ
но внести лишь незначительные изменения в код документа.
BACKGROUND
BACKGROUND— атрибут, специфический для Internet Explorer, он задает файл, со
держащий изображение, которое должно выводиться в качестве ф о н а таблицы.
Если отключить отображение обрамления, данный атрибут можно использовать
для вывода текста на ф о н е изображения, однако данная возможность не поддер
живается другими броузерами. Листы стилей позволяют реализовать такое ото
бражение в любом из новых броузеров. Учитывая это, мы не рекомендуем вам
применять атрибут BACKGROUND даже в тех случаях, когда Web-страницы предна
значены для внутренней сети, в которой используются броузеры Internet Explorer.
ALIGN
Дескриптор ALIGN (допустимые значения: LEFT, RIGHT, CENTER, JUSTIFY и CHAR)
задает тип горизонтального выравнивания содержимого ячеек в строке таблицы.
По умолчанию принимается значение LEFT. Значения JUSTIFY и CHAR не поддер
живаются ни Netscape, ни Internet Explorer.
VALIGN
Дескриптор VALIGN (допустимые значения: ТОР, MIDDLE, BOTTOM и BASELINE) за
дает тип вертикального выравнивания содержимого ячеек в строке таблицы. Если
указано значение BASELINE, первые строки каждой ячейки выравниваются по од
ной базовой линии. П о умолчанию принимается значение MIDDLE.
BGCOLOR
Атрибут BGCOLOR задает цвет ф о н а для строки таблицы. Цвет для строки замещает
цвет, заданный для всей таблицы с помощью атрибута BGCOLOR элемента TABLE.
Цвет для строки, в свою очередь, замещается цветом, заданным для отдельной
ячейки с помощью атрибута BGCOLOR элемента ТН или TD. Это дает возможность
выделить цветом одну или несколько ячеек таблицы. Так, например, в листинге
2.11 приведен п р и м е р таблицы, для которой в заголовках столбцов текст отобра
жается белым цветом на черном ф о н е , а в остальных ячейках выводится черный
текст на светло-сером ф о н е . Внешний вид таблицы показан на рис. 2.8. Таблицы
такого типа предпочитают большинство пользователей.
Version</FONT>
<TH><FONT COLOR="WHITE">Upcoming Version</FONT>
<TR><TD>HTML
<TD>3.2
<TD>4.0
<TD>XHTML
<TR><TD>HTTP
<TD>1.0
<TD>1.1
<TD>1.2
</TABLE>
</BODY>
</HTML>
ШШШЕШШШВШ
И11^И!МКД!1И
WWW Standards
,Ooci«w*,0«w
COLSPAN
Атрибут COLSPAN указывает на то, что ячейка заголовка или ячейка данных рас
ширятся на несколько столбцов. П р и м е р кода приведен в листинге 2.12. Внешний
вид таблицы показан на рис. 2.9,а.
<TABLE BORDER-1>
<TR><TH COLSPAN=2>Col 1&2 H e a d i n g
<ТН>Со13 H e a d i n g
<TR><TD>Coll Data
<TD>Col2 D a t a
<TD>Col3 D a t a
</TABLE>
iteidingi iiiee
цЩШЩ^^^^Ш
Co! 1&2 Heading CoB Holding ^ , „ ,0.0^41.^°^^°^^^^^
, * , *> Data for Row 1&2, Coll —™.__
CoU Data Col2 Data CoB Data ' |J^ow2 Col2 Data
(a) (6)
Рис. 2.9. (a) Расширение ячейки на несколько столбцов (пример кода приведен в листинге
2.12); (б) расширение ячейки на несколько строк (пример кода приведен в листинге 2.13)
ROWSPAN
Атрибут ROWSPAN определяет ячейку заголовка или данных, которая расширяется
на несколько строк. П р и м е р использования ROWSPAN приведен в листинге 2.13,
а внешний вид таблицы — на рис. 2.9,6.
<TABLE B0RDER=1>
<TR><TH>Headingl<TH>Heading2
<TR><TD R0WSPAN=2>Data f o r Row 1&2, Coll
<TD>Rowl C0I2 D a t a
<TR><TD>Row2 C0I2 D a t a
</TABLE>
74 Глава 2. Элементы блокового уровня HTML 4.0
ALIGNHVALIGN
Атрибут ALIGN (допустимые значения: LEFT, RIGHT, CENTER, JUSTIFY и CHAR) за
дает горизонтальное выравнивание данных в ячейке таблицы. П о умолчанию для
элементов TD принимается значение LEFT, а для элементов ТН — CENTER. Деск
р и п т о р VALIGN (допустимые значения: ТОР, MIDDLE, BOTTOM и BASELINE) задает
тип вертикального выравнивания содержимого ячейки. П о умолчанию принима
ется значение MIDDLE. З н а ч е н и я CHAR и BASELINE описаны при рассмотрении
элемента TR.
WIDTH и HEIGHT
Если атрибуты WIDTH и HEIGHT не указаны, размеры ячеек устанавливаются бро
узером, исходя из размеров окна и данных, содержащихся в ячейках. Атрибуты
WIDTH и HEIGHT позволяют явно задавать размеры ячейки в пикселях. Устанавли
вая размеры ячеек явным образом, следует соблюдать осторожность. Если разме
ры окна броузера на компьютере пользователя будут не такими, как предполагает
автор документа, ф о р м а т таблицы нарушится. Иногда ячейки с фиксированными
размерами используются для создания панелей инструментов с пиктограммами.
П р и этом размеры пиктограмм должны быть заранее известны и хотя бы одна
ячейка в строке должна допускать изменение размеров. В соответствии со специ
фикацией HTML 4.0 указание размеров ячеек в процентах не допускается, однако
и Netscape, и Internet Explorer поддерживают подобный ф о р м а т значений. П р и
этом размеры ячейки вычисляются относительно ш и р и н ы и высоты таблицы, а не
относительно размеров окна броузера. Атрибуты WIDTH и HEIGHT не рекомендо
ваны для применения. Вместо них желательно использовать соответствующие
средства листов стилей.
NOWRAP
Атрибут NOWRAP, также не рекомендованный для использования, запрещает пере
нос слов внутри ячейки. Аналогичного эффекта можно добиться, разделяя слова
неразрывными пробелами ( & n b s p ; ) или включая в состав ячейки элемент PRE (в
некоторых броузерах это приведет также к отображению данных ш р и ф т о м фик
сированной ш и р и н ы и появлению нежелательных символов перевода строки).
Используя атрибут NOWRAP, следует соблюдать осторожность, так как при этом
текст может оказаться за пределами окна броузера.
BGCOLOR и BACKGROUND
Атрибут BGCOLOR (спецификацией HTML 4.0 он не рекомендован для примене
ния) задает цвет ф о н а для ячейки таблицы. Атрибут BACKGROUND, поддерживае
мый Internet Explorer 3.0 и более новыми версиями, определяет файл, содержа
щий изображение, которое отображается в качестве ф о н а ячейки. Если размеры
ячейки превышают размеры изображения, оно отображается многократно.
Внимание!
ALIGN и VALIGN
Атрибут ALIGN (допустимые значения: LEFT, RIGHT, CENTER, JUSTIFY и CHAR) за
дает горизонтальное выравнивание для всех ячеек в группе. По умолчанию для
элемента THEAD принимается значение CENTER, а для элементов TBODY и TFOOT —
значение LEFT. Тип выравнивания CHAR был описан при рассмотрении элемента
TR. Атрибут VALIGN (допустимые значения: ТОР, MIDDLE, BOTTOM и BASELINE) за
дает тип вертикального выравнивания. П о умолчанию принимается значение
MIDDLE. Т и п ы вертикального выравнивания были описаны при рассмотрении
элемента TR.
76 Глава 2. Элементы блокового уровня HTML 4.0
ALIGNHVALIGN
Атрибут ALIGN (допустимые значения: LEFT, RIGHT, CENTER, JUSTIFY и CHAR) за
дает горизонтальное выравнивание для всех ячеек, объединенных с помощью
COLGROUP или COL. По умолчанию принимается значение LEFT, за исключением
тех случаев, когда ячейки объединены с помощью THEAD. Ячейки, принадлежащие
группе, созданной с помощью THEAD, по умолчанию выравниваются по центру.
Однако следует заметить, что выравнивание, заданное явно, изменяет тип вырав
нивания для раздела заголовка. С этим побочным эффектом легко справиться, за
давая атрибут ALIGN для каждого из элементов ТН либо используя соответствую
щие средства листов стилей. Атрибут VALIGN (допустимые значения: ТОР, MIDDLE,
BOTTOM и BASELINE) задает вертикальное выравнивание для всех ячеек в группе.
По умолчанию принимается значение MIDDLE. Значение BASELINE было описано
при рассмотрении атрибута ALIGN элемента TR. Следует заметить, что значения
JUSTIFY, CHAR и BASELINE поддерживаются не всеми броузерами.
SPAN и WIDTH
Атрибут SPAN указывает, какое количество последовательно расположенных
столбцов принадлежит элементу COLGROUP или COL. Атрибут WIDTH задает размер
группы COLGROUP или COL в процентах от ширины таблицы.
В листинге 2.15 показан простой пример группировки столбцов таблицы и управ
ления выравниванием каждого столбца. Один из элементов COLGROUP, расположен
ный перед элементом THEAD, связывается с первыми тремя столбцами, а второй эле
мент COLGROUP — с оставшимся столбцом. Тип выравнивания каждого столбца в пер
вой группе задается с помощью элемента COL. На рис. 2.11 показано, как таблица
отображается в окне броузера Internet Explorer 5.0, выполняющегося в среде Windows
2000 Professional. Поскольку в открывающем дескрипторе TABLE указано значение
GROUPS атрибута RULES, группы столбцов разделяются линией.
<COL ALIGN="LEFT">
<COL ALIGN="CENTER">
<COLGROUP ALIGN="RIGHT">
<THEAD>
<TR><TH>Year<TH>Cultivar<TH>Bloom Season<TH>Cost
<TBODY>
<TR><TD>1965<TD>Luxury Lace <TD>M <TD>11.75
<TR><TD>197 6<TD>Green Flutter<TD>M <TD> 7.50
<TR><TD>1984<TD>My Belle <TD>E <TD>12.00
<TR><TD>1985<TD>Stella De Oro<TD>E~L<TD> 5.00
<TR><TD>1989<TD>Brocaded Gown<TD>E <TD>14.50
<TFOOT>
<TR><TD C0LSPAN=4>E-early M - m i d s e a s o n L - l a t e
</TABLE>
L^fi^^'^?!'7''^^a;!'7l-li^ft^ -lDiiSj|
' FSe Edt View Favoritej Took НЫр
2.5. Формы
Элемент FORM позволяет организовать ввод данных в документ. Пользователь при
просмотре Web-страницы заполняет форму, и введенные данные передаются на сер
вер для обработки. Как привило, в состав элемента FORM входят поля и окна редакти
рования текста, флажки опций, переьслючатели опций, списки и кнопки. Подробно
элемент FORM будет рассматриваться в главе 18.
ALIGN
Атрибут ALIGN задает горизонтальное выравнивание. Допустимыми значениями
являются LEFT, RIGHT и CENTER. П о умолчанию принимается значение CENTER.
WIDTH
Атрибут WIDTH задает длину линии в пикселях (<HR WI DTH=7 5>) либо в процентах
от ширины окна броузера (<HR WIDTH="50%">). П о умолчанию принимается зна
чение 100%.
SIZE
Атрибут SIZE определяет толщину линии в пикселях. Толщина л и н и и прибавляет
ся к размеру тени, используемой для того, чтобы линия казалась "выгравирован
ной". По умолчанию принимается толщина, равная одному пикселю.
NOSHADE
Если задан атрибут NOSHADE, л и н и я отображается без затенения, создающего эф
фект "гравировки".
COLOR
COLOR— нестандартный атрибут, поддерживаемый Internet Explorer. Д а н н ы й ат
рибут изменяет цвет линии. Цвет задается в формате RGB (см. табл. 1.1).
COLS
Этот обязательный атрибут задает число колонок для отображения текста. Значе
ние COLS должно быть больше или равно двум.
GUTTER
Этот необязательный атрибут определяет расстояние в пикселях между колонка
ми. По умолчанию используется значение 10.
WIDTH
Атрибут WIDTH указывает ширину колонки в пикселях. Если данный атрибут не
указан, Netscape распределяет доступное пространство поровну между колонками.
2.7. Резюме
Элементы блокового уровня позволяют создавать основные компоненты Web-
страницы. С их помощью можно создавать заголовки, различные типы абзацев, спи
ски, таблицы, формы для ввода данных и другие конструкции. Для того чтобы изме
нить формат части текста внутри блокового элемента, надо использовать элементы
текстового уровня.
2.6. Прочие элементы блокового уровня 81
В этой главе...
<U>Underlined</U><BR>
Subscripts: f<SUB>0</SUB> + f<SUB>l</SUB><BR>
Superscripts: x<SUP>2</SUP> + y<SUP>2</SUP><BR>
<SMALL>Sinaller</SMALL><BR>
<BIG>Bigger</BIG><BR>
<STRIKE>Strike Through</STRIKE><BR>
<B><I>Bold Italic</I></B><BR>
<BIG><TT>Big Monospaced</TT></BIG><BR>
<SMALL><I>Small Italic</I></SiyLALL><BR>
<FONT COLOR="GRAY">Gray</FONT><BR>
<DEL>Delete</DEL><BR>
<INS>Insert</INS><BR>
</BODY>
</HTML>
^ Physicai tbm-m^eitmvkss^^fmm^m
Ne Edit View Favorites loots Hdp
3
Physical Character Styles
Bold
Italic
T e l e t y p e (Monospaced)
Underlined
Subscnpts: ^ + fj
Superscripts: x^ + y^
Smaller
Bigger
S t n k e Tlii-ough
Bold Italic
Big Monospaced
SmaW Italic
SIZE
Атрибут SIZE может принимать абсолютное значение в пределах от 1 (наимень
ший размер) до 7 (наибольший размер), а также относительные значения
(SIZE=" + 1", S I Z E = " - 1 " , S I Z E = " + 2 " и т.д.), которые задают изменения текущего
размера шрифта. Реальный размер шрифта для отображения выбирается броузе
ром. Задавая абсолютные значения, соблюдайте осторожность. Если пользователь
самостоятельно определит ш р и ф т для отображения документа, абсолютные зна
чения атрибута SIZE могут испортить внешний вид Web-страницы.
Методика профессионалов
COLOR
Как и при указании цвета в составе элемента BODY, в качестве значения атрибута
COLOR задается логическое имя (допустимые имена цветов перечислены в
табл. 1.1) либо значение в ф о р м а т е RGB. Определяя цвет текста, надо следить за
тем, чтобы он не сливался с фоном.
FACE
Netscape и Internet Explorer поддерживают атрибут FACE, в качестве значения ко
торого задается список имен шрифтов, разделенных запятыми. Если на клиент
ской машине есть первый из ш р и ф т о в , указанных в списке, он используется при
отображении документа. В противном случае система проверяет, имеется ли в на
личии второй ш р и ф т из списка и т.д. Если все ш р и ф т ы , указанные в списке, отсут
ствуют, применяется ш р и ф т по умолчанию, т.е. броузер ведет себя так, как будто
атрибут FACE не был задан.
Внимание!
<EM>Emphasized</EM><BR>
<STRONG>Strongly Emphasized</STRONG><BR>
<CODE>Code</CODE><BR>
<SAMP>Sample Output</SAMP><BR>
<KBD>Keyboard Text</KBD><BR>
<DFN>Definition</DFN><BR>
<VAR>Variable</VAR><BR>
<CITE>Citation</CITE><BR>
<EM><CODE>Emphasized Code</CODEX/EM><BR>
<FONT COLOR="GRAY"><CITE>Gray Citation</CITE></FONT><BR>
<ACRONYM TITLE="Java Development Kit">JDK Acronym</ACRONYM>
</BODY>
</HTML>
HREF
Атрибут HREF задает адрес ресурса, который броузер должен загрузить в том слу
чае, если пользователь активизирует ссылку (щелкнет кнопкой мыши в указанной
области). Значением HREF может быть абсолютный URL, относительный URL,
символ "#" за которым следует имя позиции в документе (см атрибут NAME), либо
URL, после которого указан символ "#", сопровождаемый именем позиции. Если
указан конкретный раздел документа, при активизации ссылки броузер копирует
этот документ и отображает его, начиная с заданной позиции. В противном случае
броузер отображает начало требуемого документа.
Как будет показано в главе 19, если в URL, определяющем каталог, не указана за
вершающая косая черта, броузер устанавливает два соединения с HTTP-сервером.
Во время первого соединения броузер получает корректный URL, а во время вто
рого соединения он отправляет запрос, к о т о р ы й содержит URL, скорректирован
ный в соответствии с полем L o c a t i o n в ответе HTTP-сервера. Если производи
тельность линий связи невелика, лишний запрос приводит к ненужной трате вре
мени. Поэтому вместо http://some.host.com/some/directory всегда
задавайте h t t p : / / s o m e . h o s t , c o m / s o m e / d i r e c t o r y / .
Совет
М е т о д и к а профессионалов
NAME
Атрибут NAME присваивает имя позиции в документе. В результате на эту позицию
могут указывать ссылки, в которых значение атрибута HREF содержит символ "#".
Например:
<А NAME="COBOL">COBOL: А Programming Language f o r t h e Future</A>
Имя, задаваемое с помощью атрибута NAME, зависит от регистра символов.
TARGET
Атрибут TARGET указывает на то, что документ должен быть открыт в конкретном
кадре либо в новом окне. Атрибут TARGET будет подробно рассмотрен в главе 4.
3.3. Построение гипертекстовых ссылок 93
TITLE
Атрибут TITLE присваивает заголовок документу, в котором заголовок отсутствует
(например, каталогу FTP). В некоторых броузерах с помощью TITLE предлагается
тема электронного письма (поле s u b j e c t : ) . Значение TITLE может быть исполь
зовано индексирующими программами для построения меню ссылок.
RELHREV
REL и REV применяются гораздо реже, чем другие атрибуты. С их помощью можно
определить отношение текущего документа к связанному (REL) и связанного доку
мента — к текущему (REV).
ONFOCUS и ONBLUR
Эти атрибуты используются броузерами, поддерживающими JavaiScript. С их по
мощью определяется JavaScript-код, обрабатывающий события, связанные с полу
чением и потерей фокуса. Получение и потеря фокуса может происходить в ре
зультате действий с клавиатурой или мышью. Дополнительную и н ф о р м а ц и ю вы
найдете в главе 24.
COORDS и SHAPE
Если гипертекстовая ссылка представляет карту изображений, связанную с CGI-
программой, атрибут COORDS задает координаты (х,у) области изображения. Ат
рибут SHAPE указывает, как должны интерпретироваться пары (х,у). Д а н н ы е атри
буты будут подробнее рассмотрены в разделе 3.5.
TYPE, CHARSET и H R E F L A N G
Атрибут TYPE определяет МШЕ-тип, связанный с ресурсом, на который указывает
ссылка, например TYPE=" t e x t / h t m l " . Атрибут CHARSET задает кодировку свя
занного документа, например CHARSET="ISO-8859-6". Атрибут HREFLANG опре
деляет язык ресурса, например, выражение HREFLANG="pt" означает, что доку
мент, на который указывает ссылка, представлен на португальском языке.
ACCESSKEY и T A B I N D E X
Атрибут ACCESSKEY задает единичный символ (соответствующий кодировке доку
мента), который используется в сочетании с клавишей <Alt> (в системе MS-
Windows) или <Cmd> (в системе Apple). П р и нажатии комбинации клавиш фокус
перемещается к соответствующему элементу. Атрибут TABINDEX указывает целое
число в диапазоне 0-32767, которое задает порядок элементов в документе. Если
пользователь перемещается по документу с помощью клавиатуры, TABINDEX опре
деляет порядок получения фокуса элементами документа. По умолчанию все эле
менты, не поддерживающие атрибут TABINDEX, получают значение 0. Элементы с
одинаковыми значениями получают фокус в том порядке, в котором они встреча
ются в документе. Internet Explorer 5.0 поддерживает оба указанных атрибута.
Netscape 4.x не поддерживает ни ACCESSKEY, ни TABINDEX.
94 Глава 3. Элементы текстового уровня HTML 4.0
Анимационные аГ-файлы
Многие броузеры поддерживают стандарт GIF89A, к о т о р ы й позволяет включать в
состав одного графического файла несколько кадров. Кадры сменяют друг друга через
определенный интервал времени, что создает э ф ф е к т простой анимации. Если бро
узер поддерживает только формат GIF87, он может корректно отобразить первый
кадр в составе изображения GIF89A. GIF89A является альтернативой анимации на ба
зе Java, при этом структура Web-страницы существенно упрощается. Многие про
граммные пакеты позволяют создавать файлы GIF89A, объединяя несколько единич
ных изображений, представленных в различных форматах, либо конвертируя анима
ционные файлы AVI или QuickTime.
Элемент IMG
Элемент: <IMG SRC="..." ALT="..," ...> (закрывающий дескриптор
отсутствует)
Атрибуты: SRC (обязательный), ALT (обязательный), ALIGN, WIDTH, HEIGHT, HSPACE,
VSPACE, BORDER, USEMAP, ISMAP, NAME, LONGDESC, ONLOAD (нестандартный), ONERROR
(нестандартный), ONABORT (нестандартный)
Элемент IMG включает изображение в текущую позицию в документе. Заметьте,
что IMG представляет собой элемент текстового уровня и не приводит к созданию но
вого абзаца. IMG не является контейнером, поэтому закрывающий дескриптор не ука
зывается.
SRC
SRC — обязательный атрибут. О н определяет расположение файла, содержащего
изображение, которое должно быть включено в документ. Значением SRC может
быть как абсолютный, так и относительный URL. П р и м е р ы элементов IMG, со
держащих атрибуты SRC, приведены ниже.
<IMG SRC="http://www.some-isp.сош/~jane/portrait.jpg"
ALT="Jane Doe">
<IMG SRC="images/spot.gif" WIDTH=150 HEIGHT=120
ALT="My dog Spot">
3 . 4 . Встроенные и з о б р а ж е н и я 95
ALT
Атрибут ALT задает строку, которая выводится вместо изображения в броузерах,
не поддерживающих графические файлы. Спецификация HTML 4.0 определяет
атрибут ALT как обязательный.
WIDTH и H E I G H T
Эти два атрибута определяют раЗхМеры области, которую должно занимать изобра
жение в документе. Размеры задаются в пикселях. Если в составе элемента IMG указа
ны атрибуты WIDTH и HEIGHT, броузер может сначала отобразить текст, а затем за
грузить и вывести изображение, не изменяя структуру страницы. Подобный подход
к отображению страницы улучшает ее восприятие пользователем. Если, работая с
Netscape, вы непосредственно загрузили изображение, то, выбрав пункт P a g e Info
меню View, вы можете определить размеры этого изображения. Размеры также ото
бражаются в заголовке окна Netscape. В Internet Explorer 5.0, чтобы определить раз
меры изображения, достаточно расположить поверх него курсор мыши, щелкнуть
правой кнопкой и выбрать в контекстном меню пункт Properties. Если значения ат
рибутов WIDTH и HEIGHT не совпадают с реальными размерами изображения, изо
бражение растянется или сожмется, чтобы соответствовать размерам, заданным в
составе дескриптора IMG. Если при загрузке размеры изображения изменились, то
при выборе пункта Properties из контекстного меню Internet Explorer сообщает не
исходные размеры изображения, а его размеры в окне броузера.
Методика профессионалов
ALIGN
Атрибут ALIGN, который, согласно спецификации HTML 4.0, не рекомендован для
применения, определяет расположение изображения относительно текстовой
строки, в которой присутствует дескриптор <IMG>. Допустимыми значениями
данного атрибута являются LEFT, RIGHT, TOP, BOTTOM и MIDDLE. П о умолчанию
принимается значение BOTTOM. З н а ч е н и я LEFT и RIGHT задают обтекание изо
бражения текстом и обычно указываются тогда, когда изображение используется в
качестве иллюстрации. Если вы указали значение LEFT или RIGHT и не хотите,
чтобы рядом с изображением выводился текст, надо использовать элемент <BR
CLEAR="ALL">. Подробно элемент BR будет рассматриваться далее в этой главе.
Значение MIDDLE применяется при работе с изображениями малого размера, вы
полняющего функции маркера. В листинге 3.4 приведены различные примеры
выравнивания. Результаты показаны на рис. 3.3.
96 Глава 3. Элементы текстового уровня HTML 4.0
^b^3k:i^t^m4A^kMl^tM^^
Image Alignment
I Alignment Result
^ ^ ^ This positions the image at the left side, with text flowing around it
^w\ 5, ^ <5п the nght
LEFT .VJIOT^"
r^ : ^_____
This positions the image at the nght side, with text flowing around ^ ^ ^
it on the left '^'wi^N^'
RIGHT ,4Jp}^'
^ ^ ^ Here, the image runs into the paragraph and the line containing the
Here, the image runs into the paragraph and the line containing the
iimage is aligned with the image bottom.
j9>,*^ Here, the image runs into the paragraph and Ле line containing the
Листинг3.4. Image~Alignment.html
<TABLE B0RDER=1>
<TR><TH>Alignment
<TH>Result
<TR><TH><CODE>LEFT</CODE>
<TD><IMG SRC="rude-pc.gif" ALIGN="LEFT"
ALT="Rude PC" WIDTH=54 HEIGHT=77>
This positions the image at the left side,
with text flowing around it on the right.
<TR><TH><CODE>RIGHT</CODE>
<TD><IMG SRC="rude-pc.gif" ALIGN="RIGHT"
ALT="Rude PC" WIDTH=54 HEIGHT=77>
This positions the image at the right side,
with text flowing around it on the left.
<TR><TH><CODE>TOP</CODE>
3.4. Встроенные изображения 97
</BODY>
</HTML>
HSPACE и VSPACE
Эти атрибуты задают размеры пустого пространства (в пикселях) слева и справа от
изображения (HSPACE), а также над и под изображением (VSPACE). Часто по умол
чанию принимается значение 2. HTML 4.0 явно не определяет средства, обеспе
чивающие перекрытие изображений и расположение текста над изображением,
но этот э ф ф е к т можно реализовать, задавая отрицательные границы в каскадных
листах стилей. Поскольку и HSPACE, и VSPACE не рекомендованы для применения,
мы рекомендуем использовать для контроля границ изображения листы стилей.
Подробные сведения о работе с листами стилей вы найдете в главе 5.
BORDER
Атрибут BORDER, также не рекомендованный для применения, задает ширину рам
ки, отображаемой вокруг изобрг1жения, оформленного в виде гипертекстовой
ссылки. По умолчанию принимается значение, равное 2.
USEMAP
Атрибут USEMAP задает имя компонента MAP как " # n a m e " или "URL#name". Под
робное описание и п р и м е р ы использования данного атрибута приведены далее в
этой главе.
ISMAP
Атрибут ISMAP задает использование изображения как карты, связанной с CGI-
программой. Данный атрибут допустим только в том случае, когда изображение
является частью гипертекстовой ссылки. Дополнительную и н ф о р м а ц и ю по этому
вопросу вы найдете в главе 18.
98 Глава 3. Элементы текстового уровня HTML 4.0
NAME
Атрибут NAME присваивает изображению имя. Если броузер поддерживает
JavaScript, программы на JavaScript в составе документа могут обращаться по этому
имени к изображению
LONGDESC
Атрибут LONGDESC задает URI детального описания изображения. Этот атрибут в
основном ориентирован на пользователей, которые работают с броузерами, не
поддерживающими графические изображения.
Рис. 3.4. Карты изображений на стороне Рис. 3.5. Результат активизации нижнего ле
клиента позволяют связывать Web-страницы с вого квадранта изображения на рис. 3.4
различными фрагментами изображения
HREF
Атрибут HREF определяет целевой документ. В качестве его значения могут быть
заданы абсолютный, относительный URL, а также имя позиции, следующее за
символом "#".
COORDS
Атрибут COORDS содержит список координат области, разделенных запятыми.
Число координат и порядок их обработки зависят от значения атрибута SHAPE.
Координаты должны задаваться целыми числами и интерпретироваться как рас
стояние в пикселях от верхнего левого угла изображения.
SHAPE
К допустимым значениям атрибута SHAPE относятся RECT (принимается по умол
чанию), CIRCLE, POLY и DEFAULT. Если значение не равно DEFAULT, атрибут
SHAPE должен использоваться совместно с атрибутом COORDS. Значению RECT со
ответствуют координаты, заданные в формате "левая граница, верхняя граница,
правая граница, нижняя граница". Н а п р и м е р , следующее выражение связывает
документ r e g i o n 3 . h t m l с областью размером 200x200 пикселей, левый верхний
угол которой расположен в точке (20,40):
<AREA H R E F = " r e g i o n 3 . h t m l "
SHAPE="RECT"
COORDS="20,40,220,240">
Если указано значение CIRCLE, координаты задаются посредством атрибута
COORDS в виде "х,у,радиус". З н а ч е н и е POLY требует координат в виде "х1, у1,х2,
y2,...,xN, yN", определяющих вершины многоугольника. Значение DEFAULT не
предполагает использования атрибута COORDS и означает все изображение цели
ком. URL, принадлежащий перекрывающимся областям, определяется посредст
вом первого элемента AREA. Область по умолчанию всегда определяется послед
ней, независимо от того, указан ли в элементе AREA атрибут SHAPE со значением
DEFAULT.
ALT
Атрибут ALT определяет строку, описывающую целевой ресурс. Если пользователь
помещает курсор мыши в пределах области, значение данного атрибута отобража
ется в строке состояния.
NOHREF
Атрибут NOHREF определяет область, с которой не связан конкретный URL. Этот
атрибут необходим только в том случае, когда вы хотите исключить из числа акти-
3 . 6 . Включение объектов в д о к у м е н т 101
TARGET
Атрибут TARGET определяет ф р е й м , в котором должны отображаться результаты.
Карты изображений часто используются в документах с фреймами. Фреймы будут
подробно описаны в главе 4.
O N F O C U S , O N B L U R , ACCESSKEY и T A B I N D E X
Эти атрибуты используются так же, как и в элементе IMG, описанном ранее.
Встроенные аплеты
Э л е м е н т : <APPLET CODE="..." W I D T H = x x x H E I G H T = x x x ...> ... < / A P P L E T >
Атрибуты: CODE, WIDTH (обязательный), HEIGHT (обязательный), CODEBASE, ALT, ALIGN,
HSPACE, VSPACE, NAME, OBJECT, ARCHIVE (нестандартный), MAYSCRIPT (нестандартный)
Дескриптор APPLET позволяет включать в состав Web-страниц аплеты. П о д р о б н о
этот вопрос будет рассмотрен в главе 9.
CODE
Атрибут CODE определяет имя Java-файла класса, который должен быть загружен
броузером. Атрибу'т CODE является обязательным за исключением тех случаев, ко
гда указан атриб)т OBJECT. CODE не задает абсолютный URL, а лии1Ь указывает имя
файла. Если атрибут CODEBASE отсутствует, считается, что файл находится в том
же каталоге, что и Web-страница.
102 Глава 3 . Э л е м е н т ы текстового уровня H T M L 4 . 0
На з а м е т к у
WIDTH и HEIGHT
Эти атрибуты определяют размеры области в окне броузера, которую должен за
нимать аплет. Размеры задаются в пикселях либо в процентах от ширины окна
броузера. Следует заметить, что программа a p p l e t v i e w e r , разработанная Sun
(упрощенный броузер, который игнорирует все HTML-дескрипторы за исключе
нием APPLET), не поддерживает размеры, заданные в процентах, поскольку окно,
относительно которого должны вычисляться размеры, не определено. Атрибуты
WIDTH и HEIGHT обязательны для всех аплетов.
Внимание!
CODEBASE
Атрибут CODEBASE определяет URL базового каталога. Из этого каталога загружа
ется файл, указанный посредством атрибута CODE. Использование данного атрибу
та описано в главе 9.
ALT
Броузеры, поддерживающие Java, игнорируют все элементы разметки, располо
женные между дескрипторами <APPLET . . . > и </APPLET>, поэтом)' в области, в
которой должен быть расположен аплет, отображается альтернативный текст.
Атрибут ALT предназначен для тех броузеров, которые поддерживают Java, но в
которых возможность обработки аплетов отключена. Атрибут ALT поддерживает
ся сравнительно редко, поэтому мы не рекомендуем использовать его.
ALIGN
Атрибут ALIGN определяет выравнивание области, в которой располагается бро
узер. Для этого атрибута допустимы те же значения, что и для соответствующего
атрибута элемента IMG, к о т о р ы е интерпретируются аналогичным образом.
HSPACE
Атрибут HSPACE задает размеры пустого пространства в пикселях слева и справа
от аплета.
VSPACE
Атрибут VSPACE задает размеры пустого пространства в пикселях снизу и сверху
от аплета.
3 . 6 . Включение объектов в д о к у м е н т 103
NAME
Атрибут NAME присваивает аплету имя, которое используется для организации
взаимодействия между аплетами, а также при обращении к аплету JavaScript-
программы.
OBJECT
Атрибут OBJECT используется для определения сериализованного аплета, кото
рый был сохранен с использованием средств сериализации Java.
ARCHIVE
Атрибут ARCHIVE определяет архив классов, которые должны быть заранее загру
жены. Архив задается в ф о р м а т е Java Archive (. j a r ) , однако Netscape поддержива
ет также архивы uncompressed Zip (. z i p ) .
MAYSCRIPT
Netscape и Internet Explorer с помощью этого атрибута определяют, можно ли
управлять аплетом из JavaScript-программы. Дополнительную и н ф о р м а ц и ю по
этому вопросу вы найдете в главе 24.
Согласно спецификации HTML 4.0 элемент APPLET и все его атрибуты не реко
мендованы для использования. В качестве альтернативы предлагается элемент
OBJECT. Тем не менее многие авторы предпочитают элемент APPLET как более про
стой. Дополнительные сведения об элементах APPLET и OBJECT будут приведены в
главе 9.
Внимание!
CLASSID
С помощью этого атрибута определяется URL. Для зарегистрированных элемен
тов CLASSID представляется в виде c l s i d : иденшификатор_класса.
CODETYPE
Атрибут CODETYPE определяет тип объекта. Для аплетов данный атрибут задается
в виде C O D E T Y P E = " a p p l i c a t i o n / J a v a " . Дополнительные сведения приведены в
главе 9.
CODEBASE
Атрибут CODEBASE задает каталог, из которого копируется управляющий элемент.
Данный атрибут используется так же, как атрибут CODEBASE элемента APPLET.
STANDBY
Атриб)а^ STANDBY задает строку текста, отображаемую при загрузке объекта.
ARCHIVE
Атрибут ARCHIVE определяет список URI ресурсов, которые должны быть загру
жены перед активизацией объекта. Компоненты списка разделяются пробелами.
URI задаются относительно каталога, указанного с помощью атрибута CODEBASE.
Для аплетов архивы представляются в формате JAR. Для создания JAR-файла ис
пользуется утилита j a r .
DATA и TYPE
Атрибут DATA задает URI файла данных, обрабатываемого объектом. Атрибут
TYPE определяет МШЕ-тип данных в этом файле.
NAME
Атрибут NAME обрабатывается броузерами, поддерживающими JavaScript. С помо
щью этого атрибута задается имя, используемое JavaScript-сценарием для обраще
ния к объекту.
TABINDEX
Если пользователь перемещается по документу с помощью клавиатуры, атрибут
TABINDEX определяет, в каком порядке элементы должны получать фокус. Значе-
106 Глава 3. Элементы текстового уровня HTML 4.0
нием TAB INDEX является целое число в диапазоне от О до 32767. П о умолчанию все
элементы, для которых не указан атрибут TAB INDEX, получают значение 0. Эле
менты с одинаковыми значениями данного атрибута получают фокус ввода в том
порядке, в котором они расположены в документе. Данный атрибут поддержива
ется Internet Explorer 5.x и не поддерживается Netscape 4.x.
Спецификация HTML 4.0 определяет атрибут DECLARE, который в настоящее
время не поддерживается ни Netscape, ни Internet Explorer. Этот атрибут запрещает
начальную загрузку элемента, указанного с помощью OBJECT, но разрешает загружать
его впоследствии п)тем активизации ссылки, действий, предпринимаемых другим
объектом, либо после щелчка на кнопке.
Спецификация HTML определяет также атрибут USEMAP элемента OBJECT, с по
мощью которого задается карта изобрг1жения на стороне клиента. Атрибут USEMAP не
поддерживается Internet Explorer 5.x, Netscape 4.7 и более ранними версиями этих
броузеров, однако Netscape 6 поддерживает USEMAP.
Большое количество управляющих элементов ActiveX, разработанных независи
мыми производителями, можно найти на сервере CNET ActiveX Download Caller)' по
адресу h t t p : / / w w w . a c t i v e x . c o m / .
Бегущая строка
Элемент: <MARQUEE ...> ... </MARQUEE>
А т р и б у т ы : WIDTH, HEIGHT, ALIGN, BEHAVIOR, BGCOLOR, DIRECTION, HSPACE, VSPACE,
LOOP, SCROLLAMOUNT, SCROLLDELAY
Элемент MARQUEE представляет собой расширение Internet Explorer. Текст, распо
ложенный между открывающим дескриптором <^4ARQUEE . . . > и закрывающим
</MARQUEE>, оформляется в виде бегущей строки. В составе элемента MARQUEE недо
пустимы другие элементы разметки, но сам MARQUEE может быть задан в составе таких
элементов, как FONT. В результате автор получает возможность создавать, например,
бегущую строку, в которой отображаются символы большого размера синего цвета. Все
броузеры, кроме Internet Explorer, игнорируют дескрипторы MARQUEE и рассматривают
текст, содержащийся в составе данного элемента, как часть текущего абзаца. Элемент
MARQUEE можно использовать без атрибутов либо включать в состав открывающего де
скриптора атрибуты, описанные ниже. Заметьте, что многие пользователи рассматри
вают бегущую строку как досадную помеху, затрудняющ)то восприятие Web-страницы,
поэтому, используя элемент MARQUEE, соблюдайте осторожность.
WIDTH и HEIGHT
Данные атрибуты задают высоту и ширину области для бегущей строки. З н а ч е н и я
атрибутов указываются в пикселях либо в процентах от размеров окна Internet
Explorer. П о умолчанию принимается ширина области, равная ширине окна, а вы
сота выбирается в зависимости от используемого шрифта.
3.6. Включение объектов в документ 107
ALIGN
Атрибут ALIGN определяет выравнивание бегущей строки относительно окру
жающего текста. Допустимыми значениями являются LEFT, RIGHT, CENTER, TOP,
BOTTOM и MIDDLE; они используются так же, как и соответствующие значения эле
мента IMG, описанные ранее в этой главе.
BEHAVIOR
Атрибут BEHAVIOR описывает порядок перемещения текста. Значение SCROLL,
принимаемое по умолчанию, указывает, что текст должен перемещаться в одном
направлении до тех пор, пока не достигнет края области, после чего движение
текста начинается сначала. Если задано значение SLIDE, текст перемещается до
тех пор, пока не достигнет края области, после чего движение прекращается. Зна
чение BOUNCE указывает на то, что текст должен перемещаться вперед и назад в
пределах области.
BGCOLOR
Атрибут BGCOLOR задает цвет ф о н а области бегущей строки.
DIRECTION
Атрибут DIRECTION задает направление, в котором должен перемещаться текст
(если атрибут BEHAVIOR имеет значение BOUNCE, то атрибут DIRECTION указыва
ет, в каком направлении текст начнет движение). Допустимыми значениями явля
ются LEFT (перемещение слева направо) и RIGHT (перемещение справа налево).
По умолчанию принимается значение LEFT.
HSPACE и VSPACE
Атрибуты HSPACE и VSPACE задают размеры пустого пространства вокруг области
бегущей строки. Значения данных атрибутов указываются в пикселях.
LOOP
Атрибут LOOP указывает, сколько раз должно повторяться перемещение текста.
Значение, равное -1, или INFINITE (принимаемое по умолчанию) указывает на то,
что текст должен перемещаться все время, пока дoк)^vIeнт отображается в окне
броузера.
SCROLLAMOUNT
Атрибут SCROLLAMOUNT задает расстояние в пикселях между последовательно
отображаемыми фрагментами текста.
SCROLLDELAY
Атрибут SCROLLDELAY задает время в миллисекундах между последовательными
показами текста.
108 Глава 3. Элементы текстового уровня HTML 4.0
3.8. Резюме
Элементы текстового уровня дают возможность определять стили отображения,
задавать переводы строк и создавать гипертекстовые ссылки в составе документа.
Кроме того, с помощью элементов текстового уровня можно помещать на Web-
страницу изображения, оформлять их как гипертекстовые ссылки и даже связывать с
различными областями одного изображения разные ссылки. Многие броузеры позво-
3.7. Управление переводом строк 109
в этой главе...
ROWS
Атрибут ROWS делит окно броузера (или текущий фрейм — в случае вложенных
элементов FRAMESET) на горизонтальные строки. Этот атрибут используется сле
дующим образом:
<FRAMESET ROWS="Rowl-Size, ... , RowN-Size">
</FRAMESET>
Приведенный выше фрагмент кода делит окно броузера на N строк. Размер строки
задается целым числом (в этом случае значение интерпретируется как количество
пикселей), либо целым числом, за которым след}^ет символ "%" (в этом случае раз
мер строки вычисляется в процентах от размера допустимой области), либо сим
волом "*". Знак "*" интерпретируется как "оставшееся пространство"; при необхо-
114 Глава 4 . Ф р е й м ы
</FRAMESET>
Данный фрагмент кода задает в окне четыре строки. Высота первой строки равна
50 пикселям. Вторая строка занимает 10 процентов от высоты допустимой облас
ти. Оставшееся пространство распределяется между двумя строками, причем тре
тья строка занимает одну треть этого пространства, а четвертая — две трети (так
как перед знаком "*" был указан множитель 2). Д а н н о е деление окна броузера по
казано на рис. 4.1.
1 Frame Cell 4
1 ТП i^-^ 11 Щ
Frame Cell Я
Frame Cell
1 This is a sample HTML document to be used in frame cells.
Щ^Щ^
Как видно из рисунка, малые размеры ф р е й м а приводят к том)% что документ, ото
бражаемый в нем, практически невозможно читать. Планируя деление окна,
имейте в виду, что размеры окна и ш р и ф т на компьютере пользователя могут от
личаться от выбранных вами при просмотре документа. Заметьте, что значение
атрибута ROWS должно определять как минимум две строки, в противном случае в
броузере Netscape Web-страница будет отображаться некорректно. Например,
приведенный ниже фрагмент кода будет выведен как пустое окно (при использо
вании Netscape).
<FRAMESET R O W S - " * " >
<FRAME SRC="CoreWebProgramming.html">
</FRAMESET>
Внимание!
COLS
Атрибут COLS делит окно броузера (или текущий фрейм— в случае вложенных
элементов FRAMESET) на вертикальные столбцы. Как и ROWS, атрибут COLS может
присутствовать либо в документе верхнего уровня, либо в составе фрейма, опре
деленного посредством FRAMESET. Д а н н ы й атрибут должен определять как мини
мум два столбца. Помещать в состав FRAMESET один элемент FRAME нет необходи
мости, кроме того, это может привести к некорректному отображению Web-
страницы в броузере Netscape. В составе открывающего дескриптора FRAMESET
должен быть указан либо один атрибут ROWS, либо один атрибут COLS.
FIIAMEBORDER
Атрибут FRAMEBORDER определяет, должны ли отображаться разделительные ли
нии между фреймами. П о умолчанию разделительные л и н и и выводятся на экран.
Значение FRAMEBORDER=0 о б ы ч н о применяется в сочетании со значениями
BORDER=0 и FRAMESPACING=0, результатом являются ф р е й м ы без внутренних и
внешних разделителей. З н а ч е н и е FRAMEBORDER элемента FRAMESET заменяется
значением FRAMEBORDER элемента FRAME либо значением этого атрибута в составе
вложенного FRAMESET. Netscape 3.0, Internet Explorer 4.0, a также их более новые
версии поддерживают значение атрибута FRAMEBORDER YES, или 1, указывающее
на то, что разделители должны отображаться, и значение N0, или О, запрещающее
вывод разделителей. В качестве примера в листингах 4.2 и 4.3 приведены исход
ные коды двух документов с фреймами. Эти документы почти идентичны и отли
чаются только использованием атрибута FRAMEBORDER. Результаты показаны на
рис. 4.2 и 4.3.
Листинг4.2. Frame-Borders.html
:LJjмл^li'^lJi^J!•PL^'Ш'JШl^Jli!lИl>?fЯlf^^ '
£de £d« View F§vofkes lools й«Ь ^ > ^ ., ^ КШ[
Frame Cell
1 Tbs IS a sample HTML document to be used ш frame cells. 1
0] Done i ^ My Cofflpii»
Листинг4.3. Frame-Borderless.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN">
<HTML>
<HEAD>
<TITLE>Borderless Frames</TITLE>
</HEAD>
<FRAMESET COLS="*,*">
<FRAME SRC="Frame-Cell.html">
<FRAME SRC="Frame-Cell.html">
</FRAMESET>
<N0FRAMES>
<BODY>
Your browser does not support frames. Please see
<A HREF="Frame-Cell.html">nonframes version</A>.
</BODY>
</NOFRAMES>
</FRAMESET>
</HTML>
4 . 2 . Разбиение окна броузера на фреймы 117
Frame Cell
1 This IS a sample HTML document to be iised m frame cells.
BORDERCOLOR
BORDERCOLOR— нестандартный атрибут, поддерживаемый как Netscape, так и
Internet Explorer. Он задает цвет разделителя между фреймами. В качестве значе
ния задается либо шестнадцатеричное число, определяющее цвет, либо имя цвета.
По )ТУ1олчанию используются цвет ф о н а с уменьшенной яркостью и имитация
трехмерных э ф ф е к т о в посредством затенения. Значение этого атрибута замеща
ется значением BORDERCOLOR элемента FRAME либо вложенного элемента
FRAMESET.
ONFOCUS и O N B L U R
Эти атрибуты задают код JavaScript, выполняемый в тот момент, когда ф р е й м со
ответственно получает или теряет фокус. Несмотря на то что имена атрибутов не
чувствительны к регистру символов, данные атрибуты связаны с выполнением
JavaScript-сценариев, поэтом)^ их принято обозначать o n F o c u s и o n B l u r .
ONLOAD и O N U N L O A D
Данные атрибуты определяют JavaScript-код, который выполняется при загрузке
набора ф р е й м о в и тогда, когда броузер прекращает их отображение. Эти атрибуты
также принято обозначать o n L o a d и o n U n l o a d .
118 Глава 4 . Ф р е й м ы
SRC
Атрибут SRC задает URL документа, который должен быть отобрг1жен в текущем
фрейме. Этот атрибут не является обязательным, поскольку спецификация HTML
4.0 допускает пустые ф р е й м ы . Однако во избежание непредсказуемых результатов
при работе с Netscape атрибут SRC желательно задавать.
Внимание!
NAME
Атрибут NAME присваивает имя текущему фрейму. Атрибут TARGET элементов А,
AREA, BASE и FORM может быть использован для отобра>1се1П1Я во ф р е й м е нового
документа. К тому же результат)^ приведет вызов Java-метода showDocument, для
которого вторым параметром задано имя фрейма. Имя должно начинаться с бук
вы, однако существуют четыре заранее определенных имени, начинающиеся с
символа подчеркивания.
FRAMEBORDER
Атрибут FRAMEBORDER определяет, должны ли отображаться разделители с ими
тацией трехмерного представления. З н а ч е н и е FRAMEBORDER элемента FRAME пе
реопределяет значение одноименного атрибута, который принадлежит включаю
щему элементу FRAMESET. Считается, что разделитель не должен отображаться
только в том случае, если в двух смежных фреймах его вывод запрещен соответст
вующими значениями FRAMEBORDER. Netscape 3.0, Internet Explorer 4.0 и более но
вые версии этих броузеров поддерживают значение атрибута FRAMEBORDER YES,
или 1, указывающее на то, что разделители должны отображаться, и значение N0,
или О, запрещающее вывод разделителей!.
BORDERCOLOR
Атрибут BORDERCOLOR задает цвет разделителя между фреймами. В качестве зна
чения задается либо шестнадцатеричное число, определяющее цвет в ф о р м а т е
RGB, либо имя цвета (см. табл. 1.1 в разделе 1.6). В случае конфликта цвета прини
мается цвет вложенного элемента.
4.3. Определение содержимого фреймов 119
MARGINWIDTH
Атрибут MARGINWIDTH определяет размеры левой и правой границ.
MARGINHEIGHT
Атрибут MARGINHEIGHT определяет размеры верхней и нижней границ.
SCROLLING
Атрибут SCROLLING определяет, должна ли в составе ф р е й м а отображаться полоса
прокрутки. В Netscape значение YES указывает на то, что полоса прокрутки всегда
должна присутствовать в составе фрейма. Если задано значение AUTO (принимает
ся по умолчанию), то полоса прокрутки отображается только в том случае, если
документ не помещается в отведенном для него пространстве. Для Internet Ex
plorer YES (значение по умолчанию) означает то же, что и AUTO. Значение N0 за
прещает вывод полосы прокрутки как в Netscape, так и в Internet Explorer.
NORESIZE
По умолчанию пользователю разрешается изменять размеры фреймов, перетаски
вая границу между фреймами с помощью мыши. Атрибут NORESIZE запрещает из
менение размеров.
LONGDESC
Атрибут LONGDESC задает URI документа, в котором приводится детальное описа
ние фрейма. О б ы ч н о LONGDESC применяется для невизуальных броузеров.
Примеры
Код, приведенный в листинге 4.4, создает в окне броузера две строки; первая
строка делится на три столбца, а вторая — на два. Результат показан на рис. 4.4.
Л и с т и н г 4 . 4 . Frame-Examplel.htinl
.:^-:^...m..
Рис. 4.4. Окно броузера разделено на две строки; в первой из них
созданы три столбца, а во второй — два
4.3. Определение содержимого фреймов 121
Код, представленный в листинге 4.5, делит окно на два столбца. В первом столбце
создаются три строки, а во втором — две. Результат показан на рис. 4.5.
^.~ ^ ^ a Ш Ш
Frame Cell Frame Cell
This IS a sample HTML document to be used in This IS a sample HTML document to be
frame ceDs. used in frame cells.
Frame Cell
This is a sample HTML document.to be used in
frame cells. Frame Cell
This is a sample HTML document to be
Frame Cell used in frame cells.
М е т о д и к а профессионалов
ШЕШШ2ШШШШ1 щшт
£1е £ Л Yiew fio Cownwiicala ЦеЬ
- ^^ ^ Ш fi^ ^^ ^
TntTOfhirtio» Tnvpsring
Introduction
А new breakthrough m cold fusion technology!
Листинг4.6. Cold--Fusion.html
Листинг 4 . 7 . ТОС.html
Нмя Дейапвие
_Ь1апк Если в гипертекстовой ссылке в качестве целевого имени указывается
имя b l a n k , документ, на который указывается ссылка, отображается
в новом неименованном окне
_top Использование t o p в качестве целевого имени приводит к тому, что
документ, на к о т о р ы й указывает ссылка, занимает все окно броузера.
Несмотря на т о что такой документ не включается в конкретный
фрейм, считается, что Web-страница содержит ф р е й м ы
_parent Если в качестве целевого имени указано _ p a r e n t , документ распола
гается в области, занимаемой элементом FRAMESET, родительским по
отношению к данному документу. Если Web-страница не содержит
вложенных ф р е й м о в , то использование имени _ p a r e n t приводит к
тому же результат)^ что и использование имени _ t o p
_self Если в гипертекстовой ссылке в качестве целевого имени указывается
имя s e l f , документ отображается в текущем ф р е й м е . Присутствие
_ s e l f необходимо только в том случае, если это имя переопределяет
целевой ф р е й м , заданные! с помощью элемента BASE. Если выраже
ние <BASE TARGET="имя_фpeймa"> не задано, т о по умолчанию до
кумент, на к о т о р ы й указывает ссылка, выводится во ф р е й м е , содер
жащем эту ссылку
4.5. Разрешение типичных проблем... 125
Совет
В Internet Explorer 5.x вывод фрейма на печать происходит намного проще. После
выбора пункта Print меню File броузер предложит вам следующие действия на выбор:
• печать всех ф р е й м о в так, как они отображаются на экране;
• печать только выбранного фрейма;
• печать каждого ф р е й м а по отдельности.
Выбрав нужную опцию, вы можете вывести документ на печать в требуемом виде.
Для выбранных ф р е й м о в Internet Explorer 5.x поддерживает дополнительные опции
печати. Вы можете задать вывод на п р и н т е р всех связанных документов (при выборе
этой опции надо соблюдать осторожность), а также вывод таблицы ссылок.
Как автор Web-страницы вы можете создать ее так, чтобы уменьшить трудности,
возникающие при пользовании ею, в частности при выводе на печать. С атрибутом
o n C l i c k гипертекстовой ссылки (содержащей также атрибут TARGET) можно связать
JavaScript-код, который при активизации ссылки передавал бы фокус целевому фрейму.
Дополнительную информацию о JavaScript-сценариях вы найдете в главе 24. Кроме то
го, для печати пользователю можно предоставить составной документ. Это очень удоб
но в том случае, когда в состав Web-страницы входят много отдельных документов.
Использование JavaScript
Данный способ состоит в том, что автор подключает JavaScript-код с помощью ат
рибута o n C l i c k гипертекстовой ссылки. Фрагмент кода, обрабатывающий событие
o n C l i c k , может содержать любое число команд JavaScript, включая выражение
top .имя_фрейма. location = URL, с помощью которого во ф р е й м е отображается
новый документ. Таким образом мог)Т' обновляться любые ф р е й м ы , при этом не тре
буется изменять структуру документа верхнего уровня. Очевидно, что подобное ре
шение возможно только для броузеров, поддерживающих JavaScript. Подробно во
просы, связанные с JavaScript-кодом, обсуждаются в главе 24, здесь же мы рассмотрим
небольшой пример. В листинге 4.8 приведен HTML-код документа, содержащего один
ф р е й м в верхней строке и три ф р е й м а в нижней строке.
128 Глава 4. Фреймы
Листинг4.9. Top-Frame.html
швшашшва^ штт
?! 1^ -У 3 rii'^'ai <.!•rfа ш jjj
When selected on JavaScript-с ар able browsers, tins bi^:. will update ceil une and tliree below
StflMrtteneoudly - Hetsdape
fie £(* View £о Qomnurwc^arjd:^^:—^^^^^^^
When selected on JavaScnpt-capable browsers, tins 1шк will update cell one and three below.
4 . 6 . Встроенные фреймы
в Internet Explorer и Netscape б реализована возможность включать фреймы в со
став HTML-документа подобно тому, как в документ включаются изображения. Если
вы зададите высоту, ширину и тип выравнивания, встроенный, или плавающий, фрейм
займет определенную позицию в составе Web-страницы. Этим встроенные фреймы
отличаются от обычных фреймов, которые занимают фиксированную позицию в ок
не броузера. Встроенные фреймы удобно использовать для включения персональных
данных и другой информации, которая должна присутствовать в неизменном виде во
многих документах. Несмотря на то что встроенные фреймы предусмотрены специ
фикацией HTML 4.0, они реализованы только в Internet Explorer и Netscape 6. Более
ранние версии Netscape не позволяют использовать встроенные фреймы, но поддер
живают слои (layers), которые дают возможность решать подобные задачи. Чтобы
обеспечить соответствие HTML 4.0, в Netscape 6 была исключена поддержка слоев; об
этом следует помнить, разрабатывая Web-страницы. По адресу h t t p : / / s i t e s .
n e t s c a p e . n e t / e k r o c k / s t a n d a r d s . h t m l вы найдете сведения о том, как использо
вать встроенные фреймы и слои для работы с различными типами броузеров и для
обеспечения обратной совместимости.
Проиллюстрируем использование встроенных фреймов на следующем примере.
Предположим, некий профессор ведет целый ряд курсов, связанных с компьютерами.
В современных университетах программа курса и прочая информация для студентов
публикуется на Web-страницах. Поэтому профессор должен включать в каждый доку-
4.6. Встроенные фреймы 131
мент свое имя, адрес и другие сведения. Для того чтобы избежать лишней работы, он
создает специальный документ, содержащий контактную информацию. Код докумен
та показан в листинге 4.10.
Листинг 4.10.Contact-Info,html
<P>
Blah, blah, blah, algorithms. Yada, yada, yada, time. Blah,
blah, blah, space. Yada, yada, yada, iterative. Blah, blah,
blah, recurrences. Yada, yada, yard, data structures. Blah,
blah, blah, sorting. Yada, yada, yada, dynamic programming.
Blah, blah, blah, graph algorithms. Yada, yada, yada,
NP-Completeness.
<P>
<IFRAME SRC="Contact-Info.html" FRAMEBORDER=OX/IFRAME>
</BODY>
</HTML>
Теперь, если отобразить эту Web-страницу в окне Internet Explorer, контактная ин-
форхмация разместится в нижней части Web-страницы, как показано на рис. 4.9 и 4.10.
132 Глава 4. Фреймы
d
, Щ My CornpUe»
m^^
Рис. 4.9. Верхняя часть документа c s - 4 0 l . h t m l : встроенный фрейм
не отображается
тттшчзу •
Blah, blah, blah, algonthntis. Yada, yada, yada, time. Blah, blah, blah, space. Yada. yada, yada.
Iterative. Blah, blah, blah, recurrences. Yada, yada, yard, data structures Blah, blah, blah, sorting
Yada, yada. yada, dynamic programming Blah, blah, blah, graph algorithms. Yada, yada, yada. I n
completeness.
jd
; ^ Done"" i i ^ My Computer
SRC
Атрибут SRC определяет URL документа, который должен отображаться во встро
енном фрейме.
4.6. Встроенные фреймы 133
WIDTH и HEIGHT
Эти атрибуты задают размеры плавающего ф р е й м а в пикселях. Значения в про
центах не допускаются. Автор может не указывать данные атрибуты, в таком слу
чае броузер самостоятельно вычисляет размеры фрейма.
ALIGN
Атрибут ALIGN задает тип выравнивания ф р е й м а относительно окружающего тек
ста. Данный атрибут интерпретируется как и атрибут ALIGN для встроенного изо
бражения. Допустимыми значениями являются LEFT, RIGHT, CENTER, TOP, BOTTOM
и MIDDLE.
NAME
Плавающие ф р е й м ы , как и обычные, могут задаваться в качестве целевых для ги
пертекстовых ссылок. Для этой цели фрейму присваивается имя с помощью атри
бута NAME.
FRAMEBORDER
Атриб)п: FRAMEBORDER определяет, должно ли отображаться обрамление вокруг
плавающего фрейма. Значение FRAMEB0RDER=1 указывает на то, что обрамление
должно отображаться, а значение FRAMEBORDER=0 соответственно запрещает вы
вод обрамления. П о )^1олчанию обрамление выводится.
MARGINWIDTH
Атрибут MARGINWIDTH задает ширину правой и левой границ в пикселях.
MARGINHEIGHT
Атрибут MARGINHEIGHT задает высот)^ верхней и нижней границ в пикселях.
SCROLLING
Атрибут SCROLLING указывает на то, что полоса прокрутки должна выводиться
(SCROLLING="YES"), либо запрещает вывод полосы прокрутки (SCROLLING="NO").
LONGDESC
Атрибут LONGDESC задает URI подробного описания ф р е й м а и в основном исполь
зуется в невизуальных броузерах.
4.7. Резюме
Фреймы являются важным дополнением к HTML 4.0 и поддерживаются большин
ством современных броузеров. Элемент FRAMESET делит окно либо текущий ф р е й м
на несколько прямоугольных областей, с которыми связываются HTML-документы.
Для связи документов с областями используется элемент FRAME. Гипертекстовые
ссылки, ф о р м ы и Java-аплеты могут ссылаться на ф р е й м ы , используя имена, опреде
ленные пользователем, либо стандартные имена. Для того чтобы минимизировать
134 Глава 4. Фреймы
В этой главе...
E x t e n s i b l e Stylesheet L a n g u a g e
http://www.w3.org/Style/XSL/
5 . 1 . Правила стилей
Для управления HTML-элементами используются правила стилей. О б ы ч н о правила
стилей располагаются в отдельном текстовом файле, на который ссылается элемент
LINK, находящийся в разделе HEAD документа. Правила стилей могут также разме
щаться непосредственно в разделе HEAD HTML-документа и даже в теле Web-
страницы. Правила стилей задаются в следующем виде:
селектор { свойство: значение ]
или
селектор { свойство!: значение!;
СВ0ЙСТВ02: значение2;
СВОЙСТВОМ: значением; }
Если в составе одного селектора определяется несколько свойств, свойства отде
ляются друг от друга точкой с запятой. За последним свойством точка с запятой мо
жет не ставиться.
В этой главе будут рассмотрены различные типы селекторов. Самый простой се
лектор представляет собой имя HTML-элемента и означает, что свойства, указанные в
фигурных скобках, должны применяться ко всем экземплярам этого элемента, при
сутствующим в составе документа. Свойства и их значения описаны ниже в этой главе.
Рассмотрим простой HTML-документ, код которого представлен в листинге 5.L
Внешний вид документа показан на рис. 5.L
Листинг5.1. F i z z i c s l . h t m l
Если в раздел HEAD документа включить приведенный ниже фрагмент кода, доку
мент будет выглядеть так, как показано на рис. 5.2. Для того чтобы броузеры, не под
держивающие CSS, не отображали текст между дескрипторами <STYLE> и </STYLE>,
этот текст о ф о р м л е н как комментарии.
<STYLE TYPE="text/css">
<! —
BODY { background: URL(images/confetti-background.jpg) }
HI { text-align: center;
font-family: Blackout }
H2 { font-family: MeppDisplayShadow }
STRONG { text-decoration: underline }
— >
</STYLE>
140 Глава 5. Каскадные листы стилей
М е т о д и к а профессионалов
Листинг 5.2.Sitestyle.ess
^9
/* Пример внешнего листа стилей */
HI { text-align: center;
font-family: Arial
}'
H2 { color: #440000;
text-align: center;
font-family: Arial Black, Arial, Helvetica, sans-serif
}
TYPE
Атрибут TYPE является обязательным. Он определяет формат, в котором представ
лены правила. Для каскадных листов стилей задается тип " t e x t / e s s " . Для листов
стилей JavaScript значением атрибута TYPE должно быть " t e x t / j а va s c r i p t " .
142 Глава 5. Каскадные листы стилей
MEDIA
В настоящее время атрибут MEDIA не поддерживается ни Netscape, ни Internet
Explorer. Основное назначение данного атрибута— определять устройство, для
которого должны применяться наборы правил. Предполагается, что в будущем с
документом будут связываться различные наборы правил для различных сред вос
произведения. Допустимыми значениями атрибута MEDIA являются ALL, AURAL,
BRAILLE, HANDHELD, HELD, PRINT, PROJECTION, SCREEN (значение n o умолча
нию), SPEECH, TTY и TV.
HI { t e x t - a l i g n : c e n t e r ;
font-family: Arial }
—>
</STYLE>
эквивалентно
<STYLE T Y P E = " t e x t / j a v a s c r i p t " >
<!--
tags.HI.textAlign="center";
tags.HI.fontFamily="Arial";
//—>
</STYLE>
Стандартные листы стилей более универсальны, однако при работе с броузером
Netscape листы стилей JavaScript позволяют не только использовать статические зна
чения, но и вычислять их. Подробно язык JavaScript рассматривается в главе 24.
5.3. Селекторы
Для определения правил стилей в состав элемента STYLE включается элемент,
представленный в следующем виде:
селектор { свойство!: значение!; ...; свойством: значением }
Д о сих п о р мы рассматривали примеры, в которых селекторы представляли собой
имена HTML-элементов и правила применялись ко всем вхождениям указанного эле
мента в документ. П р и этом стили, связанные с данным элементом, переопределя
лись. Так, например, чтобы указать, что текст, содержащийся в составе элемента
STRONG, должен отображаться полужирным шрифтом, размер которого на 50% пре
вышает размер по умолчанию, надо задать следующее выражение:
STRONG { font-weight: bold; font-size: 150% }
Однако типы селекторов не ограничиваются именами HTML-элементов. Каскад
ные листы стилей также поддерживают селекторы, которые применяются только в
конкретных ситуациях. Н и ж е перечислены четыре наиболее часто применяющихся
типа селекторов:
• HTML-элементы;
• классы, определенные пользователем;
• идентификаторы, определенные пользователем;
• псевдоклассы якоря.
Для указания правил, применяющихся только в определенных условиях, исполь
зуются атрибуты CLASS, ID и STYLE, которые допустимы для всех элементов за ис
ключением BASE, BASEFONT (атрибут ID разрешен), HEAD, HTML, МЕТА, PARAM
(атрибут ID разрешен), SCRIPT, STYLE и TITLE. Кроме того, спецификация HTML
4.0 определяет элемент SPAN, с помощью которого стили могут применяться к произ
вольно выбранным разделам документа.
HTML -элементы
Любой HTML-элемент может быть использован в качестве селектора, однако эле
мент BR не содержит текст, следовательно, применение к нему правил бессмысленно.
Свойства, установленные с помощью правил, наследуются, например цвет ф о н а для
элемента BODY применяется также и к абзацам в теле документа, а размер шрифта, за
данный для элемента Р, применяется к содержимому элемента CODE внутри абзаца и т.
д. Передача свойства вложенным элементам продолжается до тех пор, пока это свой
ство не будет переопределено. Н а п р и м е р , чтобы задать синий цвет для всего текста
за исключением заголовка первого уровня, который должен отображаться красным
цветом, надо указать следующие правила:
144 Глава 5. К а с к а д н ы е листы стилей
BODY { c o l o r : b l u e }
HI { c o l o r : r e d }
Ч т о б ы задать одинаковые стили для нескольких элементов, их надо объединить в
список. Элементы внутри списка разделяются запятыми. Н и ж е приведен п р и м е р ус
тановки свойств для заголовков различных уровней.
HI, Н2, НЗ, Н4, Н5, Нб { text-align: center;
font-family: sans-serif }
Элемент, содержащийся в составе другого элемента, приобретает свойства вклю
чающего элемента. Предположим, что для различных элементов стили задаются сле-
д)^ющим образом:
BODY { color: blue }
HI { color: green }
EM { color: red }
В данном примере стиль c o l o r : b l u e , заданный для элемента BODY, наследуется
всеми элементами HTML-документа (Р, UL, 0L, TABLE и т.д.). Поэтому документ будет
отображаться синим цветом за исключением элементов, для которых цвет переопре
делен, т.е. HI и ЕМ. В данном примере возникает следующая проблема: если элемент
ЕМ прис)а'ствует в составе элемента HI, цвет выделенного текста отличается от цвета
остальной части заголовка. Ч т о б ы это не происходило, необходимо добавить прави
ло, указывающее на то, что выделенр1ый текст в составе заголовка первого уровня
должен отображаться зеленым цветом.
HI ЕМ { c o l o r : green }
Используя CSS при создании документа, следует помнить, что в броузерах Netscape
4.x имеются н е к о т о р ы е ошибки, связанные с листами стилей. Так, например, иногда
стили некорректно наследуются вложенными контеР1нерами. Чтобы избежать неже
лательных последствий при отображении документов с помощью этих броузеров, же
лательно явным образом определять стили для вложенных контейнеров либо приме
нять классы, определяемые пользователем.
Внимание!
Теперь, чтобы использовать класс, надо указать имя класса в качестве значения
атрибута CLASS соответствующего элемента Р. Фрагмент документа, в котором ис
пользуется "абстрактный" абзац, выглядит следующим образом:
<Hl>New Advances in Physics</Hl>
<P CLASS="abstract">
This paper gives the solution to three previously unsolved
problems: turning lead into gold, antigravity, and a
practical perpetual motion machine.
CSS позволяет определять классы, применимые ко всем HTML-элементам. Такой
класс надо объявлять без указания имени элемента перед именем класса. Например,
следующее выражение определяет класс, в котором задается синий цвет переднего
плана и полужирный шрифт:
.blue { color: blue; font-weight: bold }
Этот стиль может быть использован в уже существующем абзаце
This text is in the default color, but
<SPAN CLASS="blue">this text is blue.</SPAN>
либо применен к целому блоку.
<Н2 CLASS="blue">A Blue Heading</H2>
Заметьте, что в именах классов, определенных пользователем, Netscape не под
держивает символ подчеркивания. Так, например, Netscape не будет интерпретиро
вать . b l u e _ f o n t как стиль.
Внимание!
<P ID="foo">
</BODY>
В большинстве случаев классы предпочтительнее идентификаторов.
146 Глава 5. Каскадные листы стилей
Псевдоклассы якоря
Поскольку в языке HTML для определения гипертекстовой ссылки предусмотрен
единственный элемент (элемент А, который п р и н я т о называть якорем), он использу
ется независимо от того, была ли ссылка просмотрена ранее или выбрана в настоя
щий момент. Стандарт CSS1 позволяет определять свойства отдельно для каждого ти
па ссылки. Для указания типа ссылки используются следующие селекторы.
A:link, и л и :link
Этот селектор определяет ссылку только в том случае, если она не была просмот
рена раньше. Броузер определяет, посещалась ли ссылка раньше, на основании
списка предыстории.
A:visited, и л и rvisited
Д а н н ы й селектор соответствует только тем ссылкам, которые не посещались
раньше.
А:active, и л и :active
Этот селектор определяет, как должна отображаться выбранная ссылка (ссылка
считается выбранной до отпускания кнопки мыши).
Aihover, и л и :hover
Этот селектор поддерживается только Internet Explorer. Он применяется к ссылке,
на которую указывает курсор мыши.
Псевдоклассы могут объединяться с другими селекторами. Н а п р и м е р , следующее
правило применяется только к выбранной ссылке и только в том случае, если она
входит в состав элемента указанного класса:
.bizarre lactive { font-size: 300% }
Приведенное ниже правило применимо к изображению, оформленному в виде ги
пертекстовой ссылки. Правило применяется до тех пор, пока ссылка не будет активи
зирована.
А:link IMG { border: solid green }
font-weight
normal I lighter | bold | bolder 110012001... 1900
Этот стиль определяет вес шрифта и задается числовыми значениями от 100
(минимальный) до 900 (максимальный) с шагом 100. Кроме того, могут быть исполь
зованы символьные обозначения: normal, l i g h t e r , bold и b o l d e r . Например:
HI { font-weight : 200 }
Н2 { font-weight : bolder }
Netscape не поддерживает значение b o l d e r .
font-style
normal I italic | oblique
Это свойство выбирает тип шрифта в составе конкретного семейства шрифтов.
Допустимыми значениями являются normal, i t a l i c и o b l i q u e .
Р { font-style : normal }
ТН { f o n t - s y t l e : italic }
Netscape не поддерживает значение o b l i q u e .
font-size
pt, pc, in, cm, mm | em, ex, px, % |
xx-large I x-large | large | medium | small | x-small | xx-small |
smaller | larger
Данный стиль определяет размер шрифта. Значение задается в стандартных еди
ницах длины (см. табл. 5.1), с помощью символьных имен либо в процентах. Сим
вольные значения могут быть абсолютными ( x x - l a r g e , x - l a r g e , l a r g e , medium,
s m a l l , x - s m a l l , x x - s m a l l ) или относительными ( s m a l l e r или l a r g e r ) . Значе
ние в процентах вычисляется относительно размера шрифта в контейнере. На
пример, следующее выражение означает, что текст в составе элемента STRONG
должен быть на 50% больше текущего размера шрифта:
STRONG { font-size: 150% }
Ниже приведены примеры использования свойства f o n t - s i z e .
Р { f o n t - s i z e : 14pt }
Р { f o n t - s i z e : 1cm }
Р { font-size: xx-large }
Для того чтобы броузер Netscape распознавал стили, необходимо между числовой
величиной и обозначением единиц измерения вставлять пробел, т.е. вместо
" 14 р t" надо задавать "14 р t".
font-family
имя семейства шрифтов
Данное свойство определяет начертание шрифтов. Например, в листинге 5.3 при
веден пример простой Web-страницы; ее внешний вид показан на рис. 5.3.
5.5. Свойства шрифтов 149
Archery
Arts and Crafts
Horseback Riding
Hiking
Campfire Song Times
C++ Programming
Рис. 5.3. Web-страница Bear Claw со
стандартными шрифтами
Листинг 5 . 5 . C a m p B e a r C l a w . c s s
HI { text-align: center;
font-family: Funstuff }
H2.archery { font-family: ArcheryDisplay }
H2.arts { font-family: ClampettsDisplay }
H2.horseback { font-family: Rodeo }
H2.hiking { font-family: SnowtopCaps }
H2.campfire { font-family: Music Hall }
H2.java { font-family: Digiface }
. о • QD a (й m- 3 M ч1
"Ш
C^Xhf Bear CUw
We have the following activities:
HORSEBACK: RIDIHC
И1К11Ю
JRVR PR05RRmmin5
Dom
Ш: Рис, 5.4. Web-страница Bear Claw со
font-variant
normal I small-caps
Данное свойство применяется для отображения текста малыми прописными бук
вами. Допустимыми значениями являются normal и s m a l l - c a p s . Internet
Explorer отображает s m a l l - c a p s обычными прописными буквами. Netscape не
поддерживает это свойство.
font
Свойство f o n t позволяет объединять свойства f o n t - w e i g h t , f o n t - v a r i a n t ,
f o n t - s t y l e , f o n t - s i z e , l i n e - h e i g h t и f o n t - f a m i l y в одной записи. Компо
ненты значения могут не указываться, но если они присутствуют, то должны сле
довать в определенном порядке и разделяться пробелами. Исключение составляют
значения f o n t - s i z e и l i n e - h e i g h t , которые разделяются косой чертой ("/")•
Например, код
Р { f o n t - w e i g h t : demi-bold;
font-style: i t a l i c ;
f o n t - s i z e : 14pt;
l i n e - h e i g h t : 150%;
f o n t - f a m i l y : Times, s e r i f }
можно заменить выражением
P { f o n t : demi-bold i t a l i c 14pt/150% Times, s e r i f }
152 Глава 5. Каскадные листы стилей
fontdef
Поддержка динамических ш р и ф т о в реализована как расширение CSSI. П р и этом с
HTML-документом связывается файл ш р и ф т о в . Для работы с динамическими
шрифтами в Netscape может быть использован как стиль f o n t d e f ,
<STYLE TYPE="text/css">
<! —
@fontdef URL(http://.../font-file.pfr);
-->
</STYLE>
так и элемент LINK, расположенный в разделе HEAD документа.
<LINK REL="fontdef"
SRC="http://.../font-file.pfr">
После связывания документа с файлом . p f r динамически загружаемые ш р и ф т ы
можно использовать как обычные ш р и ф т ы . Internet Explorer не поддерживает
ф о р м а т p r f , однако компания Bitstream выпустила управляющий компонент
ActiveX, позволяющий Internet Explorer обрабатывать файлы . p f r . Дополнитель
ная и н ф о р м а ц и я о динамических ш р и ф т а х находится по следующим адресам:
http://www.truedoc.com/webpages/intro/
http://www.bitstream.com/
Там же вы найдете свободно распространяемые ф а й л ы шрифтов.
font-face
Для поддержки динамически загружаемых ш р и ф т о в Internet Explorer использует
свойство f o n t - f a c e , определенное в Style Sheets, Level 2 ( h t t p : / / w w w . w 3 . o r g /
T R / R E C - C S S 2 / f o n t s . h t m l # f o n t - d e s c r i p t i o n s ) . Для того чтобы задать дина
мический ш р и ф т для Internet Explorer, используется код наподобие следующего:
<STYLE TYPE="text/css">
<! —
@font-face {
font-family: fontname;
font-style: normal;
font-weight: normal;
src: url(http://.../font-file.eot)
}
</STYLE>
Заметьте, что Internet Explorer и Netscape работают с различными форматами
файлов ш р и ф т о в . Internet Explorer использует ф о р м а т e o t , а Netscape — p f r . Для
создания файлов . e o t Microsoft предоставляет инструмент Web E m b e d d i n g Fonts
Tool (WEFT). П р и м е р ы динамических ш р и ф т о в Microsoft находятся по адресу
http://www.microsoft.com/typography/
С этого же узла можно скопировать свободно распространяемую программу WEFT
Version 2.
5.6. Свойства для определения фона и переднего плана 153
color
имя_цвета \ #RRGGBB | #RGB | rgb(rrr, ggg, bbb) | rgb(rrr%, ggg%. bbb%)
Данное свойство определяет цвет текста или цвет переднего плана для раздела доку
мента. Для определения цвета используются стандартные значения (см. табл. 5.2).
Ниже приведены примеры использования свойства c o l o r .
р { color blue }
HI { color #OOAABB }
Н2 { color #OAB }
НЗ { color rgb(255, 0, 0 ) } /* red -^f
Н4 { color rgb(0, 0, 255 ) } /^ blue */
background-color
transparent |
имя_цвета \ #RRGGBB | #RGB | rgb(rrr, ggg, bbb) | rgb(nT%, ggg%, b b b % )
Данное свойство задает цвет ф о н а для раздела документа. Для определения цвета
используются стандартные значения, кроме того, чтобы задать отображение пер
воначального цвета сквозь п р о з р а ч н ы й фон, можно использовать ключевое слово
transparent.
background-image
n o n e I иг\{имя_файла)
Данное свойство определяет изображение, которое может быть использовано в ка
честве фона для раздела документа. На тот случай, если файл с изображением недос
тупен либо если в броузере запрещена загрузка изображений, автор документа может
также задать цвет фона. Следующее выражение задает фоновое изображение:
Н2 { background-image: url(Bluedrop.gif);}
background-repeat
repeat | repeat-x | repeat-y | norepeat
Данное свойство может приобретать значения r e p e a t , r e p e a t - x , r e p e a t - y или
n o r e p e a t и соответственно означает, что вывод изображения повторяется в двух
направлениях, только по оси х, только по оси у, либо отображается один раз и не
может повторяться. Ниже приведен пример использования свойства b a c k g r o u n d -
repeat.
154 Глава 5. Каскадные листы стилей
BODY {
background-image: url(Bluedot.gif);
background-repeat: repeat-x;
background-attachment
scroll I fixed
Данное свойство определяет, должно ли фоновое изображение прокручиваться
вместе с содержимым документа (значение s c r o l l ) либо оставаться неподвиж
ным (значение f i x e d ) . Данное свойство не поддерживается Netscape.
background-position
[ top I center | bottom] [ left | center | right ] |
[ pt, pc, in, cm, mm ] [ pt, pc, in, cm, mm ] |
[ em, ex, px, % ] [ em, ex, px, % ]
Свойство b a c k g r o u n d - p o s i t i o n задает позицию фонового изображения отно
сительно верхнего левого края области. Для данного свойства обычно задаются
два значения, разделенные пробелами. Указанные значения уточняются посредст
вом ключевых слов l e f t / c e n t e r / r i g h t , t o p / m i d d l e / b o t t o m , знака процента
и обозначения единицы длины (см. табл. 5.1). Так, например, 50% означает, что
центр изображения должен располагаться в центре области. Значение 25рх по го
ризонтали указывает на то, что левая граница изображения должна отступать на
25 пикселей от левой границы области. Если вместо двух значений задано одно,
считается, что указана позиция по горизонтали, а позиция по вертикали принима
ется равной 50%. По умолчанию принимается значение "0% 0%". Отрицательные
значения также поддерживаются, в этом случае считается, что изображение вы
ступает за границы раздела. Ниже приведены примеры использования свойства
background-position.
BODY { background-image: url(Marty.jpg);
background-position: 10% 10%; }
HI { background-image: Bluedrop.gif;
background-position: center; } /* 50% 50% */
background
Свойство background позволяет объединять свойства b a c k g r o u n d - c o l o r , b a c k
ground-image, b a c k g r o u n d - r e p e a t , b a c k g r o u n d - a t t a c h m e n t и b a c k g r o u n d -
p o s i t i o n в одной записи.
В качестве примера рассмотрим листинги 5.6 и 5.7, которые содержат код Web-
страницы. Заголовок отображается на фоне, имитирующем деревянные панели.
Формат изображения повторяется по горизонтали. Внешний вид Web-страницы в ок
не броузера Netscape Communicator 4.7 показан на рис. 5.5.
5.6. Свойства для определения фона и переднего плана 155
ШЕВШШВШШ
ltki>'M^mail.,.nM.
Welcome to Joe's Cabinets. We specialize in
• Custom Cabinets ,
• Kitchen Remodebng
word-spacing, letter-spacing
normal I + / - pt, pc, in, cm, m m | + / - em, ex, px
Данные свойства изменяют расстояния между словами и между символами, приня
тые по умолчанию. Для указания расстояния используются стандартные единицы
длины (см. табл. 5.1) либо ключевое слово n o r m a l . Числовые значения мог)т быть
либо положительными (указанная величина добавляется к стандартному расстоя
нию), либо отрицательными (заданная величина вычитается из стандартного рас
стояния). Свойство w o r d - s p a c i n g не поддерживается ни Netscape, ни Internet
Explorer. Кроме того, Netscape не поддерживает свойство l e t t e r - s p a c i n g .
text-decoration
n o n e I underline | overline | line-through | blink
Свойство t e x t - d e c o r a t i o n описывает дополнительные элементы текста. Допус
тимыми значениями являются п о п е , u n d e r l i n e , o v e r l i n e , l i n e - t h r o u g h и
b l i n k . Например, если вы хотите, чтобы гипертекстовые ссылки отображались
синим цветом, но без подчеркивания, а текст абзаца выводился с подчеркиванием,
надо задать следующие выражения:
А:link { coloriblue; text-decoration: none }
P { text-decoration: underline }
Заметьте, что Internet Explorer не поддерживает значение b l i n k , a Netscape не
поддерживает значение o v e r l i n e .
vertical-align
top I bottom I baseline | middle | sub | super | text-top | text-bottom | %
Данное свойство определяет позиционирование элементов по вертикали. Значение,
заданное в процентах (положительное или отрицательное), определяет смещение
базовой линии элемента от базовой линии родительского элемента. Кроме того,
значение может задаваться посредством символьных имен. Допустимыми символь
ными именами являются t o p (выравнивание верхней части данного элемента по
верхней части самого высокого элемента строки), b o t t o m (выравнивание нижней
части данного элемента по нижней части самого низкого элемента строки), b a s e
l i n e (выравнивание базовой линии данного элемента по базовой линии родитель
ского элемента), m i d d l e (выравнивание середины элемента по половине расстоя
ния над базовой линией родительского элемента), s u b (представление элемента как
нижнего индекса), s u p e r (представление элемента как верхнего индекса), t e x t - t o p
(выравнивание верхней границы по верху шрифта родительского элемента), t e x t -
b o t t o m (выравнивание нижней границы по низу шрифта родительского элемента).
5-7- Текстовые свойства 157
text-transform
n o n e I uppercase | lowercase | capitalize
Данное свойство определяет, должно ли выполняться преобразование текста в сим
волы верхнего регистра ( u p p e r c a s e ) , в символы нижнего регистра ( l o w e r c a s e ) и
следует ли начинать каждое слово с прописной буквы ( c a p i t a l i z e ) .
text-align
left I right I center [justify
Данное свойство задает выравнивание абзаца по левой границе, по центру, по
правой границе и по обеим границам.
text-indent
+ / - pt, рс, in, cm, mm | + / ~ em, ex, px, %
Данное свойство задает отступ первой строки абзаца. Отступ отсчитывается от ле
вой границы, определенной посредством свойства m a r g i n - l e f t . Значения зада
ются в стандартных единицах длины либо вычисляются в процентах от ш и р и н ы
родительского элемента. По умолчанию принимается значение 0. Отрицательная
величина означает, что первая строка выступает за левую границу. Например:
Р { text-indent: -25рх } /* Выступ */
line-height
normal I число \ pt, рс, in, cm, mm | em, ex, px, %
Данное свойство задает высоту строки — расстояние между базовыми линиями
двух последовательно расположенных строк абзаца. Значение может быть задано в
стандартных единицах длины, а также в процентах от размера шрифта. Например:
.double { line-height: 200% }
.triple { line-height: 3 } /* Зх the font size */
DIV { line-height: 1.5em }
white-space
normal I pre | nowrap
Свойство w h i t e - s p a c e определяет особенности интерпретации пробелов, сим
волов табуляции, возврата каретки и новой строки в пределах элемента. Допусти
мыми значениями являются n o r m a l (преобразование нескольких последователь
но расположенных пробелов в один пробел), p r e (пробелы интерпретируется так
же, как в элементе PRE) и n o w r a p (перевод строки осуществляется только посред
ством элемента BR). Броузер Netscape не распознает значение n o w r a p ; Internet
Explorer вовсе не поддерживает свойство w h i t e - s p a c e .
В качестве примера рассмотрим Web-страницу, которая должна выглядеть как де
ловое письмо. Исходный код этой Web-страницы представлен в листинге 5.8. Рас
стояние между абзацами уменьшено с помощью следующего выражения:
Р { margin-top: 5рх }
Для даты, адреса получателя и отправителя определены классы абзацев, выров
ненные по правой ( r h e a d ) и левой ( I h e a d ) границам. Основное содержание доку-
158 Глава 5. Каскадные листы стилей
Листинг 5 . 8 . B a t e s . html
P { margin-top: 5px }
P.rhead { text-align: right;
margin-right: O.Sin;
font-family: sans-serif }
P.lhead { font-family: sans-serif }
P.body { text-align: justify;
text-indent: 0.5in }
P.foot { margin-left: 60%;
line-height: 300% }
5.8. Свойства блоков с обрамлением 159
April 1,2001
"3
VViiliam A. Bates
Macrosoft Софогайоп
Blumood.WA 12345 f
Internal Revenue Service
Philadelphia, PA 67890
Dear Sirs,
I am writing to inform you that, due to financial difficulties, I wiD be unable to
pay ray taxes this year.
You see, my company has had reduced profits this year. In fact gross
revenues have now dropped bdow the GDP of twelve foreign countries! Given this
intolerable situation, I am sure you will understand
Sincerely,
Williain A. Bates
zl
i^Oone ( ^ My Computer
I ш1 ^
^Щ^^^^^Лм!
-^Done ^ ^ My Computer
Границы
Границы представляют собой зарезервированное пространство вокруг элемента, в
пределах которого отображается цвет фона или ф о н о в о е изображение. Для перекры
вающихся абзацев могут быть заданы отрицательные границы.
Обрамление
Обрамление элемента представляет собой зарезервированную область, в пределах
которой отображается заданный цвет ф о н а или ф о н о в о е изображение. Обрамление
отображается внутри границ. Размеры обрамления могут быть нулевыми, но не могут
быть отрицательными.
5.8. Свойства блоков с обрамлением 161
border-width
none I thin | medium | thick |
pt, pc, in, cm, mm | em, ex, px
Данное свойство позволяет в одной записи задавать величины b o r d e r - w i d t h -
top, b o r d e r - w i d t h - r i g h t , border-width-bottom и b o r d e r - w i d t h - l e f t
(значения задаются в указанной последовательности). Если задано только одно
значение, оно применяется для определения всех четырех частей обрамления. Ес
ли заданы два или три значения, недостающая величина принимается равной раз
меру противоположной части. Например, в приведенном ниже выражении для
верхней и нижней частей обрамления принимается значение medium, а для пра
вой и левой частей — значение t h i n .
DIV { b o r d e r - w i d t h : medium t h i n }
border-color
имя_цвета \ #RRGGBB | #RGB | rgb(rrr, ggg, bbb) | rgb(rrr%, ggg%, bbb%)
Данное свойство задает цвета различных частей обрамления. Подобно b o r d e r -
width, для данного свойства указываются четыре значения, которые определяют
характеристики соответственно верхней, правой, нижней и левой частей обрам
ления. Способы определения значений цветов описаны в табл. 5.2. Например:
Р { border-style: solid;
b o r d e r - c o l o r : b l a c k gray gray b l a c k ;
}
border-style
none I dotted | dashed | solid | double | groove | ridge | inset | outset
Данное свойство задает способ отображения обрамления. Для него могут быть зада
ны от одного до четырех значений, определяющих, подобно b o r d e r - w i d t h , харак
теристики верхней, правой, нижней и левой частей обрамления. Допустимыми яв
ляются значения попе, d o t t e d , dashed, s o l i d , double, groove, r i d g e , i n s e t и
o u t s e t . В областях обрамления, не заполненных цветом переднего плана, отобра
жается цвет фона или фоновое изображение включаемого элемента. Значения
dashed и d o t t e d не поддерживаются ни Netscape, ни Internet Explorer. Следует за
метить, что Netscape не поддерживает свойства b o r d e r - s t y l e ; соответствующие
значения должны задаваться посредством свойства border. Например,
162 Глава 5. Каскадные листы стилей
Р { border-sytle: ridge }
не распознается Netscape; вместо этого следует задать следующую конструкцию:
Р { border: ridge }
Internet Explorer корректно обрабатывает оба выражения.
border
Данное свойство определяет размеры, стиль и цвет для всех четырех частей об
рамления. Например, сплошное обрамление черного цвета шириной в четверь
дюйма, показанное на рис. 5.7, задается с помощью следующего выражения:
border: 0.25in s o l i d black
Заполненная область
Заполненная область— это зарезервированное пространство между включаемым
элементом и обрамлением. В нем отображается цвет фона или фоновое изображение,
заданное для элемента. Размеры заполненной области не могут быть отрицательными.
padding
Данное свойство позволяет задавать размеры верхней, правой, нижней и левой
частей заполненной области в рамках одной записи. Если для свойства padding
указано только одно значение, оно применяется для всех четырех частей области.
Если же заданы два или три значения, недостающий размер принимается равным
размеру противоположной части. Например, заполненная область шириной чет
верть дюйма, показанная на рис. 5.7, задается с помощью следующего выражения:
padding: 0.25in
5.9. Изображения и плавающие элементы 163
display
block I inline | list-item | none
Данное свойство определяет, должен ли элемент отображаться в составе ограни
ченного блока, выводиться как абзац, подобно элементам Р или PRE, либо должен
быть представлен как встроенный блок в составе другого блока. Допустимыми
значениями являются b l o c k , i n l i n e , l i s t - i t e m и none. Значение l i s t - i t e m
интерпретируется как b l o c k , за исключением того, что к пункту списка добавля
ется маркер.
width, height
auto I pt, pc, in, cm, mm | em, ex, px
Данные свойства задают фиксированные размеры элемента и обычно применяют
ся к изображениям. Значения указываются в стандартных единицах длины, кроме
того, в качестве значения может быть использовано ключевое слово a u t o . Напри
мер, тип "bullet" задается следующим образом:
IMG.bullet { width: 50рх; height: 50рх }
Ключевое слово a u t o применяется к изображениям, для которых задана либо ши
рина, либо высота. Оно означает, что изображение должно быть масштабировано
с сохранением соотношения между исходной шириной и высотой.
float
none I left I right
Данное свойство располагает плавающие элементы по левой или правой границе с
обтеканием текста. Часто это свойство используется для выделения прописных
букв и для размещения плавающих изображений. Например, в листинге 5.10 пока
зан код документа, в котором выделяется прописная буква "Т" размером 75 пунк
тов. Внешний вид документа показан на рис. 5.8.
164 Глава 5. Каскадные листы стилей
Листинг5.10. Psalm23.html
шшшшшшв
file g(M ifiew fio £ofwnunic«ioi НФ
T
shepherd; I shall not
want. He maketh me to
lie down in green
pastures: he leadeth me
beside the still waters. He
restoreth my soul he
leadeth me in the paths of
righteousness for his name's sake
Yea, though I walk through the
уаДеу of the shadow of death, I will »j Рис. 5.8. Свойство f l o a t может быть
использовано для выделения прописных букв
clear
none I left I right | both
Данное свойство определяет, допустимы ли плавающие элементы слева или справа
от элемента. В качестве значений могут быть указаны l e f t (продолжить вывод
ниже плавающего элемента, расположенного слева), r i g h t (продолжить вывод
5.10. Свойства списков 165
T
shepherd; I shall not shepherd; I shall not
^^^
•want.
He maketh me to lie
down m green pastures:
T want.
list-style-image
n o n e I иг\{гшя_файла)
Данное свойство позволяет задавать новые маркеры для списков. Используя это
свойство, следует помнить, что оно поддерживается только Internet Explorer. В ка
честве значения задается URL либо ключевое слово попе. П р и м е р ы использования
l i s t - s t y l e - i m a g e приведены ниже. Первое выражение устанавливает в качестве
маркера по умолчанию для маркированного списка изображение, содержащееся в
файле d i a m o n d . g i f . Второе выражение задает класс s t a r , для которого маркиро
ванные списки помечаются маркером в виде звездочки (файл s t a r . g i f ) .
UL { l i s t - s t y l e - i m a g e : u r l ( d i a m o n d . g i f ) }
UL.star { l i s t - s t y l e - i m a g e : u r l ( s t a r . g i f ) }
166 Глава 5. Каскадные листы стилей
list-style-type
n o n e I disc | circle | square | decimal | upper-alpha | lower-alpha | upper-roman |
lower-roman
Д а н н о е свойство устанавливает маркер для списка в том случае, когда задано зна
чение п о п е свойства l i s t - s t y l e - i m a g e (оно принимается по умолчанию для 0L
и DL). Допустимыми значениями являются d i s c (закрашенный круг), c i r c l e
(незакрашенный круг), s q u a r e , d e c i m a l (1, 2, 3 и т.д.), u p p e r - a l p h a (А, В, С
и т.д.), l o w e r - a l p h a (а, Ь, с и т.д.), u p p e r - r o m a n (I, II, III и т.д.), l o w e r - r o m a n (i,
ii, iii и т.д.) и n o n e .
list-style-position
outside I inside
Д а н н о е свойство, допустимыми значениями которого являются o u t s i d e (по
умолчанию) и i n s i d e , указывает, должен ли маркер располагаться в пределах аб
заца ( i n s i d e ) или выступать влево ( o u t s i d e ) . Н и Netscape, ни Internet Explorer
не поддерживают свойство l i s t - s t y l e - p o s i t i o n .
list-style
Д а н н о е свойство позволяет задавать значения l i s t - s t y l e - i m a g e , list-style-
t y p e и l i s t - s t y l e - p o s i t i o n в одной записи.
Единицы длины
Каскадные листы стилей дают возможность автору указывать размеры, используя
единицы длины, описанные в табл. 5.1.
Окончание табл. 5 . 1 .
in Дюймы (абсолютная единица)
пил Миллиметры (абсолютная единица)
рс Пика; в дюйме 6 пика; в пика 12 пунктов (абсолютная единица)
pt Пункты; в дюйме 72 пункта (абсолютная единица)
рх Пиксели (относительная единица)
Цвет
Каскадные листы стилей позволяют задавать цвет любым из способов, описанных
в табл. 5.2.
5.12. Слои
Netscape 4 поддерживает средство, которое п р и н я т о называть слоями. Слои по
зволяют размещать элементы разметки в отдельных прямоугольных областях, а затем
располагать эти области в абсолютных и относительных позициях. Области могут пе
рекрываться, в этом случае, определяя верхнюю область как прозрачную, можно ото
бражать нижележащие данные. Слои дают возможность ф о р м и р о в а т ь перекрываю
щиеся заголовки и панели, отображать текст в несколько колонок, аннотировать диа
граммы и другие рисунки и создавать составные изображения, помещая прозрачные
картинки поверх других. Включая в состав документа JavaScript-сценарии, можно ди
намически превращать видимые области в невидимые и наоборот. П р и н ц и п динами
ческого изменения слоев подробно описан в главе 24, здесь же, оценивая преимуще
ства слоев, достаточно помнить о такой возможности. Слои задаются в теле докумен
та (раздел BODY) с помощью элементов LAYER и ILAYER. Для обеспечения соответ-
168 Глава 5. К а с к а д н ы е листы с т и л е й
Внимание!
</BODY>
</HTML>
1 •1|дВ"'"'^<^ layer is on top, even thougii it appears first in Йхе HTML docTjment
IQI* -*.• ;DOGUrf»rtt D o n e ..„: ,:.^^*-,.. ...,. .,,i~ .:^:......, ^Я.: ^лШ-Ш
Рис. 5.10. А т р и б у т ы ABOVE, BELOW И Z - I N D E X ПОЗВОЛЯЮТ
изменять порядок следования слоев
BACKGROUND, BGCOLOR
По умолчанию слои создаются прозрачными. Ч т о б ы сделать слой непрозрачным,
надо задать ф о н о в о е изображение или цвет фона. Так, в предыдущем примере
(листинг 5.10 и рис. 5.10) с помощью атрибута BGCOLOR определялся цвет ф о н а для
каждого слоя. Если атрибут BGCOLOR задает н е п р о з р а ч н ы й ф о н , атрибут
BACKGROUND может использоваться для создания частично прозрачного фона, для
этого в качестве фонового должно быть задано п р о з р а ч н о е GIF-изображение.
170 Глава 5. К а с к а д н ы е листы с т и л е й
CLIP
Значением данного атрибута является набор целых чисел, разделенных запятыми,
которые определяют размеры области, занимаемой слоем. H T M L воспроизводит
всю область, но часть слоя может быть отсечена при выводе. Размеры задаются в
формате ''левая_граница, верхняя_граниг1,а, правая_граница, нижняя_грапица' либо в
формате ''правая_граница, нижняя_граница\ Последняя запись эквивалента "О, О,
правая_граниг^а, нижпяя_граница\
WIDTH, HEIGHT
Д а н н ы е атрибуты задают минимальную ширину и высоту слоя. Если атрибуты
WIDTH и HEIGHT не указаны, ширина и высота определяется содержимым слоя.
Заметьте, что WIDTH и HEIGHT — не максимальные, а минимальные размеры. П р и
необходимости ширина и высота увеличиваются, чтобы требуемая и н ф о р м а ц и я
могла разместиться в пределах области. В примере, приведенном в листинге 5.11 и
на рис. 5.10, атрибуты WIDTH и HEIGHT задавали размеры слоев.
ID
Данный атрибут присваивает слою имя. Это имя может быть использовано в качест
ве значения атрибутов ABOVE и BELOW либо при выполнении сценария JavaScript.
te4iHHitHiffil'ff1 РШ11
£fe £cft ^lew fio £omfnunical« Цв^
SRC
Д а н н ы й атрибут задает URL HTML-документа, который должен быть помещен в
указанный слой. Если в документе также определены слои, они рассматриваются
как д о ч е р н и е по отношению к текущему слою. Описанная возможность полезна в
тех случаях, когда необходимо включить фрагмент HTML-кода в несколько доку
ментов, а также при поддержке Web-страницы, основная часть которой остается
неизменной, а один небольшой фрагмент часто изменяется. Так, например, вы
можете включить контактную и н ф о р м а ц и ю в состав Web-страницы, поместив вы
ражение <LAYER S R C = " C o n t a c t - I n f o . h t m l " > < / L A Y E R > непосредственно пе
ред закрывающим дескриптором </BODY>. Для включения в статический документ
динамически изменяющегося фрагмента можно использовать следующий фраг
мент кода:
<Hl>Menu f o r J o e ' s D i n e r < / H l >
<ILAYER S R C = " B l u e - P l a t e - S p e c i a l . h t m l " > < / I L A Y E R >
<H2>Appetizers</H2> . . .
<H2>Main D i s h e s < / H 2 > . . .
<H2>Vegetables</H2> . . .
VISIBILITY
Д а н н ы й атрибут задает видимость слоя, т.е. определяет, должен ли слой отобра
жаться в окне броузера. Допустимыми значениями являются SHOW, INHERIT и
HIDDEN. З н а ч е н и е SHOW указывает на то, что слой должен отображаться, значение
INHERIT устанавливает видимость слоя равной видимости родительского слоя, а
значение HIDDEN запрещает отображение. Скрытые слои трудно применять на
172 Глава 5. Каскадные листы стилей
примененное в элементе
<SPAN I D = " l a y e r l " >
</SPAN>
почти эквивалентно следующему выражению:
<LAYER I D = " l a y e r l " LEFT=50 ТОР=75 ...>
</LAYER>
Аналогично, правило
#1ауег2 { position: relative;
t o p : lOpx;
... }
5.12. Слои 173
примененное в элементе
<SPAN I D = " l a y e r 2 " >
</SPAN>
почти эквивалентно элементу, приведенному ниже.
<ILAYER I D = " l a y e r 2 " ТОР=10 ...>
</ILAYER>
В дополнение к стандартным атрибутам, допустимым в CSS1, при работе со слоями
поддерживаются следующие атрибуты.
clip
З н а ч е н и е данного атрибута задается в виде прямоугольной области, т.е. с помо
щью выражения гect {верхняя_граница, правая_граница, нижпяя_грапица, ле-
вая_граница) либо с помощью ключевого слова a u t o (по умолчанию). Свойство
c l i p эквивалентно атрибуту CLIP элементов LAYER и ILAYER. Заметьте, что раз
меры области, как и все другие величины, связанные с позиционированием слоев,
задаются с помощью стандартных единиц длины CSS. Помимо пикселей, исполь
зуемых в LAYER и ILAYER, могут быть заданы пункты, дюймы и сантиметры.
left, t o p
Д а н н ы е свойства определяют верхний левый угол слоя в стандартных единицах
длины CSS. Эти свойства эквивалентны атрибутам LEFT и ТОР элементов LAYER и
ILAYER.
overflow
Д а н н о е свойство определяет поведение слоя в том случае, когда содержимое эле
мента превышает высоту или ширину слоя. Значение попе (по умолчанию) указы
вает на то, что содержимое должно отображаться обычным способом. З н а ч е н и е
c l i p задает отсечение, а значение s c r o l l указывает на то, что броузер должен
выполнить прокрутку, чтобы вместить содержимое.
position
Д а н н о е свойство может приобретать значения a b s o l u t e , r e l a t i v e и s t a t i c .
Эти значения соответствуют элементу LAYER, элементу ILAYER и обычным эле
ментам, для которых не используются слои. П о умолчанию принимается значение
static.
visibility
Д а н н о е свойство определяет, должен ли слой быть видимым или скрытым. Допус
тимыми значениями являются v i s i b l e , h i d d e n и i n h e r i t . Они соответствуют
нормально отображаемому элементу, скрытому элементу или элементу, наследую
щему видимость родительского элемента. Д а н н о е свойство может использоваться
при динамическом о т о б р а ж е н и и элементов посредством JavaScript-сценариев.
174 Глава 5. Каскадные листы стилей
<DIV ID="layer2">
<Hl>This is Iayer2.</Hl>
</DIV>
</BODY>
</HTML>
Changing Visibility
Dynamically
Changing Visibility
Dynamically
This is layeM.
^д^-^ =»jl^.- <
width, height
Д а н н ы е свойства определяют размеры слоев. О н и выполняют те же функции, что
атрибуты WIDTH и HEIGHT элементов LAYER и ILAYER.
z-index
В о б ы ч н ы х условиях слои располагаются один над другим в том порядке, в кото
ром они встречаются в HTML-документе. Свойство z - i n d e x изменяет порядок
следования слоев. Значением свойства является целое число, определяющее но
мер слоя. Слои с меньшими номерами располагаются ниже слоев с большими но
мерами. Данное свойство эквивалентно атрибуту Z-INDEX элементов LAYER и
ILAYER.
176 Глава 5. Каскадные листы стилей
5.13. Резюме
Каскадные листы стилей представляют собой мощный инструмент форматирова
ния Web-страниц. П р и работе с документами H T M L 4.0 листы стилей предпочтитель
нее др)тих средств. Листы стилей позволяют задавать ш р и ф т ы , цвет ф о н а и изобра
жения для различных разделов текста, определять плавающие элементы, границы и
отступы. Листы стилей также дают возможность ф о р м а т и р о в а т ь списки. Помимо но
вых возможностей, связанных с выводом текста, каскадные листы стилей позволяют
добиться, чтобы документ имел одинаковый вид в различных броузерах. Благодаря
использованию листов стилей достигается однотипная обработка слоев в Netscape и
Internet Explorer.
Несмотря на обилие возможностей, H T M L все же представляет собой не язык
программирования, а язык разметки, поэтому набор приложений, которые могут
быть созданы посредством HTML, ограничен. Язык Java позволяет создавать про
граммы, которые включаются в состав Web-страниц и выполняются в среде броузера.
Сфера применения Java не исчерпывается программами, работающими в составе
Web-страниц. Java представляет собой язык программирования общего назначения.
Рассмотрению Java-технологии посвящена часть II данной книги.
-JlEJS^-.
ПРОГРАММИ
РОВАНИЕ
НА ЯЗЫКЕ JAVA
Глава 6. Общие сведения о языке Java
Глава 7. Объектно-ориентированное программирование на Java
Глава 8. Синтаксис Java
Глава 9. Аплеты и основные действия с графикой
Глава 10. Java 2D: графика в Java 2
Глава 11. События, связанные с мышью и клавиатурой
Глава 12. Диспетчеры компоновки
Глава 13. КомпонентыAWT
Глава 14. Основы Swing
Глава 15. Расширенные средства Swing
Глава 16. Использование потоков
Глава 17. Сетевое программирование
ОБЩИЕ СВЕДЕНИЯ
О ЯЗЫКЕ JAVA
В ЭТОЙ главе...
читав эту главу, вы узнаете, где можно найти необходимое программное обеспечение
и документацию. Наконец, в этой главе будут приведены п р и м е р ы простых программ,
которые помогут вам начать изучение Java.
Если вы считаете Java аббревиатурой, вы ошибаетесь. Дело в том, что в Америке
слово "Java" — почти синоним слова "кофе". Этим названием компания Sun заменила
имя Oak, которое конфликтовало с существующим продуктом. Со словом Java ассо
циируется нечто тонизирующее и стимулирующее к работе.
6 . 1 . Возможности Java
Как бы восторженно ни отзывались разработчики о Java, его нельзя считать уни
кальным. Действительно, хотя Java — прекрасный язык, он никак не является набором
гениальных решений, которые никогда не встречались прежде. Многие решения уже
были реализованы в других языках. Однако в Java были объединены стандартные вы
разительные средства (синтаксис C/C++), богатые возможности проблемно-
ориентированных языков (автоматическое управление памятью и интерпретация
байтового кода) и набор API для разработки корпоративных систем. В последующих
разделах описаны некоторые наиболее важные характеристики Java.
Доставка п р о г р а м м н о г о о б е с п е ч е н и я ч е р е з Web
Java-аплеты поддерживаются в большинстве реализаций Netscape и Internet
Explorer, следовательно, могут выполняться практически в любой из существую
щих операционных систем. Использование аплетов становится причиной рас
смотрения броузера не только как программы, предназначенной для копирования
и отображения документа, но также как среды доставки и выполнения программ
ного кода. Теперь, если вы работаете с приложением, которое подвергается час
тым модификациям, у вас нет необходимости следить за выходом новой версии
программы и устанавливать ее. П о существу, вам не надо ничего инсталлировать,
достаточно создать в броузере закладку на Web-страницу, содержащую требуемый
6 . 1 . Возможности Java 181
Java п р е д о с т а в л я е т п е р е н о с и м у ю г р а ф и ч е с к у ю б и б л и о т е к у
Главным фактором, препятствующим переносимости большинства программных
систем, является пользовательский и н т е р ф е й с . Многие разработчики предпочи
тают стандартным кроссплатформенным графическим средствам оконную систе
му, ориентированную на конкретную платформу. Следуя подобному подходу, при
переходе на другую платформу компоненты программы, реализующие пользова
тельский и н т е р ф е й с , приходится переписывать заново. Создатели Java исходили
из того, что переносимый язык должен включать стандартную графическую биб
лиотеку, поэтому в реализацию Java компания Sun Microsystems включила AWT
184 Глава 6. Общие сведения о языке Java
ш 76 ^\ 0 3
0 4
0 51
0 47
0 41
0 36
0 38
0 33
0 33
0 28
0 29
0 25
8 0 5 0 43 0 32 0 32 0 26 0 23
06 0 37 026 0 22 0 19 02
__ 9 _ 0 7 0 33 0 22 0 19 0 16 0 16
08 03 021 0.18 0 13 0.13
~ii"' 0.9 0.2 0.14 0.12 0.1 0.1
1 n^6 0 1 0.08 0.07 0.08
; ;М
' 13 1
И ;
•
; ; '^z
А Cross Language Retrieval
'• Z
г,; ""А liil \ JHU/APL
19 "чХц^
: В^ ' ^ , TNO/UTwente
" 20 0.6-
VIRIT
21
Ч UTartpere
0 5-
''^CWI
O 0.4-
О
2 03-
29'1
30
02-
31
__33j 0 1-
()
л
IMI 0.1 0.2 0.3 0,4 05 06 0.7 0.8 0.9
37 Recall
|^ЩД|ЩД| H^joixil
_J__T ^
;^^Ш)^
~^чй
. ;-|3
v'^^.o>2t3isyT^>y^.:'?^^"^^^^^^
P^»»#Btfe^v#^^ "^v;>;- :-:л;;Г^Й=^^:;^|
m^\ nl4Q||¥®|ffl|^|Al
Rovef:|fOcky7 3 Оа1в:[и^?1 3 Cyde;[l 3 Map:|Eteve(ion 3
Простота Java
Язык Java похож на язык C++, но свободен от сложных синтаксических конструкций,
типичных для C++. Так, в Java-программах нет необходимости в файлах заголовков, не
нужны make-файлы, а механизм обмена данными по сети крайне прост. Среди большого
числа средств, упрощающих разработку программ, следует особо выделить два решения:
автоматическое управление памятью и автоматическую поддержку указателей.
Автоматическая п о д д е р ж к а указателей
Если вы передаете Java-функции объект (данные, не принадлежащие к простым
типам), система реально передает указатель или ссылку на этот объект. Это озна
чает, что в стек записывается не сам объект, а ссылка на него. Все детали этого
процесса скрыты от пользователя; с его точки зрения создается впечатление, что
объект непосредственно передается функции. Создавая программы на Java, у вас
нет необходимости присваивать значения указателям, более того, непосредствен
ные действия с указателями запрещены. Программист может не думать об указате
лях, а сосредоточить свое внимание на структуре классов. Несмотря на то что
операции с указателями не допускаются, действия, основанные на указателях, на
пример создание связных списков и деревьев, без труда реализуются средствами
Java. Описанный подход может показаться странным для программистов, рабо
тающих на C/C++, однако он успешно зарекомендовал себя в десятках языков, та
ких как Smalltalk и Lisp.
пая к разработке программ на Java, надо заранее приготовиться к тому, что рано или
поздно возникнет ситуация, когда вы затратите время и силы для написания утилиты,
а впоследствии выясните, что практически все возможности этой программы уже
реализованы в одном из Java API. Конечно, сознавать, что работа проделана зря, не
очень приятно, но все же это лучше, чем использовать язык, для которого отс)пгству-
ют библиотеки, и любую программу реализовывать "с нуля".
Н'НТДРДВ!
J96.48 (W 3|23.039
WmaitJmjm X RentMTalH.
j^fe^^^^^Ei
ClicK to start йешш a ieeioti.
ir^
;^App$et3tdrtsd \^i г.ГТЧт'ь^'^ •
Рис. 6.5. Java-интерфейс к Master Environmental Library ( M E L ) ~ биб
лиотеке для получения географических данных. Java-аплет предостав
ляет описание выбранной области
J a v a - п р и л о ж е н и я могут о б р а щ а т ь с я к л о к а л ь н ы м , н е п е р е н о с и м ы м
программам
Метод e x e c класса R u n t i m e позволяет Java-приложениям вызывать локальные
программы. Кроме того, платформенно-зависимый и н т е р ф е й с дает возможность
объединять программы, написанные на Java и С. Вызов локальных п р и л о ж е н и й
делает Java-программы полностью непереносимыми, а объединение с программа
ми на С обеспечивает переносимость в той мере, в которой ее позволяют реализо
вать связанные программы на С. Поэтому справедливо будет утверждать, что при
л о ж е н и е на Java непереносимо лишь потому, что непереносима связанная с ней
программа. Однако такие приложения уже нельзя рассматривать как "чистые" Java-
программы. Несмотря на то что при написании ряда программ удастся избежать
обращения к платформенно-зависимым компонентам, в некоторых случаях необ
ходимо форматировать диск, получать сведения о пользователях, зарегистриро
ванных в системе, либо организовать взаимодействие с существующими приложе
ниями, написанными на С или C++. Н е следует думать, что платформенно-
зависимых операций или взаимодействия с существующими компонентами надо
избегать. Напротив, возможность обращения к локальным средствам часто бывает
важнее переносимости. Плохо, если разработчик при создании программы не от
дает себе отчет в том, что на определенном этапе она перестала быть переноси
мой. Поэтому, используя библиотеки независимых производителей, будьте осто
р о ж н ы и старайтесь выяснить, какая часть библиотеки представляет собой
"чистые" Java-средства, а какая часть зависит от платформы.
190 Глава 6. Общие сведения о языке Java
Простота Java
Несколькими страницами выше было сказано, что Java — простой язык. Об этом
стоит поговорить особо.
Дело в том, что простота— относительное понятие. По сравнению с С и C++ син
таксические конструкции Java кажутся простыми в изучении и применении. Разра
ботчики, которым довелось выяснять, почему не освобождается фрагмент памяти
6.2. Java: мифы и реальность 191
или откуда берется то или иное значение указателя, скажут, что автоматическая
"сборка мусора" освобождает программиста практически от всей работы. Однако не
следует забьщать, что Java — это все же язык программирования, а программирование
никогда не было простым делом. Тот, для кого основным занятием было создание
HTML-документов, скажет, что Java — чрезвычайно сложный язык. Из-за возрастаю
щего количества стандартов и библиотек независимых производителей становится
все труднее следить за их появлением и изучать их.
Не говоря о том, что программирование — нелегкая работа сама по себе, программи
сты постоянно стремятся решать более сложные задачи. Так, например, используя дру
гие языки, только компьютерные гуру берутся за создание систем "клиент/сервер" или
многопотоковых приложений. В Java решением подобных задач часто занимаются про
граммисты среднего уровня. Хорошо это или плохо? С одной стороны, разработчики
могут создавать программы, недоступные им ранее. С другой стороны, при написании и
отладке таких программ неизбежно возникают дополнительные трудности.
Таким образом, язык Java совсем не прост. Однако синтаксис языка понять доста
точно легко, а тот факт, что компоненты Java можно изучать независимо друг от дру
га, обусловливает привлекательность Java для программистов.
• А п л е т ы . Для создания аплетов лучше всего выбирать Java Development Kit 1.1
(JDK 1.1, последней реализацией которого была JDK 1.1.8_005). Netscape 4.06,
Internet Explorer 4.01 и даже более поздние версии этих броузеров без допол
нительных модулей поддерживают только версию 1.1 и более ранние версии
Java. Исключением является только Netscape 6, который, однако, не поддержи
вает JDK 1.3. Распространяя аплеты по Internet, вы не можете знать, с какими
194 Глава 6. Общие сведения о языке Java
Установка Java
Средства Java поставляются со многими операционными системами (например,
OS/2, MacOS 10, Solaris 2.6), поэтому не исключено, что Java уже инсталлирован на
вашем компьютере. Если это не так, вам доступны свободно распространяемые вер
сии для Windows MacOS, OS/2, Novell IntranetWare, Solaris, Irix, HP-UX, AIX, SCO
UnixWare, Linux, Amiga, BeOS и многих других операционных систем. Ниже перечис
лены адреса основных узлов, с которых можно скопировать различные версии Java.
Что касается других операционных систем и коммерческих продуктов, информацию
о них вы найдете на сервере Sun по адресу
http://Java.sun.com/cgi-bin/java-ports.cgi
Заметьте, что информация, расположенная по многим URL, приведенным в этой
книге, доступна также по адресу h t t p : //www. corewebprogramming. com/.
Solaris SPARC/x86
http://Java.sun.com/j2se/l.3/download-solaris.html
Linux x86
http://Java.sun.com/j2se/l.3/download-linux.html
Solaris SPARC/x86
http://Java.sun.com/products/jdk/1.2/download-solaris.html
196 Глава 6. Общие сведения о языке Java
L i n u x х86
http://Java.sun.com/products/jdk/1.2/download-linux.html
Solaris SPARC/x86
http://Java.sun.com/products/jdk/1.2/download-jdk-solaris.html
N e t s c a p e Navigator
http://home.netscape.com/download/
Microsoft I n t e r n e t E x p l o r e r
http://www.microsoft.com/ie/download/
Hotjava
http://Java.sun.com/products/hotjava/
Для того чтобы получить список всех доступных продуктов, надо обратиться к узлу
Sun по адресу h t t p : / / J a v a . s u n . c o m / p r o d u c t s / .
Borland JBuilder
http://www.boгland.com/jbuilder/
IBM VisualAge
http://www-4.ibm.com/software/ad/vajava/
198 Глава 6. Общие сведения о языке Java
Oracle J D e v e l o p e r
http://www.oracle.com/ip/develop/ids/jdeveloper.html
http://www.visualeafe.com/Products/VisualCafe_Overview.html
Sun Forte D e v e l o p e r
http://www.sun.com/forte/ffj/
Компиляция
Если вы работаете в системе Windows или UNIX и используете компилятор j a v a c
из пакета Sun JDK, скомпилируйте текст, выполнив команду j a v a c T e s t . J a v a .
В системе Macintosh перетащите исходный файл на Java-компилятор. Если вы ра
ботаете в и н т е г р и р о в а н н о й среде, следуйте инструкциям поставщика. В результа
те компиляции создается файл T e s t , c l a s s .
Запуск п р о г р а м м ы
Для запуска независимого Java-приложения с консольным и н т е р ф е й с о м можно
вызвать команду J a v a T e s t . Заметьте, что утилита называется не j a v a c , а J a v a ,
кроме того, в качестве параметра задается T e s t , а не T e s t . c l a s s . В Mac доста
точно перетащить файл класса на программу запуска. Для выполнения аплета вам
потребуется броузер, в котором необходимо открыть Web-страницу, содержащую
аплет. Так, например, чтобы запустить аплет в составе Web-страницы T e s t . h t m l ,
эта страница должна ссылаться на файл T e s t , c l a s s посредством дескриптора
<APPLET>. Подробно о запуске аплетов мы поговорим позже.
Л и с т и н г 6 . 1 . HeiioWorid.Java
Компиляция:
javac HelloWorld.Java
Запуск:
Java HelloWorld
Результаты выполнения:
H e l l o , world.
раметры, несмотря на то, что в этой системе не существует такого понятия, как ко
мандная строка; в большинстве реализаций в тот момент, когда программа начинает
сбор входных данных, на экране отображается небольшое окно.
Листинг 6 . 2 . S h o w A r g s . J a v a
p u b l i c c l a s s ShowArgs {
public s t a t i c void main(String[] args) {
f o r ( i n t i = 0 ; i < a r g s . l e n g t h ; i++) {
System.out.println("Arg " + i + " is " + args[i];
}
}
}
Компиляция:
javac ShowArgs.Java
Запуск:
Java ShowArgs fee fie foe fum
Результаты выполнения:
Arg 0 is fee
Arg 1 is fie
Arg 2 is foe
Arg 3 is fum
Листинг 6 . 3 . HelloWWW. J a v a
import Java.applet.Applet;
import java.awt.*;
p u b l i c c l a s s HelloWWW e x t e n d s A p p l e t {
p r i v a t e i n t f o n t S i z e = 40;
6.5. Несколько простых Java-программ 201
</BODY>
</HTML>
Компиляция:
javac HelloWWW.Java
Запуск:
HelloWWW. h t m l загружается в Web-броузер.
Результаты выполнения:
Т и п и ч н ы е результаты показаны на рис. 6.6.
Компиляция:
javac Message.Java
Запуск:
M e s s a g e . h t m l загружается в Web-броузер.
Результаты выполнения:
На рис. 6.7 показана Web-страница, в которой один и тот же аплет загружается че
тыре раза. П р и вызове аплета в составе дескриптора APPLET задаются разные значе
ния атрибута HEIGHT, а в дескрипторе PARAM — разные значения атрибута VALUE.
JSIxJ
, Ete 1 * iiew Favorites lools Неч
d
T h e Message A p p l e t
Small
Medium
Giant
i^jOone ;уЗ My Computer
J
Рис. 6.7. Один и тот же аплет четырежды
отображается в окне броузера Explorer 5.5,
который выполняется в системе Windows 2000
204 Глава 6. Общие сведения о языке Java
6.6. Резюме
Язык Java был впервые представлен несколько лет назад и бурно развивался все
эти годы. Большинство разработчиков не встречались прежде с н е к о т о р ы м и средст
вами Java, тем не менее, идеи, на базе которых созданы эти средства, уже были неод
нократно реализованы в других языках. Целью данной главы было предоставить чи
тателю общие сведения о Java и развеять л о ж н ы е представления о данном языке. По
сле инсталляции Java, броузера с поддержкой Java и документации по Java API можно
приступать к созданию первых программ.
Дальнейшие ваши действия зависят от того, насколько богат ваш опыт программи
рования. Если вы никогда не работали с объектно-ориентированными языками, вам
следует внимательно прочитать главу 7. Если же объектно-ориентированный подход —
не новость для вас, то достаточно бегло просмотреть эту главу для того, чтобы узнать о
некоторых особенностях, отличающих Java от других объектно-ориентированных язы
ков. Аналогично, если вы ничего или почти ничего не знаете о С или C++, вам надо вни
мательно прочитать главу 8, где рассматривается синтаксис Java, и попытаться написать
несколько простых программ. Если же ваш опыт программирования на C/C++ доста
точно велик, вам следует лишь пролистать главу 8 и перейти к более сложному материа-
лу. В последующих главах будут рассмотрены работа с окнами и графикой, поддержка
событий, многопотоковая обработка, создание программ, взаимодействующих по сети,
Java-сервлеты, JavaServer Pages и прочие вопросы.
ОБЪЕКТНО-
ОРИЕНТИРОВАННОЕ
ПРОГРАММИРО
ВАНИЕ НА JAVA
В ЭТОЙ главе...
7 . 1 . Переменные экземпляра
Класс можно упрощенно представить себе как структуру или запись. О б ы ч н о для
создания объекта (экземпляра класса) используется о п е р а т о р new, после которого
указывается конструктор класса. Конструктор — это метод, имя которого совпадает с
именем класса. Н а п р и м е р :
Point р1 = new Point(2, 4);
Color red = new Color(255, 0, 0);
В некоторых случаях использование оператора new остается скрытым от разра
ботчика. Н а п р и м е р , объект может возвращаться в результате выполнения метода, в
этом случае о п е р а т о р new выполняется в теле метода, либо метод вовсе не обращает
ся к данному оператору, а возвращает существующий экземпляр класса. П р и м е р ы
объектов, возвращаемых методами, приведены ниже.
208 Глава 7. Объектно-ориентированное программирование.
Листинг 7 . 1 . T e s t l . j a v a
class Shipl {
public double x, у, speed, direction;
public String name;
}
Компиляция и запуск:
javac T e s t l . j a v a
Java T e s t l
Результаты выполнения:
Shipl is at (1,0).
Ship2 is at (-1.41421,1.41421).
П р о с м о т р е в текст данного примера, вы, возможно, заметили в именах перемен
ных и классов н е к о т о р ы е особенности. В соответствии со стандартными соглаше
ниями об именовании Java имена локальных переменных и переменных экземпляра
начинаются со с т р о ч н о й буквы (например, s o m e S t r i n g , window, o u t p u t S t r e a m l ) , а
имена классов начинаются с прописной буквы (например. S t r i n g , Window,
O u t p u t S t r e a m ) . Если имя переменной или класса состоит из нескольких "слов", каж
дое из последующих "слов" п р и н я т о начинать с прописной буквы (например,
s o m e l n s t a n c e V a r i a b l e , S o m e C l a s s ) . Н е к о т о р ы е разработчики предпочитают раз
делять "слова" знаками подчеркивания (например, someinstancevariable,
S o m e C l a s s ) . Имена констант состоят из прописных букв (например, P I ) . Данное
соглашение делает код более удобочитаемым, по имени можно сразу сказать, является
ли оно именем класса или переменной.
Методика профессионалов
Имя переменной начинается со строчной буквы (myVar), а имя клас
са—с прописной (myCLass).
7.2. Методы
В предыдущем примере один и тот же фрагмент кода повторялся несколько раз
для того, чтобы присвоить значения переменным экземпляра х и у двух объектов. Та
кой стиль программирования считается плохим не только потом)% что одинаковые
фрагменты повторяются многократно, сколько потому, что при модификации про
граммы надо вносить изменения сразу в нескольких ее частях. Для того чтобы решить
эт)^ проблему, включим функцию в состав класса, который до сих п о р содержал только
данные. Код такого класса показан в листинге 7.2. Функции, входящие в состав класса,
п р и н я т о называть, как и в L i s p / C L O S , методами (в языке C++ они называются функ
циями-членами). Заметьте, что в отличие от C++, в Java переменные экземпляра могут
инициализироваться при объявлении.
public double х=0.0;
П р и объявлении переменных и методов могут использоваться ключевые слова
p u b l i c и p r i v a t e , которые п р и н я т о называть модификаторами. П о д р о б н о они буд)т
описаны ниже в этой главе, сейчас же достаточно заметить, что м о д и ф и к а т о р p u b l i c
разрешает дост)'п к переменной или методу из других объектов. Модификатор p r i
v a t e , напротив, ограничивает доступ рамками данного класса.
Листинг 7.2. T e s t 2 . j a v a
/ / К к л а с с у S h i p д о б а в л я ю т с я методы move и p r i n t L o c a t i o n ,
/ / объявленные к а к p u b l i c
class Ship2 {
public double x=0.0, y=0.0, speed=1.0, direction=0.0;
public String name = "UnnamedShip";
Компиляция и запуск:
javac Test2.java
Java Test2
Результаты выполнения:
Shipl is at (1, 0) .
Ship2 is at (-1.41421,1-41421).
Внимание!
На з а м е т к у
}
Единственным результатом выполнения этого кода будет п о в т о р н о е присвоение
локальным переменным тех же значений. Один из выходов из создавшегося положе
ния — использовать различные имена для локальных переменных и переменных эк
земпляра.
public Ship3(double inputX, double inputY, ...) {
X = inputX;
у = inputY;
X = X + speed * Math.cos(angle);
у = у + speed * Math.sin(angle);
}
Указывать переменную t h i s перед именем каждой переменной экземпляра или
метода нет никакой необходимости, однако в некоторых случаях данная переменная
оказывается полезной. Так, например, с ее помощью можно отделить локальные пе
ременные от полей класса с теми же именами.
Листинг 7 . 3 . T e s t 3 . J a v a
/ / В к о н с т р у к т о р е S h i p 3 при с о з д а н и и о б ъ е к т а происходит
/ / и н и ц и а л и з а ц и я переменных э к з е м п л я р а .
class Ship3 {
public double x, у, speed, directions-
public String name;
public Ship3(double x, double y, double speed,
double direction, String name) {
this.x = x; // Переменная "this" позволяет отделить
this.у = у; // переменные экземпляра от локальных переменных,
this.speed = speed;
this.direction = direction;
this.name = name;
Компиляция и запуск:
javac Test3.java
Java T e s t s
Результаты выполнения:
Shipl is at (1,0).
Ship2 is at (-1.41421,1.41421).
static {
for (int i=0; i<values . length; i-»-+) {
values[i] = 2 * i + 5;
}
}
}
В большинстве случаев действия по инициализации выполняются в теле конструк
тора. Статические инициализационные блоки применяются крайне редко.
7.4. Деструкторы
Д а н н ы й раздел вполне мог бы отсутствовать.
Дело в том, что в Java нет необходимости в использовании деструкторов
(функций, предназначенных для разрушения объектов). После удаления последней
ссылки на объект система "сборки мусора" освобождает память, занимаемую этим
объектом. Если ссылка на объект содержится в локальной переменной, объект удаля
ется после завершения работы метода либо раньше, при изменении значения пере
менной. Если на объект ссылается переменная экземпляра, то объект удаляется после
присвоения этой переменной нового значения. Следует признать, что деструкторы —
не самая удобная конструкция, используемая в языке С. В Java деструкторов нет, но
программы продолжают работать нормально. В Java не может быть указателей, ссы
лающихся на неиспользуемые области памяти. Пока переменная ссылается на объект,
этот объект продолжает существовать. В Java не могут оставаться неиспользуемые об
ласти памяти: система "сборки мусора" освобождает память, занимаемую объектами,
7-5- Переопределение 215
7.5. Переопределение
Подобно C++ и другим объектно-ориентированным языкам, Java допускает сущест
вование нескольких методов с одинаковыми именами. Эти методы различаются по
числу и типу передаваемых им параметров. Например, вы можете определить два ме
тода i s B i g : один из них выявляет "большие", согласно выбранному вами критерию,
объекты S t r i n g , а другой определяет, превышает ли значение целочисленной пере
менной некоторую заранее заданную величину.
public boolean i s B i g ( S t r i n g s) {
r e t u r n ( s . l e n g t h 0 > 10);
}
public boolean i s B i g ( i n t n) {
r e t u r n ( n > 1000);
}
Вновь объявленный вариант метода move позволяет задавать число "шагов" при
перемещении судна. Определяя новый метод, вы можете создать в его тело вызов
старого метода, а можете построить программу так, что два метода будут выполняться
независимо друг от друга. В следующем примере при выполнении второго из указан
ных методов вызывается первый метод move:
p u b l i c void move() {
double angle = d e g r e e s T o R a d i a n s ( d i r e c t i o n ) ;
X = X + speed * M a t h . c o s ( a n g l e ) ;
у = у 4- speed * Math, s i n (angle) ;
}
p u b l i c void move(int s t e p s ) {
for ( i n t 1=0; K s t e p s ; i++) {
move();
}
}
p u b l i c void move2(int s t e p s ) {
double angle = d e g r e e s T o R a d i a n s ( d i r e c t i o n ) ;
X = X + ( d o u b l e ) s t e p s * speed * M a t h . c o s ( a n g l e ) ;
у = у + ( d o u b l e ) s t e p s * speed * M a t h . s i n ( a n g l e ) ;
}
p u b l i c void move{) {
move(1);
p u b l i c void move{int s t e p s ) {
double angle = d e g r e e s T o R a d i a n s ( d i r e c t i o n ) ;
X = X + ( d o u b l e ) s t e p s * speed * M a t h . c o s ( a n g l e ) ;
у = у + ( d o u b l e ) s t e p s * speed * M a t h . s i n ( a n g l e ) ;
}
Подобные решения встречаются чаще, чем это может показаться на первый взгляд,
поэтому запомните данный подход и постарайтесь использовать его при возникнове
нии аналогичной проблемы. Заметьте, что данное решение неприменимо, если исход
ный метод move принадлежит классу, код которого вы не можете изменить.
Полностью код класса представлен в листинге 7.4.
Листинг 7 . 4 . T e s t 4 , j a v a
class Ship4 {
public double x=0.0, y=0.0, speed=1.0, direction=0.0;
public String name;
// Перемещение на N шагов.
Компиляция и запуск:
javac Test4.java
Java Test4
Результаты выполнения:
Shipl is at (1,0).
Ship2 is at (-4.24264,4.24264).
Листинг 7 . 5 . S h i p . j a v a
// Конструкторы
this.x = х;
}
/** Определение текущей позиции Y. */
It'Hn^ffiPi'illfffflllHWIWIl
File Edk View Fjvofites Tools Help
Class Ship
I
+—Ship
Itpj &yow}t
Constructor Sununaiy
iSli4fi<<iovaji* X, doubi* y , doubit s p « t d , doublt dirtction,
S'ibSLljUiil пале)
Build a sbp with specified perametere.
:SMp<S':vin:t n*ike)
\ Build a ship with default values (хЧЗ, y-0, sp«ed-l .0, di«ction-0.0).
Method Smmnary
d
; ^ My Compu»«
с
Рис. 7.1. Программа javadoc генерирует гипертек
стовые документы по исходному коду Java
Листинг7.6. ShipTest.Java
p u b l i c c l a s s ShipTest {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ^ args) {
Ship s i = new S h i p ( " S h i p l " ) ;
Ship s2 = new S h i p ( 0 . 0 , 0 . 0 , г.Or 135.0, "Ship2");
s1.move();
s2.move(3);
si.printLocation();
s2.printLocation();
}
}
Компиляция и запуск:
javac ShipTest.Java
Java ShipTest
Первая из приведенных выше двух команд вызывает программу j a v a c для компи
ляции файла S h i p . Java. Java-компилятор автоматически проверяет дату создания
7.7. Javadoc 223
На заметку
При работе с Java нет необходимости в применении таке-файлов.
Компилятор javac автоматически проверяет соответствие дат соз
дания всех непосредственно связанных классов.
Результаты выполнения:
Shipl is at (1,0).
Ship2 i s a t ( - 4 . 2 4 2 6 4 , 4 . 2 4 2 6 4 ) .
7.7.Javadoc
п р о г р а м м а j a v a d o c распространяется в составе JDK, a также вместе с продуктами
независимых производителей. Эта утилита использует для генерации документации
комментарии, помещенные между последовательностями символов " / * * " и " * / " .
В состав документов могут включаться гипертекстовые ссылки на другие системные
классы и классы, определенные пользователем. О б ы ч н о комментарии j a v a d o c по
мещаются перед определением класса, а также перед методами и переменными, в
объявлении которых не используется ключевое слово p r i v a t e . Первое предложение
в описании метода или переменной используется для ф о р м и р о в а н и я индекса вверху
страницы, а полное описание помещается в нижней части документа. Для построения
документации надо вызвать программу j a v a d o c и предать ей одно или несколько
имен файлов либо пакетов. Например:
javadoc Foo.java
javadoc Foo.java Bar.Java
javadoc graphics.newWidgets
javadoc graphics.newWidgets math.geometry
П р и вызове j a v a d o c можно также задавать различные опции. Допустимые опции
будут рассмотрены ниже в этом разделе, здесь же мы приведем лишь следующие про
стые примеры:
javadoc -author -version SomeClass.Java
javadoc -noindex -notree somePackage
Рассмотрению пакетов посвящен раздел 7.10.
По умолчанию программа j a v a d o c использует для генерации HTML-данных стан
дартный доклет-шаблоп. Доклет распознает в составе комментариев не только текст,
но и HTML-разметку. Поэтому вы можете использовать выражения типа <А
HREF=" . . . "> для ф о р м и р о в а н и я ссылок на Web-страницу организации и на другие
ресурсы, элементы IMG для включения копий экрана демонстрирующих программу в
224 Глава 7. Объектно-ориентированное программирование...
Дескрипторы javadoc
в дополнение к элементам разметки HTML в j a v a d o c определены специальные
дескрипторы, которые включаются в состав комментариев для достижения требуе
мых результатов. Так, например, дескриптор @param используется для описания па
раметров, передаваемых методу, @return — для описания возвращаемых значений, а
@see — для определения ссылок на классы и методы, имеющие отношение к рассмат
риваемом)^ элементу программы. Ниже приведен фрагмент комментариев, в котором
используются указанные дескрипторы.
/** Преобразование градусов в радианы.
* @param degrees Значение угла в градусах.
* @return Значение угла в радианах.
* @see t r a d i a n s T o D e g r e e s .
©author
Д е с к р и п т о р @ a u t h o r задает сведения об авторе. Ч т о б ы данный дескриптор учи
тывался при создании документа, необходимо задать команду " j a v a d o c - a u t h o r
. . .". В составе дескриптора @ a u t h o r допустимы HTML-элементы разметки, на
пример:
/** Описание класса SomeClass
{@docRoot}[Java 1.3]
Д а н н ы й дескриптор представляет относительный путь от сгенерированного доку
мента до корневого док^'мента в иерархии пакетов. Этот дескриптор удобно при
менять тогда, когда создается документация для большого пакета со многими под
каталогами; с его помощью п р и н я т о ссылаться на страницу с лицензионными дан
ными, расположенную в корневом каталоге. Например, если в документе
c o r e w e b p r o g r a m m i n g / S h i p . J a v a требуется ссылка на лицензионную информа
цию, то выражение
<а href="{@docRoot}/license.html">
будет и н т е р п р е т и р о в а н о как
<а href="../license.html">
П р и этом предполагается, что файл licence.html находится в каталоге
corewebprograiraning.
©exception
Данный дескриптор, за которым после пробела должно быть указано имя класса
исключения, описывает методы и конструкторы.
{@link}Uaval.2]
Данный дескриптор аналогичен дескриптору 0 s e e , за исключением того, что вме
сто раздела "See Also" (см. также) в документе генерируется гипертекстовая ссыл
ка. Д а н н ы й дескриптор применяется в описаниях для создания ссылок на другие
методы. Н а п р и м е р , в описании S h i p . J a v a может содержаться приведенный ни
же фрагмент.
То change the location of a ship use
{(Slink #move(int) move}.
226 Глава 7. Объектно-ориентированное программирование...
@param
Дескриптор @param описывает параметры, передаваемые методу (или конструк
тору). За дескриптором должно следовать имя параметра, за которым после про
бела располагается описание этого параметра.
©return
Данный дескриптор описывает значение, возвращаемое методом.
@see
Дескриптор @see создает ссылки на описания других методов или классов. Перед
именем метода задаются имя класса и символ "#". Если метод принадлежит теку
щему классу, имя класса не указывается. Например:
* @see #getWidget
* @see Widget
* @see Frob#setWidget
V
public void setWidget(Widget w) { ... }
@serial[Java 1.2]
@serialData[Java 1.2]
@serialField[Java 1.2]
Эти три дескриптора предназначены для того, чтобы описывать классы, допускаю
щие вывод в поток ( S e r i a l i z a b l e ) . Первый дескриптор описывает поля, которые
подлежат записи в поток. Второй дескриптор описывает все поля ObjectStream
F i e l d , а третий задает последовательность и типы данных E x t e r n a l i z a b l e . Под
робную информацию об этих дескрипторах вы найдете в документе h t t p : / / J a v a .
sun.com/j 2 s e / l . 3 / d o c s / g u i d e / s e r i a l i z a t i o n / s p e c / s e r i a l - a r c h . d o c 6 . h t m l .
©since
Данный дескриптор создает раздел "Since", используемый для документирования
добавляемых классов, полей или методов. Его удобно применять при описании
модифицируемых классов и пакетов, так как он позволят отличить вновь создан
ные элементы от элементов, существующих давно.
©throwsljava 1.2]
Дескриптор @throws описывает исключение, генерируемое классом или методом.
За дескриптором указываются имя класса исключения, пробел и описание исклю
чения.
7.7. Javadoc 227
©version
Д е с к р и п т о р A v e r s i o n используется при документировании класса и задает номер
версии. Ч т о б ы программа j a v a d o c учитывала данный дескриптор, ее надо вы
звать следующим образом: " j a v a d o c - v e r s i o n . . . ".
-author
Данная опция )тсазывает j a v a d o c на то, что в результирующий документ должна быть
включена информация об авторе. По умолчанию эта информация игнорируется.
-bottom[Java 1.2]
Опция b o t t o m задает текст, который помещается в нижней части каждого выход
ного д о к ) ^ е н т а . Текст располагается ниже навигационной строки. Если в тексте
содержатся пробелы, его надо заключить в кавычки.
-classpath
-sourcepath
Д а н н ы е опции указывают j a v a d o c , где надо искать заданные файлы . J a v a .
Для разделения каталогов в Solaris используется двоеточие, а в Windows — точка с
запятой. Каталоги, перечисленные в переменной окружения CLASS PATH, участву
ют в поиске автоматически.
-d
Д а н н ы й флаг задает целевой каталог для HTML-файлов. В качестве значения мо
жет быть приведено абсолютное либо относительное имя каталога. Если данная
опция не указана, HTML-файлы помещаются в тот же каталог, в котором находят
ся исходные файлы. Часто с помощью опции - d задают каталог, в котором уже на
ходится подкаталог i m a g e s , содержащий файлы, используемые в описаниях.
-encoding
-docencoding
Данная опция позволяет указать кодировку символов для исходного файла
( - e n c o d i n g ) либо для документа ( - d o c e n c o d i n g ) .
228 Глава 7. Объектно-ориентированное программирование...
-J
Инструмент j a v a d o c сам no себе является Java-программой. Опция - J позволяет
передавать параметры непосредственно в среду выполнения Java. Например, если
набор документов очень велик, вы можете задать большой (24 Мбайт) исходный
размер посредством следующего вырг1жения:
javadoc -J-ms24m . . .
-nodeprecated
-nodeprecatedlist [Java 1.2]
Первая из указанных опций сообщает javadoc о том, что записи о компонентах, не
рекомендованных для применения, должны быть исключены из документов. Вторая
опция запрещает создание документа d e p r e c a t e d - l i s t . h t m l и исключает ссылку
на компоненты, не рекомендованные для применения, из навигационной строки.
Информация о подобных компонентах генерируется и включается в документы.
-noindex
Данная опция указывает j a v a d o c на то, что документ AllNames . html не должен
создаваться. Индексирование удобно при описании пакетов. При создании доку
ментации на отдельные классы его часто запрещают.
-notree
Данная опция указывает j a v a d o c на то, что иерархия классов t r e e . h t m l не
должна генерироваться.
7.7. Javadoc 229
-public
-protected
-package
-private
Данные опции позволяют указать, какие классы, поля и методы должны быть до
кументированы. В приведенном выше перечне они расположены так, что каждая
последующая опция приводит к возрастанию объема данных в документе по срав
нению с предыдущей. По умолчанию предполагается опция p r o t e c t e d , которая
задает документирование всех компонентов, объявленных как p u b l i c и p r o
t e c t e d . Такие описания чаще всего требуются пользователям, однако разработ
чикам, которым приходится модифицировать содержимое классов, могут понадо
биться данные о компонентах, объявленных как p r i v a t e .
-verbose
Данная опция указывает j a v a d o c на то, что при работе программы должна выво
диться информация о времени, затраченном на разбор каждого файла.
-version
Опция v e r s i o n включает в документ номер версии, заданный с помощью деск
риптора @ v e r s ion. По умолчанию номер версии не включается.
7.8. Наследование
Наследование состоит в том, что новый класс создается на базе имеющегося клас
са; при этом код существующего класса остается неизменным. Для обозначения на
следования классов используется ключевое слово e x t e n d s . Исходный класс принято
называть родительским классом, или суперюшссом (в терминологии C++ он называется
базовым классом). Н о в ы й класс, созданный на основе существующего, называют до
черним классом, или подклассом (в C++ такой класс называют порожденным). Конст
руктор дочернего класса может непосредственно вызвать конструктор родительского
класса; для этого надо поместить в первой строке нового конструктора выражение
s u p e r . Ниже приведен код простого примера.
// ParentClass.Java: используется в роли суперкласса.
// Содержит поля а и Ь, а также методы foo и bar.
/ / В данном классе определены два конструктора.
public ChildClass(double z) {
super(z); // Вызов конструктора ParentClass
p u b l i c void b a z ( b o o l e a n isReady) {
}
На з а м е т к у
На з а м е т к у
Листинг 7.8.SpeedboatTest.Java
Компиляция и запуск:
javac -depend SpeedboatTest.Java
Java SpeedboatTest
Первгш из приведенных выше команд автоматически обрабатывает файлы
S p e e d b o a t . j ava и S h i p . j ava.
Результаты выполнения:
RED Speedboatl is at (20,0).
BLUE Speedboat2 is at (-1.41421,1.41421).
Shipl is at (-1.41421,1.41421).
В отличие от C++ и L i s p / C L O S , в Java запрещено множественное наследование.
lOiacc может иметь сколь угодно подклассов, но только один суперкласс. В этом Java
похож на Smaltalk. Несмотря на то что работать с одним суперклассом очень удобно,
множественное наследование также имеет свои преимущества. В Java аналогичных
результатов можно добиться, применяя и н т е р ф е й с ы , которые будут рассмотрены в
следующем разделе.
Листинг 7 . 1 0 - C u r v e . j a v a
Листинг 7.11.StraightEdgedShape.Java
Листинг 7 . 1 2 . I n t e r f a c e l . j a v a
Листинг 7.13.Classl.Java
В листинге 7.15 приведен код класса, реализующего оба представленных выше ин
терфейса.
Листинг 7.15,Class2,java
}
7.9. Интерфейсы и абстрактные классы 237
Листинг 7 . 1 6 . C l a s s 3 . j a v a
Листинг 7 . 1 7 . I n t e r f a c e s . J a v a
Затем при определении класса Circle можно указать, что он реализует интер
фейс Measurable (листинг 7.19).
Листинг 7.19.Circle.Java
Листинг 7.20.MeasureUtil.Java
Листинг7.21. Polygon.java
/ * * З а к р ы т а я форма с у г л а м и . */
p u b l i c a b s t r a c t c l a s s Polygon e x t e n d s StraightEdgedShape
implements Measurable {
p r i v a t e i n t numSides;
p u b l i c i n t getNumSides() {
return(numSides);
при получении доступа к классу A p p l e t можно каждый раз указывать полное имя
j a v a . a p p l e t . A p p l e t , a можно включить в файл выражение i m p o r t j a v a . a p p l e t .
A p p l e t (или i m p o r t J a v a , a p p l e t . *) и обращаться к классу по имени A p p l e t .
Обратите внимание, что при объявлении методов p r i n t l n f o указан модификатор
s t a t i c . Для вызова методов класса необязательно создавать экземпляр класса, доста
точно указать имя класса (например, M a t h . c o s ) .
Листинг 7 . 2 4 . С : \ J a v a \ c l a s s e s \ p a c k a g e l \ C l a s s l . J a v a
package p a c k a g e l ;
package package2;
package package2.раскадеЗ;
Листинг 7.27.С:\Java\classes\package4\Classl.java
package package4;
Листинг 7.28.С:\Java\classes\PackageExample.Java
import packagel.*;
import package2.Class2;
import package2.packages.*;
p u b l i c c l a s s PackageExample {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
Classl.printlnfo() .
Class2.printlnfo() ,
C l a s s 3 . p r i n t l n f o (),
package4.Classl.printlnfo(
}
Компиляция и запуск:
j a v a c PackageExample.Java
Java PackageExample
Первая из приведенных выше команд автоматически компилирует все четыре
класса.
Результаты выполнения:
This is Classl in packagel.
This is Class2 in package2.
This is Class3 in package2.раскадеЗ.
This is Classl in package4.
В приведенном примере компиляция файла PackageExample. Java автоматиче
ски влечет за собой компиляцию остальных исходных файлов, поскольку Р а с к а д е -
Example непосредственно обращается к соответствующим классам. Если вы хотите
скомпилировать исходные файлы по отдельности, вам надо указать в командной
строке также подкаталог.
javac packagel/Classl.Java
javac package2/Class2.Java
javac package2/package3/Class3.Java
javac package4/Classl.Java
Безопасность
Перед запуском броузера отключите установки CLASSPATH.
Использование JAR-файлов
Установка переменной окружения CLASSPATH— наиболее подходящий способ за
дать список каталогов, в которых должен осуществляется поиск файлов классов. Од
нако, если вы используете большое количество пакетов, размеры CLASS PATH могут
превысить максимальные размеры, допустимые для переменной окружения в опера
ционной системе. Для того чтобы разрешить эту проблему, Java позволяет включать
классы в Java-архив (JAR). В состав JDK входит утилита j a r , которая помещает файлы
классов в сжатом виде в единый JAR-файл. П р и этом используется алгоритм, анало
гичный сжатию в ZIP-формате.
Ниже перечислены опции, которые наиболее часто задаются п р и вызове j а г .
с
Данная опция задает создание нового JAR-файл а.
f
Опция f указывает файл для обработки или целевой JAR-файл.
т, М
Первая из приведенных опций (строчная ш) указывает на то, что для поддержки
расширенных возможностей (подписанные JAR-файлы, исполняемые JAR-файлы)
используется файл описания (manifest file). Если указаны и m и f, порядок исполь
зования файла описания и JAR-файла совпадает с порядком следования опций.
Вторая опция (прописная М) указывает на то, что файл описаний не должен созда
ваться. П о умолчанию описание включается в архив; ознакомиться с его содержи
мым можно, разархивировав JAR-файл. Дополнительную и н ф о р м а ц и ю о файлах
описаний вы найдете по адресу h t t p : / / J a v a . s u n . c o m / d o c s / b o o k s / t u t o r i a l /
jar/basics/manifest.html.
t
Эта опция выводит содержимое JAR-файла.
u
Данная опция указывает на обновление JAR-файла, например добавление файлов
или изменение описания.
V
Опция V задает вывод подробного отчета о выполненных действиях.
хфайя
Данная опция распаковывает файлы, входящие в состав JAR-файла. Если файл не
указан, распаковываются все файлы в архиве.
7 . 1 1 . Модификаторы 247
О
Указанная опция (цифра "нуль") задает создание несжатого JAR-файла.
Н и ж е в качестве примера приведена команда, с помощью которой все ф а й л ы
C l a s s X . c l a s s , рассмотренные в рамках предыдущего примера, помещаются в один
JAR-файл.
С:\Java\classes>jar cfv e x a m p l e . j a r p a c k a g e l package2 package4
Результаты выполнения:
added manifest
adding: packagel/(in = 0) (out= 0)(stored 0%)
adding: packagel/Classl.class(in = 4 68)
(out= 326)(deflated 30%)
adding: package2/(in = 0) (out= 0)(stored 0%)
adding: package2/Class2.class(in = 4 68)
(out= 327)(deflated 30%)
adding: package2/package3/(in = 0) (out= 0)
(stored 0%)
adding: package2/package3/Class3.class(in = 486)
(out= 338)(deflated 30%)
adding: package4/(in = 0) (out= 0)(stored 0%)
adding: package4/Classl.class(in = 4 31)
(out= 298)(deflated 30%)
В данном примере мы предполагаем, что в каталогах, соответствующих пакетам,
содержатся только файлы классов. Если это не так, в архив e x a m p l e . j a r будут вклю
чены также исходные тексты программ и все другие файлы. Для того чтобы в архив
помещались только файлы классов, это надо явно указать в командной строке. П р и
необходимости вы можете поместить список jar-команд в отдельный файл и затем за
дать его в командной строке в виде (? имя_файла.
Создав jar-файл, можно указать его в качестве значения переменной CLASSPATH.
Если строка все же оказывается слишком длинной, файл следует поместить в каталог
/ r o o t / j d k l . 3 / j r e / l i b / e x t / . JAR-файлы, расположенные в этом каталоге, Java
проверяет автоматически, как и каталоги, явно указанные в списке поиска классов.
На з а м е т к у
7 . 1 1 . Модификаторы
в данной главе при объявлении классов, методов и переменных экземпляров ис
пользовались различные модификаторы: p u b l i c , p r i v a t e , p r o t e c t e d , s t a t i c и др.
Несмотря на то что смысл этих модификаторов был ясен из контекста, желательно
рассмотреть их подробнее.
248 Глава 7. Объектно-ориентированное программирование.
Тот же класс Да Да Да Да
public
Данный модификатор указывает на то, что переменная или метод доступны любо
му, кто имеет доступ к экземпляру класса. Данным модификатором помечаются
средства, предоставляемые пользователям; они обычно документируются с помо
щью j a v a d o c .
Многие разработчики считают, что переменные экземпляра никогда не должны
объявляться как общедоступные и что обращаться к ним следует только посредст
вом методов. Аргументы в пользу такого мнения вы найдете в одном из предыду
щих разделов. Подобный подход использовался при создании примера S h i p
(листинг 7.5); такое соглашение действует и для компонентов JavaBeans. Однако
некоторые программисты утверждают, что "никогда" — это слишком строгое тре
бование и что общедоступные поля вполне допустимы для небольших классов, ис
пользуемых как записи (подобно структурам в языке С). Для таких классов, счита
ют они, методы доступа лишь устанавливают и читают значения переменных, не
выполняя никаких проверок, поэтому совершенно излишни. В качестве примера
подобного класса можно привести класс J a v a . a w t . P o i n t , который содержит пе
ременные X и у, объявленные как p u b l i c , и который с самого начала задумывался
как объект, объединяющий две целочисленные переменные. В качестве компро
миссного решения можно порекомендовать избегать объявления переменных как
p u b l i c в классах со сложной структурой.
7 . 1 1 . Модификаторы 249
М е т о д и к а профессионалов
private
Этот модификатор означает, что переменная или метод доступны только для ме
тодов того же класса. Модификатор p r i v a t e обычно используется для определе
ния тех методов и переменных, к о т о р ы е необходимы для реализации логики клас
са, но которые не должны быть доступны пользователям.
protected
Д а н н ы й модификатор указывает на то, что переменная или метод могут быть дос
тупны методам того же класса и классов, принадлежащих тому же пакету. Пере
менные и методы, объявленные как p r o t e c t e d , могут быть видимы из-за границ
пакета посредством механизма наследования. Этот модификатор обычно прим
няется при определении тех методов и данных, которые в обычных условиях рас
сматриваются как p r i v a t e , но могут представлять интерес для программистов,
разрабатывающих дочерние классы.
О т с у т с т в у ю щ и й м о д и ф и к а т о р (по умолчанию)
Если модификатор области видимости не указан, обращаться к переменным или
методам имеют право методы, принадлежащие тому же классу или классам того же
пакета. П р и этом право доступа не наследуется подклассами. Область видимости
по умолчанию не распространяется за пределы пакета.
Прочие модификаторы
static
Д а н н ы й модификатор означает, что переменная или метод совместно использу
ются всеми экземплярами класса. П р и обращении к переменным и методам, объ
явленным как s t a t i c , указывается либо экземпляр класса, либо имя класса. Так,
например, если в классе Foo объявлена переменная класса b a r и созданы два эк
земпляра класса f o o l и f о о 2 , то для обращения к переменной b a r может исполь
зоваться одно из следующих выражений: f o o l . b a r , f оо2 . b a r и Foo , b a r . Все три
выражения обеспечивают доступ к одной и той же разделяемой переменной. В ка
честве примера метода класса (статического метода) можно привести M a t h , c o s ,
где Math — имя класса, а c o s — имя метода.
Статические методы могут обращаться только к переменным класса и статическим
методам другого класса. Чтобы иметь возможность работать с прочими компонен
тами, они должны создавать экземпляры соответствующих классов. В листинге 7.29
250 Глава 7. Объектно-ориентированное программирование..
показан код метода класса main. Этот метод может непосредственно обращаться к
статическому методу s t a t i c M e t h o d , но для обращения к методу regularMethod он
должен создать экземпляр класса.
pmi
Листинг 7.29. Statics.java
final
Приведенный в определении класса модификатор f i n a l означает, что класс не
может иметь подклассов. Такие сведения позволяют компилятору оптимизировать
вызовы методов и действия с переменными. Если модификатор f i n a l присутству
ет в объявлении переменной, он указывает, что ее значение не может изменяться
в процессе выполнения и она не может быть переопределена в подклассах. Таким
образом, переменная, объявленная как f i n a l , —это константа.
abstract
Данный модификатор применим к классам и методам и означает, что экземпляр
класса не может быть создан. Примеры использования модификатора a b s t r a c t
приведены в разделе, посвященном интерфейсам и абстрактным классам.
synchronized
Модификатор s y n c h r o n i z e d применяется для блокировки методов при многопо
токовом программировании. Метод, объявленный как s y n c h r o n i z e d , не может
одновременно использоваться двумя потоками. Дополнительную информацию о
работе с потоками вы найдете в главе 16.
volatile
Для эффективной работы многопотоковых программ Java позволяет методам соз
давать локальные копии переменных экземпляров, согласовывая вносимые изме
нения. Для некоторых типов данных (например, long) при выполнении многопо
токовых программ возникает риск частичного обновления переменной одним по
током перед обращения к ней другого потока. Модификатор v o l a t i l e предотв
ращает возникновение подобной ситуации.
7 . 1 1 . Модификаторы 251
transient
П е р е м е н н ы е , определенные как t r a n s i e n , не подлежат сериализации при записи
объектов на диск или передаче их по сети.
native
Данный модификатор указывает на то, что метод реализован на языке С или C++.
7.12. Резюме
Java— это объектно-ориентированный язык программирования общего назначе
ния. Не понимая основных принципов использования объектов, невозможно создать
программу на Java. В данной главе были описаны создание объектов, определение их
состояния (работа с переменными экземпляров) и поведения (создание методов). Пу
тем наследования можно строить иерархии классов, не повторяя фрагменты кода,
совместно используемые подклассами. Несмотря на то что в Java запрещено множест
венное наследование, и н т е р ф е й с ы предоставляют удобные средства для работы с
объектами, принадлежащим различным иерархиям классов. Классы, предназначен
ные для повторного использования, документируются с помощью j a v a d o c и для
удобства работы объединяются в пакеты.
Для тех программистов, которые никогда не работали с объектами, применение
средств Java сопряжено с определенными трудностями. Чтобы чувствовать себя ком
ф о р т н о при программировании объектов, надо освоить ряд новых понятий, т.е. сде
лать своеобразный "концептуальный рывок". Для освоения материала, изложенного в
главе 8, такой "рывок" не нужен; эта глава представляет собой описание базовых кон
струкций Java. Если вы ранее разрабатывали программы на C++, вы можете бегло
прочитать эт)^ главу, отмечая для себя отличия Java от известного вам языка.
СИНТАКСИС JAVA
В ЭТОЙ главе...
Простые типы.
Арифметические, логические операторы и операторы
сравнения.
Условные операторы и циклы.
Математические методы.
Ввод с клавиатуры и вывод на консольный терминал.
Выполнение программ, написанных на языках,
отличных от Java.
Ссылки.
Строки.
Массивы.
Векторы.
Пример построения бинарного дерева.
Исключения.
Sl/\ZJ^ZJ
8 . 1 . Синтаксические правила
Приступая к написанию реальных программ и намереваясь понять сообщения об
ошибках, выводимых компилятором, желательно знать "правила игры". В данном
разделе описаны некоторые лексические и грамматические правила Java.
Используя комментарии и выделяя фрагменты кода с помощью пробелов, симво
лов табуляции и перевода строки, можно добиться того, чтобы программа стала более
удобочитаемой. В Java поддерживаются блоки комментариев (текст, расположенный
между парами символов " / * " и " * / " ) и строки комментариев (текст, находящийся ме
жду парой символов " / / " и концом строки).
Пробелы, символы табуляции и перевода строки используются для отделения фраг
ментов кода друг от друга. С их помощью можно выделить выражение в отдельную
строку, отделить имя функции от параметров или расположить математические опера
торы в формате, удобном для чтения. Кроме того, с помощью пробелов и знаков табу
ляции можно сформировать отст)'пы в операторах цикла и условных операторах. При
мер Java-кода, использующего комментарии, пробелы и отстутгы, показан ниже.
254 Глава 8. Синтаксис Java
// Строка комментариев
boolean
Этот тип данных может принимать одно из двух значений: t r u e или f a l s e . В от
личие от C/C++, в Java логический тип отличается от целого. Например:
boolean flagl = false;
boolean flag2 = (6 < 7 ) ; // true
boolean flag3 = !true; // false
boolean flag4 =0; // Сообщение об ошибке при компиляции!
char
Содержит 16-битовое целое число, обозначающее символ в формате Unicode.
Символьное значение может представлять собой символ в одинарных кавычках,
шестнадцатеричный код unicode-символа (\uXXXX, где X— шестнадцатеричная
цифра) либо специальный символ \ Ь (Baskspace), \ t (табуляция), \ п (перевод
строки), \ f (перевод ф о р м а т а ) , \ г (возврат каретки), \ » (двойная кавычка), \ '
(одинарная кавычка), \ \ ( о б р а т н а я косая). Например:
char сО= 3 ;
char с1 = ' Q ' ;
char с2 = ' \uOOOO'; / / Наименьшее з н а ч е н и е
char сЗ = ' \ u F F F F ' ; / / Наибольшее з н а ч е н и е
char с4 = ' \ Ь ' ; / / Backspace
Описание стандарта Unicode можно найти по адресу h t t p : //www. U n i c o d e . o r g / .
byte
Данный тип представляет 8-битовое целое число со знаком. Для определения от
рицательных чисел используется дополнение до двух. Диапазон значений пере
менной типа b y t e — от -128 до -«-127.
short
Тип s h o r t представляет 16-битовое целое число со знаком. Для определения от
рицательных чисел используется дополнение до двух. Диапазон значений пере
менной типа s h o r t — от -32768 до +32767.
int
Этот тип представляет 32-битовое целое число со знаком. Для определения отри
цательных чисел используется дополнение до двух. Целые числа можно задавать в
десятичной системе счисления (числа 1, 10 и 100 представляются как 1, 10 и 100),
восьмеричной системе с префиксом О (числа 1, 10 и 100 представляются как 0 1 ,
256 Глава 8. Синтаксис Java
long
Д а н н ы й тип представляет 64-битовое целое число со знаком. Для определения от
рицательных чисел используется дополнение до двух. Длинные целые литералы
обозначаются буквой L, которая располагается после числового значения. Буква 1
нижнего регистра также поддерживается компилятором, но применять ее не ре
комендуется, поскольку при выводе на печать строчная буква 1 похожа на цифру 1.
Значения можно задавать в десятичном, восьмеричном и шестнадцатеричном
форматах. Допустимый диапазон значений переменной типа l o n g — от
L o n g . MIN_VALUE (-2"") до Long . MAX_VALUE (2''-1). Например:
long аО = 0L;
long al = -123451;
long а2 = OxBabeL; // Это не слово, а число
long аЗ = -067671;
За исключением c h a r , все целочисленные т и п ы ( b y t e , s h o r t , i n t и l o n g ) яв
ляются знаковыми. В отличие от С и C^-^-, в Java не поддерживаются беззнаковые
целые. Поэтому, используя целочисленные т и п ы (особенно b y t e и s h o r t ) , следу
ет следить, чтобы результат вычислений не превысил максимально допустимое
значение для данного типа. Так, например, если вы хотите представить день в го
ду, тип b y t e для этого не подходит, поскольку максимальное положительное чис
ло, которое может содержаться в переменной типа b y t e , равно 127. Вместо этого
вам надо использовать s h o r t , i n t или l o n g . Как правило, тип i n t вполне подхо
дит для большинства приложений.
float
Тип f l o a t представляет 32-битовое число с плавающей точкой в ф о р м а т е IEEE
754. Для обозначения литералов с плавающей точкой одинарной точности после
числового значения указывается буква f либо F. В приведенном ниже примере бу
ква f необходима, поскольку в противном случае константа будет интерпретиро
вана как число с плавающей точкой двойной точности, а при присвоении пере
менной типа f l o a t значение будет усечено.
float fO = - 1 . 2 3 f ;
Для указания степени числа 10 используется буква е либо Е. Н а п р и м е р , в первом
из приведен1гых ниже примеров переменной f l присваивается число 6.02x10"^ , а
во втором примере переменной f 2 присваивается число 4.5x10 .
8.2. Простые типы 257
float fl = 6.02E23F;
float f2 = 4.5e-17f;
Диапазон значений чисел с плавающей точкой лежит в интервале от
F l o a t . MIN_VALUE (1.4x10"'") до F l o a t .MAX_VALUE (3.4х10''). П р и вычислениях
значений с плавающей точкой исключения генерируются только в случае деления
на нуль. В классе F l o a t определены константы специального назначения —
POSITIVE_INFINITY, NEGATIVE_INFINITy и NaN (not-a-number не является чис
лом). Для сравнения со значением NaN следует использовать F l o a t . isNaN. Выра
жение ( F l o a t . NaN == F l o a t . NaN) всегда возвращает значение f a l s e . В специ
фикации IEEE определено, что данное значение должно возвращаться при любом
сравнении с NaN.
double
Данный тип представляет 64-битовое число с плавающей точкой в формате IEEE
754. Для обозначения литералов с плавающей точкой двойной точности можно
использовать d либо D, однако в большинстве случаев эта буква не указывается.
Н е к о т о р ы е п р и м е р ы приведены ниже.
double dO = 1.23;
double d2 = -4.56d;
double d3 = 6.02214E+23;
double d4 = le-99;
Диапазон значений чисел с плавающей точкой двойной точности лежит в интер
вале от D o u b l e . MIN_VALUE (4.9х10'''') до D o u b l e .MAX_VALUE (1.7х10'"'). Как и в
случае с f l o a t , при вычислениях с двойной точностью не генерируются исключе
ния. В классе D o u b l e определены константы специального назначения —
POSITIVE_INFINITY, NEGATIVE_INFINITY и NaN. Для сравнения со значением
D o u b l e . NaN следует использовать D o u b l e . isNaN.
double d = 3.1416;
float f = (float)d; // Преобразование для хранения
// в 32-битовой переменной
short S = (short)f; // Преобразование float в short
int i = s; // Преобразование в тип с большим диапазоном
// значений; явного указания типа не требуется
Для того чтобы вместо усечения производилось округление, надо использовать
соответствующие методы класса Math, к о т о р ы е будут рассмотрены ниже в этой главе.
Заметьте, что числовые значения не могут быть преобразованы в логические, а логи
ческие — в числовые. Ситуации, при которых требуется явное преобразование типов,
подробно описаны в д о к у м е н т е / a f а Language Specification, который находится по адре
су h t t p : / / J a v a . s u n . c o m / d o c s / b o o k s / j I s / .
Арифметические операторы
Основные операторы для работы с числами приведены в табл. 8.1. Вы, вероятно, за
метите, что в ней отсутствует оператор возведения в степень. Не стоит беспокоиться по
этому поводу: соответствующие операции реализованы посредством методов класса
Math. Заметьте также, что оператор + может использоваться для конкатенации строк.
можно записать
1 += 5;
X += 3 ;
Условные операторы
в языке Java определены условные операторы if, switch и "? :", которые приве
дены в табл. 8.2 и детально описаны в этом разделе. Если вы знакомы с С или C++, мо
жете не уделять этому материалу много внимания, поскольку данные операторы поч
ти идентичны соответствующим операторам C/C++, за исключением того, что усло
вия задаются как логические значения. Логические операторы, которые часто
используются в сочетании с условными операторами, приведены в табл. 8.3.
Оператор Описание
==, != Равенство, неравенство. Помимо сравнение двух простых типов,
== позволяет выявить, указывают ли две ссылки на один объект
<г <= f >/ >= Операции "меньше", "меньше или равно", "больше", "больше или
равно", выполняемые над целыми числами
&&/ Ii Логические операции AND, OR. Для повышения эффективности
вычисления производятся по сокращенной схеме
! Логическое о т р и ц а н и е
if {логическое_выраэн:ение) операция
if {логическое_вырал€ение) операция! e l s e операция2
После ключевого слова i f в скобках задается логическое выражение ( b o o l e a n ) .
Если логическое выражение принимает значение t r u e , выполняется операция,
следующая за ним. Если значение логического выражения равно f a l s e , выполня
ется операция, следующая за ключевым словом e l s e (если это слово присутствует
в составе оператора). Если в скобках после i f указано выражение, тип которого
отличен от b o o l e a n , компилятор выведет сообщение об ошибке. Этим Java отли
чается от С и C++, где любое значение, не равное нулю, интерпретируется как
t r u e . В следующем примере возвращается наибольшее из дв}'х целых чисел:
/ / См. Math.max
public static int max2(int nl, int n2) {
if (nl >= n2)
return(nl);
else
return(n2);
}
В состав выражения i f - e l s e можно включать несколько операций, объединяя их
с помощью фигурных скобок. Н а п р и м е р :
8.3. Операторы, условные операторы и циклы 261
statementZ;
}
}
// Третий тип отступа
public SomeType someMethod(...)
{
if
{
statementl;
statementN;
}
else
{
statementA;
StatementZ;
}
}
Пи необходимости вы можете использовать в условном о п е р а т о р е несколько
сравнений, объединяя их с помощью логических операторов && (логическое И,
или операция AND) либо | | (логическое И Л И , или операция OR). Как и в языках
C/C++, эти операторы реализуют вычисления по "сокращенной схеме". Это зна
чит, что результирующее значение возвращается в тот момент, когда появляется
достаточная и н ф о р м а ц и я для вычисления результата, даже если не все сравнения
были выполнены. Так, например, если два оператора сравнения объединены с по
мощью && и выражение слева от && равно f a l s e , возвращается результат f a l s e ;
при этом оператор сравнения справа от && не выполняется. Аналогично, выраже
ние, сформированное посредством оператора | |, возвращает t r u e , если его левая
часть равна t r u e . Сказанное иллюстрируется следующим примером:
public static int max3(int nl, int п2, int пЗ) {
if ((nl >= n2) && (nl >= пЗ))
return(nl);
else if ((n2 >= nl) && (n2 >= n3))
return(n2);
else
return(n3);
}
Логический оператор, обозначаемый с помощью единичного символа & или |, ука
зывает на то, что должны быть вычислены оба операнда. Однако такие операции
применяются редко и их легко принять за операторы поразрядной логики.
логическое__выражение ? значение_1кеп: значение_е15е
Поскольку выражение i f не возвращает значение, Java предоставляет оператор, с
помощью которого вычисленное значение может быть присвоено переменной.
Приведенный ниже о п е р а т о р
if (someCondition)
someVar = valuel;
else
someVar = value2;
8.3. Операторы, условные операторы и циклы 263
Далее в этой главе при обсуждении массивов мы рассмотрим более простой способ
преобразования целого числа в строковое представление. Ошибки, возникающие
при использовании оператора s w i t c h , чаще всего связаны с тем, что пользователь
не учитывает важную особенность данного оператора: при совпадении значения
выражения со значением c a s e выполняются не только операторы, следующие за
текущим c a s e , но и за всеми остальными c a s e . В некоторых ситуациях, подоб
ных приведенному ниже примеру, такое поведение оператора s w i t c h позволяет
упростить программу.
switch(val) {
case testl:
case test2:
actionForTestland2();
}
264 Глава 8. Синтаксис Java
result = "zero";
break;
case 1: System.out.println("one");
result = "one";
break;
Циклы
в языке Java определены те же основные циклы, что и в C/C++: w h i l e , do и f o r .
Эти языковые конструкции перечислены в табл. 8.4 и детально описаны в данном
разделе. Кроме того, Java также поддерживает о п е р а т о р ы b r e a k и c o n t i n u e , кото
рые используются соответственно для выхода из цикла и принудительного выполне
ния следующей итерации.
О п е р а т о р while
О п е р а т о р w h i l e п р о в е р я е т логическое выражение, заданное в скобках, и, если
вырг1жение возвращает значение t r u e , выполняет тело цикла. Например, сле
дующий метод выводит числа в интервале от О до max:
p u b l i c s t a t i c v o i d l i s t N u m s l ( i n t max) {
i n t i = 0;
w h i l e ( i <= max) {
System.out.println("Number: " + i ) ;
i++;
}
}
2: two
3: three
4: four
Оператор do
Оператор do отличается от w h i l e тем, что проверка логического выражения про
водится после выполнения тела цикла. Это означает, что тело цикла обязательно бу
дет выполнено хотя бы один раз. Ниже приведен вариант рассмотренного выше ме
тода, в котором использован оператор do. Результат вызова l i s t N u m s 2 (5) будет та
ким же, как и раньше, но если вы вызовете l i s t N u m s 2 ( - 5 ) , то увидите сообщение
"Number : О". Для сравнения: при вызове l i s t N u m s l (-5) не будет выведено ни од
ного значения. Причина заключается в том, что оператор do проверяет условие по
сле выполнения цикла, в то время как оператор w h i l e делает это до выполнения
цикла. При вызове l i s t N u m b e r (-5) тело цикла не будет выполнено ни разу.
public static void listNums2(int max) {
int i = 0;
do {
System.out.println("Number: " + i ) ;
i++;
} while (i <= max); // Точка с запятой должна присутствовать
}
Как правило, большинство начинающих программистов делают одну и ту же
ошибку: не указывают точку с запятой после окончания оператора d o .
Ц и к л for
Для организации цикла с целочисленным счетчиком чаще всего используется опе
р а т о р f o r . П р и выполнении цикла сначала выполняется инициализация счетчика.
Затем, то тех пор, пока логическое выражение возвращает значение t r u e , выпол
няется тело цикла и изменяется значение счетчика. Н и ж е приведен код метода
l i s t N u m s 3 , который при передаче ему положительных значений дает тот же ре
зультат, что и два предыдущих примера.
public static void listNums3(int max) {
for(int i=0; i<max; i++) {
System.out.println("Number: " + i ) ;
}
}
Java позволяет не указывать любое из трех (или все три) выражений в скобках по
сле ключевого слова f o r . Если логическое выражение пропущено, считается, что
оно возвращает значение t r u e . Следующие два оператора эквивалентны:
for(;;) { / * т е л о цикла */ }
и
while(true) { /* тело цикла */ }
Такая форма оператора f o r применяется в тех случаях, когда условие завершения
цикла трудно представить в виде логического выражения. Вместо этого в тело
цикла помещается условный о п е р а т о р , содержащий r e t u r n либо b r e a k .
8.3. Операторы, условные операторы и циклы 267
Листинг8.1. DropBall.Java
Константы
public static Hnal d o u b l e E
Эта константа равна основанию натурального логарифма, т.е. 2.7182818284590452354.
public static d o u b l e c e i l ( d o u b l e n u m )
public static d o u b l e floor(double num)
Метод c e i l возвращает d o u b l e - п р е д с т а в л е н и е наименьшего из целых чисел,
большего или равного указанному числу. Метод f l o o r возвращает d o u b l e -
представление наибольшего из целых чисел, не превышающих указанное число.
public static e x p ( d o u b l e n u m )
Данный метод возвращает е"""\
8.4. Класс Math 269
Тригонометрические методы
public static double sin(double radians)
public static double cos(double radians)
public static double tan(double radians)
Указанные методы возвращают соответственно синус, косинус и тангенс указанно
го числа, которое интерпретируется как угол в радианах.
Biglnteger И BigDecimal
Java поддерживает два числовых формата произвольной точности: Java.math.
B i g l n t e g e r и Java .math . BigDecimal. Эти классы содержат методы, позволяющие
выполнять сложение, умножение, деление, возведение в степень, находить наиболь
ший общий делитель и производить многие другие операции над такими числами.
Подробно эти классы описаны в документации, основной же их характеристикой яв
ляется тот факт, что они позволяют получить требуемый уровень точности. Так, на
пример, в B i g l n t e g e r каждая цифра является значащей и такое понятие, как пере
полнение, для этого класса отсутствует. В качестве примера в листинге 8.3 показано
использование B i g l n t e g e r для представления точного значения N ! (факториала N,
т.е. произведения N* (N-1) * (N-2) * . . . *1) для различных N. Результаты вычисле
ний представлены в листинге 8.4.
Листинг 8.3. F a c t o r i a l . j a v a
import Java.math.Biglnteger;
/** Вычисление факториала с помощью B i g l n t e g e r . */
public class Factorial {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
f o r ( i n t i = l ; i<=256; i'^=2) {
S y s t e m . o u t . p r i n t l n ( i + "!=" + f a c t o r i a l ( i ) ) ;
}
}
8.5. Ввод и вывод 271
Внимание!
Следует отличать пакет java .math, содержащий классы Biglnteger
и BlgDeclmal, ОТ класса java. lang.Math. Класс Math используется
достаточно часто. Он содержит методы общего назначения, позво
ляющие выполнять математические вычисления.
import java.text.*;
/** Форматирование чисел посредством DecimalFormat. */
Л и с т и н г 8 . 6 . Выходные д а н н ы е NumFormat
Символ Описание
О Резервирует место для ц и ф р ы
# Резервирует место для ц и ф р ы . Ведущий или завершающий нуль, она не
выводится
Расположение десятичной точки
/ Указывает позицию, в которой должна отображаться запятая
Знак "минус"
Е Указывает позицию, в которой мантисса должна отделяться от степени
% Значение умножается на 100 и отображается как величина в процентах
Внимание!
import java.io.*;
/** Класс, который упрощает запуск внешних процессов из
^ приложений. Программы можно запускать тремя способами:
* <0L>
* <LI><B>exec</B>: управление возвращается сразу после
* вызова, даже если выполнение команды еще продолжается.
* Это удобно для таких задач, как вывод файла на печать.
* <LI><B>execWait</B>: управление не возвращается до тех
* пор, пока выполнение команды не будет завершено.
* Это удобно для последовательности команд, когда
* следующая команда зависит от результатов предыдущей
* (например, <CODE>javac</CODE> и <CODE>java</CODE>).
* <LI><B>execPrint</B>: команда выполняется, и выводятся
* результаты. Это удобно для команды UNIX
* <CODE>ls</CODE>.
* </0L>
* Заметьте, что переменная PATH не используется, поэтому вы
* должны задать <В>полный</В> путь. Кроме того, команды
* оболочки не поддерживаются. Например, в системе UNIX
* три приведенных примера будут иметь вид
* <0L>
* <LI><PRE>Exec.exec("/usr/ucb/lpr Some-File");</PRE>
* <LI><PRE>Exec.execWait("/usr/local/bin/javac Foo.java");
* Exec.execWait("/usr/local/bin/Java Foo");</PRE>
* <LI><PRE>Exec.execPrint("/usr/bin/ls -al");</PRE>
* </0L>
if (verbose) {
printSeparator();
System.out.println("Executing '" + command + " ' . " ) ;
}
try {
// Запуск команды; немедленная передача управления.
Process р = Runtime.getRuntime().exec(command);
} else if (wait) {
try {
System.out.println ( " " ) ;
int returnVal = p.waitFor();
if (returnVal != 0) {
if (verbose) {
printError(command);
}
return(false);
}
} catch (Exception e) {
if (verbose) {
printError(command, e ) ;
}
return(false);
}
}
} catch (Exception e) {
if (verbose) {
printError(command, e ) ;
}
return(false);
8.6. Выполнение программ, отличных от Java 279
}
return(true);
}
Листинг8.8. ExecTest.Java
Executing '/usr/local/bin/netscape'.
Executing '/usr/bin/ls'.
Output: Exec.class
Output: Exec.Java
Output: ExecTest.class
Output: ExecTest.Java
Output: Test.Java
Executing '/usr/bin/ls'.
Output: Exec.class
Output: Exec.Java
Output: ExecTest.class
Output: ExecTest.Java
Output: Test.class
Output: Test.Java
8.7. Ссылки
Значения, которые являются объектами, т.е. не относящиеся к простым типам
(экземпляры классов или массивы), называют ссылочными значениями, или просто
ссылками. П р и обсуждении программ на Java принято говорить, что значение той или
иной переменной представляет собой объект. Поскольку в Java не существует опера
ций, связанных с прямым присвоением значений указателям, бытует мнение, что в
Java указатели отсутствуют. Это ошибка! ^Вг^ значения, не принадлежащие к простым
типам, реализуются только с помощью указателей. Программистам, имеющим опыт в
разработке программ на С, легче будет понять реальное положение вещей, если ска
зать, что значения переменных, не относящихся к простым типам, указывают на объ
екты. В Java не существует отличия между переменной, codej)Maiu,eu объект, и перемен
ной, указывающей на объект.
Если вы еще не знакомы с указателями, можете себе представить их следующим
образом. Чтобы повысить эффективность работы программ, Java не выполняет копи
рование больших и сложных объектов каждый раз, когда они передаются от одного
метода другому. Вместо объектов передаются данные, описывающие их расположе
ние. Если вы работали с указателями на других языках программирования, вам надо
запомнить, что Java не позволяет непосредственно задавать значения указателей. Ес
ли переменная ссылается на объект, невозможно изменить ее так, чтобы она ссыла
лась на объект другого типа.
8.7. Ссылки 281
Листинг 8.12.ModificationTest.Java
import Java.awt.Point;
public class ModificationTest extends.ReferenceTest {
public static void main(String[] args) {
Point pi = new Point(1, 2 ) ; // Переменная pi ссылается
/ / н а объект Point.
Point p2 = pi; // В переменной p2 хранится еще одна
// ссылка на тот же объект Point,
print("р1", р1); // (1, 2)
print("р2", р2); // (1, 2)
munge(p2); // Модификация полей объекта Point.
printC'pl", pi) ; // (5, 10)
print("р2", p2); // (5, 10)
}
public static void munge(Point p) {
p.x = 5;
p.У = 10;
}
}
На з а м е т к у
Если вы полностью поняли это правило, то, наверное, скажете, что Java передает
параметры по значению, но сами эти значения являются ссылками.
8.7. Ссылки 283
Оператор instanceof
Оператор i n s t a n c e o f возвращает значение t r u e , если операнд в его левой части
соответствует классу, или интерфейсу, указанному в правой части. Соответствие в
данном случае означает, что объект является экземпляром указанного класса или его
подкласса, либо, если вместо класса задан интерфейс, объект является экземпляром
класса, реализующего этот интерфейс, либо его подкласса. Например:
if (item instanceof Breakable) {
add(item, chinaCabinet);
}
При использовании оператора instanceof возникает одна проблема: при напи
сании кода необходимо знать имя класса, на принадлежность к которому выполняется
проверка. Для того чтобы подобная задача могла быть решена в любой ситуации, в
Java 1.1 была реализована динамическая версия проверки на принадлежность к клас
су. Она состоит в вызове метода islnstance объекта Java. lang.Class и передаче
ему требуемого объекта. Пример использования метода islnstance приведен в лис
тинге 8.14, а результаты выполнения кода — в листинге 8.15.
Листинг 8.14.Instanceof.Java
interface Barking {}
class Mammal {}
System.out.println("\nTesting islnstance:");
Class barkingClass = Barking.class;
Class dogClass = Dog.class;
Class retrieverClass = Retriever.class;
System.out.println(" Does a retriever bark? " +
barkingClass.islnstance(rover));
System.out.println(" Is a retriever a dog? " +
dogClass.islnstance(rover));
System.out.println(" Is a dog necessarily a retriever? " +
retrieverClass.islnstance(new Dog ()));
284 Глава 8. Синтаксис Java
Testing islnstance:
Does a retriever bark? true
Is a retriever a dog? true
Is a dog necessarily a retriever? false
public int c o m p a r e T o ( S t r i n g c o m p a r i s o n )
public int c o m p a r e T o ( O b j e c t object)
Метод c o m p a r e T o сравнивает текущую строку с указанной строкой. Сравнение
осуществляется посимвольно с учетом порядка следования символов в Unicode.
Если строки эквиваленты (содержат одинаковые символы), метод возвращает зна
чение 0. Отрицательное значение указывает на то, что текущая строка лексико
графически меньше, чем указанная строка. Возвращаемая положительная величи
на означает обратное. Конкретное число либо равно разности межд)^ Unicode-
значениями первых несовпадающих символов, либо, если первая строка полно
стью содержится в начале второй строки, — разности длин строк. Для того чтобы
обеспечить соответствие интерфейсу C o m p a r a b l e , в Java 1.2 был добавлен вари
ант метода c o m p a r e T o , которому в качестве параметра передается объект Ob j e c t .
Он действует так же, как и метод c o m p a r e T o ( S t r i n g c o m p a r i s o n ) , но если па
раметр не является строкой, генерируется исключение C l a s s C a s t E x c e p t i o n .
286 Глава 8 . Синтаксис Java
public b o o l e a n equals(Object c o m p a r i s o n )
Если объект c o m p a r i s o n не является строкой, метод e q u a l s возвращает значение
f a l s e . В противном случае выполняется посимвольное сравнение двух строк. Таким
образом, для сравнения строк должен всегда использоваться метод e q u a l s , а не
оператор ==. Как показано в примере, содержащемся в листинге 8.17, проверка с
помощью оператора == дает отрицательный результат, а проверка посредством ме
тода e q u a l s — положительный. Заметьте также, что различные экземпляры строк,
заданных с помощью литерала, не обязательно будут распознаны оператором == как
равные, потому что компилятор может по-разному преобразовать эти константы.
Внимание!
public b o o l e a n equalsIgnoreCase(String c o m p a r i s o n )
Данный метод осуществляет посимвольное сравнение строк без учета регистра
символов.
Листинг 8.16.StringTest.Java
str.substring(3,8)) ;
System.out.println(" toLowerCase () " +
str.toLowerCase());
System.out.println(" toUpperCase() " +
str.toUpperCase ());
System.out.println { " trim() " +
str.trim());
System.out.println("\nString is still \"" + str + "\"\n")
Конструкторы
public StringO
Данный конструктор создает строку нулевой длины (но не объект n u l l ) .
8.9. Массивы
Массивы — это простые и эффективные структуры данных, имеющиеся практиче
ски во всех языках программирования. Массивы обеспечивают доступ к наборам дан
ных простых типов или объектов и позволяют обращаться к различным значениям
посредством одного идентификатора. Доступ к различным элементам массива осуще
ствляется за одно и то же время. Массивы реализуются как объекты, обладающие сле
дующими свойствами.
• Длина массива содержится в поле l e n g t h .
• Элементы массива могут соответствовать объектам Object либо переменным
конкретных типов.
• Подобно объектам, ссылки на массивы передаются при вызове методов.
Нумерация элементов массивов начинается с нуля, поэтому если в массиве содер
жится 10 элементов, то их индексы лежат в диапазоне от О до 9. Как правило, массивы
создаются в два этапа: сначала выделяется память под элементы массива, а потом
этим элементам присваиваются значения. Если создается массив из простых типов
данных, каждый элемент массива инициализируется значением по умолчанию для
этого типа. При создании массива объектов его элементы инициализируются значе
ниями n u l l . Присваивая элементам значения, следите за тем, чтобы индекс оставал
ся в пределах массива.
292 Глава 8 . С и н т а к с и с Java
Часто разработчики упускают из виду второй этап создания массива. В этом случае
при обращении к элементу массива генерируется исключение N u l l P o i n t e r E x c e p t i o n .
Внимание!
i n t [ ] v a l u e s = { 10, 100 };
P o i n t [ ] p o i n t s = { new P o i n t ( 0 , 0),
new P o i n t ( 2 , 4),
new P o i n t ( 4 , 8),
... };
Листинг 8 . 1 8 . G o l f . J a v a
/•к-к Р е з у л ь т а т ы и г р в г о л ь ф . */
Многомерные массивы
в языке программирования Java многомерные массивы реализуются как "массивы
массивов", и в этом заключается очередное сходство между Java и C++. Следующий
фрагмент программы объявляет массив, состоящий из 12x14 элементов, и заполняет
его значениями.
i n t [ ] [ ] v a l u e s = new i n t [ 1 2 ] [ 1 4 ] ;
f o r ( i n t i = 0 ; i < 1 2 ; i++) {
f o r ( i n t j = 0 ; j < 1 4 ; j++) {
values[i][j] = someFunctionOf(i, j ) ;
}
}
Для обращения к конкретным элементам используются выражения наподобие
следующих:
i n t someVal = v a l u e s [ i ] [ j ] ; // i<12, j<14
v a l u e s [ i ] [ j ] = someint;
He указывая второй индекс, можно получить доступ сразу к целому массиву.
i n t [ ] someArray = v a l u e s [ i ] ; // 0<=i<=ll
v a l u e s [ i ] = someOtherArray;
Аналогичным образом создаются массивы с размерностью больше двух. Вложен
ные массивы не обязательно должны иметь одинаковую длину. Чтобы реализовать
"непрямоугольные" массивы, надо не указывать второй размер. Ниже приведен при
мер такого массива.
S t r i n g [ ] [ ] names = new S t r i n g [ 3 ] [ ] ;
S t r i n g [ ] nameO = { " J o h n " , " Q . " , " P u b l i c " };
S t r i n g [ ] namel = { " J a n e " , "Doe" };
S t r i n g [ ] name2 = { " P e l e " };
n a m e s [ 0 ] = nameO; / / 3 э л е м е н т а
names[1] = namel; / / 2 элемента
n a m e s [ 2 ] = name2; / / 1 элемент
8.10. Векторы 295
8.10. Векторы
Массивы — чрезвычайно полезное средство Java, однако они имеют один недоста
ток: в процессе выполнения программы нельзя увеличить размеры массива. Для того
чтобы преодолеть это ограничение, в Java реализованы "расширяемые" массивы, или
векторы, которые реализуются посредством класса j a v a . u t i l . V e c t o r . Класс V e c t o r
отличается тем, что позволяет добавлять или удалять элементы в любой позиции.
Обычно он используется для тех же целей, что и связные списки. Класс V e c t o r обес
печивает доступ к конкретному элементу за фиксированное время, однако интервал
времени, который требуется для включения элемента в начало или в середину
V e c t o r , пропорционален общему числу элементов.
Н и ж е описаны основные методы класса V e c t o r ; пример их использования будет
приведен в следующем разделе. О б р а т и т е внимание, что методы для извлечения зна
чений возвращают тип O b j e c t .
Конструкторы
p u b l i c Vector()
p u b l i c Vector(int initialCapacity)
p u b l i c Vector(int initialCapacity, int c a p a c i t y l n c r e m e n t )
Эти конструкторы создают пустой объект V e c t o r . Если при вызове конструктора
емкость вектора (число элементов, содержащихся в нем) не указана, она устанав
ливается равной 10 элементам, однако при необходимости Java автоматически ко
пирует данные в массив большего размера.
Методы
p u b l i c void a d d E l e m e n t ( O b j e c t object)
p u b l i c v o i d i n s e r t E l e m e n t A t ( O b j e c t object, int i n d e x )
p u b l i c v o i d s e t E l e m e n t A t ( O b j e c t object, int i n d e x )
Д а н н ы е с и н х р о н и з и р о в а н н ы е методы добавляют элементы к объекту V e c t o r . Ме
тод a d d E l e m e n t присоединяет объект к концу массива, а остальные два метода
включают его в указанной позиции. П р и выполнении метода i n s e r t E l e m e n t A t
объекты с индексами, равными и большими, чем указанный, сдвигаются вправо на
один элемент. Метод s e t E l e m e n t A t замещает элемент в указанной позиции.
p u b l i c int capacityO
Метод c a p a c i t y возвращает текущий размер массива, в котором хранятся эле
менты объекта V e c t o r . П р и добавлении новых элементов размер массива может
быть увеличен.
296 Глава 8. Синтаксис Java
p u b l i c void setSize(int n e w S i z e )
Синхронизированный метод s e t S i z e задает размер объекта V e c t o r . От метода
e n s u r e C a p a c i t y он отличается тем, что если в объекте V e c t o r содержится
большее число элементов, чем указано, он усекается.
p u b l i c int size()
Метод s i z e возвращает число элементов в объекте V e c t o r (текущий размер мас
сива может превышать число элементов).
p u b l i c void trimToSize()
Данный с и н х р о н и з и р о в а н н ы й метод устанавливает размеры массива, в котором
хранятся элементы объекта V e c t o r , так, что в нем может находиться число эле
ментов, в точности равное текущему. Если в процессе работы элементы могут до
бавляться или удаляться, использовать этот метод не следует, однако, он поможет
сэкономить память, если число элементов в объекте V e c t o r фиксировано.
Многие методы класса V e c t o r синхронизированы для того, чтобы предотвратить
проблемы, возникающие п р и попытке обращения к одним и тем же данным из раз
ных потоков. Синхронизация снижает производительность программы, поэтому в
Java 2 предусмотрены два н е с и н х р о н и з и р о в а н н ы х класса A r r a y L i s t и L i n k e d L i s t ,
которые действуют аналогично классу V e c t o r . Однако эти классы доступны только в
JDK 1.2 и новых версиях данного пакета и не поддерживаются большинством броузе
ров, в среде которых выполняются аплеты. Дополнительная и н ф о р м а ц и я о синхро
низации и поддержке многопотоковых программ приведена в главе 16.
import Java.util.Vector;
return(leftChild);
Теперь, когда общая стр)^тст)ра данных готова, напишем тестовый пример. На рис. 8.1
показано простое дерево, а в листинге 8.23 представлен код класса, реализующего
N o d e O p e r a t o r и использующего классы Node и Leaf. Данный класс не выполняет ника
кой обработки, а лишь выводит значения каждого из просмотренных узлов. Результаты
работы этого класса показаны в листинге 8.24.
Предложение
Листинг 8.23.TreeTest.Java
8.12. Исключения
В Java реализовано мощное средство обработки ошибок — исключения. Исключе
ние может быть сгенерировано в одном блоке кода, а обработано в другом блоке или
даже в другом методе (из которого вызывается метод, генерирующий исключение).
Исключения в Java отличаются от исключений в C++. Во-первых, в Java в конструкции
t r y / c a t c h предусмотрен блок f i n a l l y ; в него помещается фрагмент кода, который
должен быть выполнен независимо от того, было ли сгенерировано исключение.
Второе отличие заключается в том, что, создавая метод, можно потребовать от раз
работчика, применяющего его, включить в программу обработку исключения, кото
рое может генерировать этот метод. Если разработчик не выполнит данное требова
ние, код программы не будет скомпилирован.
Обработка исключения
Простейшая конструкция, предназначенная для обработки исключения, имеет
следующий вид:
try {
// Выражение 1
// Выражение 2
} catch(SomeException someVar) {
handleTheException(someVar);
}
Например, конструктор j a v a . n e t . URL может генерировать исключение J a v a ,
n e t . Malf o r m e d U R L E x c e p t i o n , a метод r e a d L i n e класса j a v a . i o . Buf f e r e d R e a d e r —
исключение J a v a . i o . l O E x c e p t i o n . Код, представленный в листинге 8.25, использует
как конструтстор URL, так и метод r e a d L i n e , поэтому в нем предусмотрена обработка
обоих возможных исключений. Как видно из листинга 8.26, исключение
Malf o r m e d U R L E x c e p t i o n генерируется в результате проверки формата URL. Попытка
скопировать ресурс и даже проверить, существует ли он, не предпринимается. Приме
ры обращения к файлам по сети будут приведены в главе 17, посвященной сетевому
программированию.
p u b l i c c l a s s URLTest {
public s t a t i c void main(String[] args) {
URLTest t e s t = new URLTest Ob
t e s t . getURL () ;
test.printURLO ;
}
p r i v a t e URL u r l = n u l l ;
8.12. Исключения 303
p u b l i c URL getURLО {
i f ( u r l != n u l l ) {
return(url);
}
System.out.print("Enter URL: " ) ;
System.out.flush() ;
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
8.12. Исключения 305
Выражение finally
После блоков c a t c h можно указать блок f i n a l l y , который будет выполняться в
любом случае, независимо от того, было ли сгенерировано исключение. Он получает
управление даже тогда, когда в блоке t r y или c a t c h присутствуют выражения b r e a k ,
c o n t i n u e или r e t u r n . В листинге 8.28 показан третий вариант метода getURL, ис
пользующий блок f i n a l l y .
p u b l i c URL getURLО {
i f ( u r l != n u l l ) {
return(url);
}
System.out.print("Enter URL: " ) ;
System.out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String urlString = null;
try {
urlString = in.readLine();
url = new URL(urlString);
} catch(MalformedURLException mue) {
System.out.println(urlString + " is not valid.\n" +
"Try again.");
getURL();
} catch(lOException ioe) {
System.out.println("lOError when reading input: " + ioe)
ioe.printStackTrace0; // Можно пропустить return(null)
} finally {
return(url);
}
}
306 Глава 8. Синтаксис Java
!
I Листинг 8 . 2 9 . N e g a t i v e L e n g t h E x c e p t i o n . Java
import java.io.*;
public NegativeLengthException() {
super("Negative dimensions not permitted.");
}
public NegativeLengthException(String message) {
super(message) ;
Необрабатываемые исключения
Исключения, о которых шла речь выше считаются обрабатываемыми. При созда
нии программы вы обязаны предусмотреть их обработку. Java также включает два
класса необрабатываемых исключений: E r r o r и R u n t i m e E x c e p t i o n . Вы имеете пра
во включить в создаваемый класс соответствующие обработчики, но не обязаны это
делать, поскольку данные исключения могут возникать в самых различных точках
308 Глава 8. Синтаксис Java
8.13. Резюме
В данной главе рассказывалось о синтаксисе Java-программ. Здесь были вкратце рас
смотрены простые и ссылочные типы, операторы, класс Math, строки, массивы, векто
ры и исключения. Освоив этот материал и имея общее представление об объектно-
ориентированном программировании (глава 7), вы можете приступать к изучению кон
кретных вопросов программирования на Java, рассмотренных в следующих главах.
АПЛЕТЫ
И ОСНОВНЫЕ
ДЕЙСТВИЯ
С ГРАФИКОЙ
В ЭТОЙ главе...
• Java Plug-In.
• Создание графических приложений. Java-программы,
выполняющиеся независимо от броузера.
• Рисование, использование цвета, шрифтов и областей
отсечения.
З а п и с ь на л о к а л ь н ы й д и с к
В некоторых случаях броузер записывает в кэш информацию, в том числе данные,
загруженные аплетами, но эта процедура никак не контролируется аплетом.
Установка сетевых соединений за исключением соединений с сервером, с которо
го аплет был загружен
Это ограничение не позволяет аплету извлекать и н ф о р м а ц и ю из сети, защищен
ной брандмауэром.
Шаблон аплета
Т и п и ч н а я структура аплета представлена в листинге 9.L Как правило, аплет со
держит определения переменных экземпляра, методы i n i t и p a i n t . Метод i n i t ав
томатически вызывается броузером в процессе создания аплета. Затем, когда аплет
готов к выводу информации, вызывается метод p a i n t . Метод p a i n t также автомати
чески вызывается в тех случаях, когда изображение на некоторое время оказалось пе
р е к р ы т ы м другим окном и должно быть восстановлено, а также при добавлении ком
понентов. Этот метод может быть вызван и программным путем. Реализации методов
i n i t и p a i n t , используемые по умолчанию, не выполняют никаких действий; пред
полагается, что при создании аплета эти методы будут переопределены. Помимо
i n i t и p a i n t , существуют и другие предопределенные методы (они будут рассмотре
ны далее в этой главе), однако, чтобы создать простой аплет, достаточно переопре-
9.2. Создание an лета 313
делить два указанных метода. Как вы знаете, в Java, в отличие от таких языков, как С и
C++, разрешается инициализировать переменные экземпляра при их определении в
теле класса, но поступать таким образом при создании аплета не рекомендуется. Дело
в том, что н е к о т о р ы е т и п ы графических объектов запрещается инициализировать до
вызова метода i n i t . Поэтому, вместо того чтобы запоминать, какие из объектов
можно инициализировать непосредственно, лучше п р и н я т ь за правило выполнять
всю инициализацию в теле метода i n i t . В отличие от переменных экземпляра, дос
тупных всем методам класса, переменные, которые нужны лишь на время выполне
ния i n i t , следует объявлять как локальные.
import Java.applet.Applet;
import j a v a . a w t . * ;
/ / Объявления переменных.
public void i n i t ( ) {
/ / Инициализация переменных, з а г р у з к а изображений и т . д .
}
p u b l i c v o i d p a i n t ( G r a p h i c s g) {
/ / Операции р и с о в а н и я .
Шаблон HTML'фaйлa
После создания и компиляции аплета полученный файл класса должен быть связан с
Web-страницей. Для этого используется дескриптор APPLET, показанный в листинге 9.2.
Подробнее данный дескриптор будет описан в разделе 9.6, сейчас же заметьте, что
обязательный атрибут CODE задает имя файла класса Java, кроме него в составе деск
риптора также должны присутствовать атрибуты WIDTH и HEIGHT. Если аплет поме
щен не в тот каталог, в котором находится связанный с ним HTML-документ, для ука
зания расположения аплета должен использоваться атрибут CODEBASE. После того
как аплет скомпилирован и связан с Web-страницей, загрузка этой страницы в броузер
автоматически приведет к запуску аплета. Разработчики часто присваивают одинако
вые имена аплету и связанному с ним Web-документу (например, HTML-файл
A p p l e t T e m p l a t e . h t m l и аплет A p p l e t T e m p l a t e . c l a s s ) , но на самом деле имена
аплета и Web-страницы никак не связаны. Более того, в одном HTML-документе мо
жет содержаться несколько аплетов.
Скомпилированный файл класса аплета ( f i l e , c l a s s ) должен быть доступен че
рез Web; на исходный код это требование не распространяется. Если исходные фай
лы и файлы классов расположены в разных каталогах, помните, что все несистемные
файлы классов, используемые аплетом, должны быть доступны из Web и находиться
314 Глава 9 . Аплеты и основные д е й с т в и я с графикой
Л и с т и н г 9 . 2 . HTML-шаблон
</BODY>
</HTML>
того, в этом методе аплету присваивается метка и выводится строка текста. Метод
paint выводит изображение, располагая его на 50 пикселей ниже верхнего края об
ласти, выделенной для аплета. В листинге 9.4 представлен HTML-код документа, со
держащего аплет, а результаты выполнения аплета в среде броузера Internet Explorer
5.0 (в системе Windows 2000) показаны на рис. 9.1.
import Java.applet.Applet;
import java.awt.*;
Стандартный вывод
в Netscape Navigator и н ф о р м а ц и я , которая выводится в стандартный выходной
поток, представляется в специальном окне. Для того чтобы отобразить это окно на
экране, надо выбрать пункт Java Console в меню Window. В Netscape C o m m u n i c a t o r
пункт J a v a Console находится в меню Tools, которое, в свою очередь, вызывается по
средством меню Communicator. На рис. 9.2 показано, как выглядит окно Java Console
после выполнения аплета J a v a Jump. Ч т о б ы отобразить в окне список допустимых
команд, надо ввести символ "?".
Оконаниетабл. 9.1
controlText Цвет для вывода текста
desktop Цвет ф о н а для рабочего стола
inactiveCaption Ц в е т ф о н а для заголовков неактивных окон
inactiveCaptionBorder Ц в е т обрамления для заголовков неактивных окон
inactiveCaptionText Цвет для вывода текста в заголовках неактивных окон
info Ц в е т фона для вывода вспомогательного текста
(подсказок)
infoText Цвет вспомогательного текста (подсказок)
menu Цвет фона для невыбранных пунктов меню. Для вы
бранного пункта используется t e x t H i g h l i g h t
menuText Цвет для вывода текста невыбранных пунктов меню.
Для выбранного пункта используется
textHighlightText
scrollbar
Цвет ф о н а для полос прокрутки
text
Ц в е т ф о н а для вывода текстовых компонентов
textHighlight Цвет фона для вывода "подсвеченного" текста.
"Подсвеченным" считается выделенный текст в по
лях редактирования, выбранные пункты меню и
п р о ч и е элементы
textHighlightText Цвет "подсвеченного" текста
textlnactiveText Цвет текста для неактивных компонентов
textText Цвет текста для текстовых компонентов
window Ц в е т ф о н а для окон
windowBorder Цвет обрамления для окон
windowText Цвет текста, отображаемого в окнах
public U R L getCodeBaseO
public U R L g e t D o c u m e n t B a s e O
Эти методы возвращают и н ф о р м а ц и ю о расположении аплета ( g e t C o d e B a s e ) и
HTML-документа, содержащего аплет ( g e t D o c u m e n t B a s e ) .
322 Глава 9. Аплеты и основные действия с графикой
p u b l i c C o m p o n e n t g e t C o m p o n e n t A t ( i n t х, int у)
Метод g e t C o m p o n e n t A t возвращает "самый верхний" из компонентов, располо
женных в указанной позиции. Это может быть либо сам аплет, либо компонент,
включенный в его состав. Если точка (х, у) находится за пределами области, выде
ленной для аплета, данный метод возвращает значение n u l l .
p u b l i c Cursor getCursor()
public void setCursor(Cursor cursor)
Эти методы позволяют прл)^чать и устанавливать курсор.
public F o n t M e t r i c s g e t F o n t M e t r i c s ( F o n t f)
Данный метод возвращает объект, который может быть использован для опреде
ления размеров строк ( s t r i n g W i d t h ) или отдельных символов ( c h a r W i d t h ) ,
представленных определенным шрифтом.
public Color g e t F o r e g r o u n d O
public Color s e t F o r e g r o u n d ( C o l o r fgColor)
Эти методы позволяют определять и устанавливать цвет переднего плана, исполь
зуемый в аплете по умолчанию. Способы задания цвета были рассмотрены при об
суждении метода g e t B a c k g r o u n d .
9.5. Прочие методы аплета 323
p u b l i c Graphics getGraphics()
Метод g e t G r a p h i c s () возвращает текущий графический объект аплета. Этот ме
тод используется в тех случаях, когда необходимо выполнить операции рисования
за пределами метода p a i n t . Метод p a i n t получает графический объект автома
тически.
p u b l i c I m a g e g e t I m a g e ( U R L imageFile)
public I m a g e g e t I m a g e ( U R L base, String imtageFilename)
Варианты метода g e t Image "регистрируют" удаленные файлы изображений и
связывают их с объектом I m a g e . Исполняющая система Java не загружает изобра
жение до тех пор, пока не возникнет необходимость отобразить его либо пока не
будет получено обращение с требованием начать загрузку (для этого используется
p r e p a r e Image или M e d i a T r a c k e r ) . Подробнее о выводе изображений рассказы
вается ниже в этой главе.
p u b l i c Locale getLocale()
p u b l i c v o i d setLocale(Locale locale)
Эти методы позволяют определять и устанавливать текущую национальную коди
ровку.
p u b l i c String getParameter(String p a r a m e t e r N a m e )
Метод g e t P a r a m e t e r позволяет определять значения параметров, передаваемых
с помощью дескрипторов PARAM. Д е с к р и п т о р ы РАКАМ включаются в состав деск
риптора APPLET HTML-документа. Подробно передача параметров будет рассмат
риваться далее в этой главе.
p u b l i c String[ ][ ] getParameterInfo()
Данный метод предоставляет описание параметров, распознаваемых аплетом.
Каждый элемент массива, в свою очередь, является массивом, содержащим имя
параметра, его тип и краткое описание.
p u b l i c Container getParent()
Метод g e t P a r e n t возвращает родительское окно либо значение n u l l .
public D i m e n s i o n getSize()
Метод g e t S i z e возвращает объект D i m e n s i o n , который описывает размеры об
ласти, занимаемой аплетом. Этот объект содержит поля w i d t h и h e i g h t . Таким
образом, ширина области, выделенной для аплета, определяется с помощью вы
ражения g e t S i z e () . w i d t h . В классе A p p l e t также определен метод s e t S i z e () ,
но на практике большинство броузеров игнорирует этот метод; размеры области
задаются с помощью атриб)Т'ов WIDTH и HEIGHT дескриптора APPLET и не изме
няются в процессе работы аплета. Исключением является броузер a p p l e t v i e w e r .
324 Глава 9. Аплеты и основные действия с графикой
p u b l i c b o o l e a n isActive()
Данный метод сообщает, является ли аплет активным. Аплет считается неактив
ным до вызова метода s t a r t и после вызова метода s t o p .
p u b l i c void repaint()
p u b l i c void repaint(long m i l l i s e c o n d D e l a y )
public void repaint(int x, int y, int width, int height)
public void repaint(long m s D e l a y , int x, int y, int width, int height)
Метод r e p a i n t дает команду потоку AWT вызывать метод u p d a t e либо немедлен
но, либо через заданное число миллисекунд. В любом случае r e p a i n t сразу же
возвращает управление вызывающему методу, а обновление и н ф о р м а ц и и на экра
не осуществляется в отдельном потоке. Вы также можете указать методу на то, что
обновлению подлежит лишь часть экрана. В этом случае методы u p d a t e и p a i n t
получат объект G r a p h i c s с установленной областью отсечения.
p u b l i c void s h o w D o c u m e n t ( U R L h t m l D o c ) [в классе A p p l e t C o n t e x t ]
public void s h o w D o c u m e n t ( U R L h t m l D o c , String f r a m e N a m e ) [в классе
AppletContext]
Д а н н ы й метод дает команду броузеру скопировать и отобразить Web-страницу.
Реально этот метод принадлежит не классу A p p l e t , а классу A p p l e t C o n t e x t ,
но используется подобно другим описанным выше методам. К данному методу не
обходимо обращаться с помощью выражения g e t A p p l e t C o n t e x t ( ) . s h o w -
Document { . . . ) • Броузер a p p l e t v i e w e r игнорирует метод showDocument.
p u b l i c v o i d showStatus(String m e s s a g e )
Метод s h o w S t a t u s отображает последовательность символов в строке состояния,
расположенной в нижней части окна броузера.
p u b l i c void u p d a t e ( G r a p h i c s g)
Этот метод вызывается потоком AWT после вызова метода r e p a i n t . Реализация
r e p a i n t по умолчанию очищает экран, а затем вызывает метод p a i n t . В прило
жениях, обрабатывающих анимационные последовательности и выполняющих
двойную буферизацию, данный метод обычно переопределяется так, чтобы он вы
зывал метод p a i n t , но не очищал экран. Данный вопрос будет подробно обсуж
даться в главе 16.
9 . 6 . Э л е м е н т APPLET 325
a d d C o m p o n e n t L i s t e n e r , a d d F o c u s L i s t e n e r , addKeyListener,
andMouscListener, addMouseMotionListener
Эти общедоступные методы добавляют к аплету обработчики различных событий.
Каждому из методов addXxAjListener соответствует метод r e m o v e X X X L i s t e n e r .
Эти методы будут обсуждаться в главе 10.
CODE
П р и отсутствии атрибута OBJECT значением CODE должно быть имя файла класса.
В атрибуте CODE нельзя указывать абсолютный URL. Файл класса должен нахо
диться в том же каталоге, что и HTML-документ, либо в каталоге, на который ука
зывает атрибут CODEBASE. Файл класса должен быть дост)^пен из Web; на исходный
Java-файл это требование не распространяется.
На з а м е т к у
WIDTH и HEIGHT
Атрибуты WIDTH и HEIGHT определяют размеры области, выделяемой для аплета.
Значения атрибутов могут быть заданы в пикселях либо в процентах от ширины ок
на броузера. Броузер a p p l e t v i e w e r не поддерживает значения в процентах, по
скольку для этого броузера понятие ширины окна не существует. Атрибуты WIDTH и
HEIGHT должны обязательно присутствовать в составе дескриптора <APPLET>.
Внимание!
CODEBASE
Данный атрибут определяет URL каталога, в котором содержится аплет. Имя ап-
лета задается с помощью атрибута CODE. Если CODEBASE отсутствует, считается,
что аплет расположен в том же каталоге, что и соответствующий HTML-документ.
ALT
Броузеры, поддерживающие Java, игнорируют текстовую информацию, содержа
щуюся между дескрипторами <APPLET . . . > и </APPLET>, поэтому здесь удобнее
всего помещать альтернативный текст. Атрибут ALT применяется крайне редко.
ALIGN
Этот атрибут определяет тип выравнивания области, выделенной для аплета. Зна
чения данного атрибута (LEFT, RIGHT, TOP, BOTTOM, MIDDLE) совпадают со значе
ниями атрибута ALIGN дескриптора IMG и интерпретируются так же.
HSPACE
Атрибут HSPACE задает размеры (в пикселях) пустого пространства слева и справа
от аплета.
VSPACE
Атрибут VSPACE задает размеры (в пикселях) пустого пространства сверху и снизу
от аплета.
NAME
Атрибут NAME присваивает аплету имя. Имя используется при организации взаи
модействия аплетов, а также аплетов и сценариев JavaScript. Имя применяется
вместо элемента массива аплетов. Следует заметить, что при реализации броузера
Netscape допущена ошибка, в результате чего броузер не распознает имена апле
тов, содержащие символы верхнего регистра. Поэтому, если вам надо организо
вать обмен данными между двумя аплетами, надо использовать имена, включаю
щие только строчные буквы.
Методика профессионалов
Значением атрибута NAME дескриптора APPLET должно быть имя, со
держащее лишь символы нижнего регистра.
OBJECT
Атрибут OBJECT указывает на аплет, который был сохранен средствами сериали-
3a4HHjava.
ARCHIVE
Атрибут ARCHIVE задает архив файлов классов, которые должны быть загружены
перед выполнением аплета. Архив необходимо представить в формате Java
ARchive ( . j a r ) . Netscape 3.01 поддерживает также несжатые ZIP-архивы ( . z i p ) .
9.7. Чтение параметров 327
MAYSCRIPT
Netscape и Internet Explorer используют данный атрибут для того, чтобы указать,
разрешено ли управление аплетом изJavaScript-cцeнapия.
Внимание!
Листинг 9 . 5 . HelloWWW2.java
import Java.applet.Applet;
import java.awt.*;
p u b l i c c l a s s HelloWWW2 e x t e n d s A p p l e t {
public void i n i t O {
s e t F o n t ( n e w F o n t ( " S a n s S e r i f " , Font.BOLD, 30));
9.7. Чтение параметров 329
Ш^^ШШ
:^ "Ф^
CLASSID
Задает URL объекта. Для аплетов значение CLASSID представляется в ф о р м е
Java:Applet.class.
CODETYPE
Атрибут CODETYPE определяет тип объекта, предназначенного для копирования.
Для аплетов используется значение C O D E T Y P E = " a p p l i c a t i o n / J a v a " .
CODEBASE
Данный атрибут указывает URL каталога, в котором расположен объект (аплет).
9.8. HTML-элемент OBJECT 331
STANDBY
Атрибут STANDBY задает строку, которая отображается в процессе загрузки аплета.
Л и с т и н г 9 . 7 . HelloWWWObject.html
<BODY>
<H1>A HelloWWW Object</Hl>
<OBJECT CODETYPE="application/java"
CLASSID="java:HelloWWW.class"
CODEBASE="applets"
WIDTH=400 HEIGHT=55>
<PARAM NAME="codebase" value="applets">
<PARAM NAME="code" value="HelloWWW.class">
<PARAM NAME="BACKGROUND" VALUE="DARK">
<B>Error! You must use a Java-enabled browser.</B>
</OBJECT>
</BODY>
</HTML>
М е т о д и к а профессионалов
М е т о д и к а профессионалов
• "Standard (IE 8с Navigator) for Windows and Solaris only" — стандартное для
Windows и Solaris.
• "Extended (standard + all browsers/platforms)"— расширенное (стандартное +
все б р о у з е р ы / п л а т ф о р м ы ) .
9 . 9 . Java Plug-In 333
• "Internet Explorer for Windows and Solaris only" — Internet Explorer для Windows
и Solaris.
• "Navigator for Windows only" — Navigator для Windows.
Кроме того, для выполнения преобразования вы можете определять собственные
шаблоны.
*izJiii
Fee Edit Н ^
•C\CWP2\Java-Applets+Graphics-Code
indude Subfolders
с lCvvF2\java-Applets<-Graphics-Code\Backup
<EMBED type="application/x-java-applet;version=l.3"
CODE = "HelloWWW.class" CODEBASE = "applets"
WIDTH = 400 HEIGHT = 40
BACKGROUND = "LIGHT"
scriptable=false
pluginspage="http://Java.sun.com/products/plugin/1.3/
334 Глава 9. Аплеты и основные действия с графикой
plugin-install.html"
>
<NOEMBED>
< B > E r r o r ! You m u s t u s e a J a v a - e n a b l e d browser.</B>
</NOEMBED>
</EMBED>
<OBJECT classid="clsid:8AD9C840-044E-llDl-B3E9-00805F499D93'
WIDTH = 400 HEIGHT = 40
Godebase="http://Java.sun.com/products/plugin/1.3/
jinstall-13-win32.cab#Version=l,3,0,0"
>
<PARAM NAME = CODE VALUE = "HelloWWW.class" >
<PARAM NAME = CODEBASE VALUE = "applets" >
<PARAM NAME="type"
VALUE="application/x-java-applet;version=l.3">
<PARAM NAME=="scriptable" VALUE="false">
<PARAM NAME = "BACKGROUND" VALUE ="LIGHT">
<B>Error! You must use a Java-enabled browser.</B>
</OBJECT>
frame.addWindowListener(new E x i t L i s t e n e r ( ) ) ;
frame.setSize(width, height);
frame.setVisible(true) ;
}
9 . 1 1 . Графические операции
Традиционно в аплетах и приложениях для рисования используется метод p a i n t . В
качестве параметра этому методу передается объект G r a p h i c s . Другие методы могут
получить объект G r a p h i c s путем вызова g e t G r a p h i c s . Однако при создании аплета
или приложения не стоит вызывать метод g e t G r a p h i c s , а затем сохранять объект
G r a p h i c s в переменной экземпляра, поскольку при последующих вызовах методу
p a i n t буду!^ переданы другие экземпляры этого объекта. Методы, в которых осуществ
ляется рисование, лучше вызывать из метода p a i n t и передавать им объект G r a p h i c s .
В аплетах и приложениях, использующих Swing, объект G r a p h i c s используется
для выполнения простых операций рисования. Основные действия, связанные с вы
водом графической информации, выполняются не в методе p a i n t , а в методе
p a i n t C o m p o n e n t . Этот метод доступен лишь в "легковесных" Swing-компонентах, к
которым не относятся J A p p l e t и J F r a m e . Таким образом, для выполнения операций
рисования в Swing к J A p p l e t и J F r a m e добавляется "легковесный" компонент, чаще
всего J P a n e l . Более подробно операции рисования в аплетах и приложениях обсуж
даются в главах 10 и 14.
336 Глава 9 . Аплеты и основные д е й с т в и я с графикой
М е т о д и к а профессионалов
Операции рисования
p u b l i c void clearRect(int left, int t o p , int width, int height)
Метод c l e a r Re c t отображает в указанной позиции закрашенный прямоугольник.
public void copyArea(int left, int t o p , int width, int height, int deltaX, int deltaY)
Данный метод копирует все пиксели из прямоугольника, определяемого парамет
рами l e f t , t o p , w i d t h , h e i g h t , в прямоугольник l e f t + d e l t a X , t o p + d e l t a Y ,
width, height.
Режимы рисования
p u b l i c void s e t X O R M o d e ( C o l o r color)
После вызова данного метода последующие операции рисования будут выполняться
в режиме XOR: цвет пикселя определяется результатом выполнения побитовой опе
рации XOR между указанным цветом и текущим цветом пикселя в конкретной пози
ции. Части линии, выведенной в режиме XOR, на многоцветном фоне будут отобра-
340 Глава 9. Аплеты и основные действия с графикой
жаться разными цветами. Цвет пикселя при рисовании в режиме XOR предсказать
трудно, поскольку операция исключающего XOR выполняется над внутренним
представлением цвета пикселей, которое может быть разным на различных маши
нах. Если два раза подряд вывести одно и то же изображение в режиме XOR, инфор
мация на экране вернется в исходном состояние. Этот эффект можно использовать
для стирания фрагментов, выведенных на фоне сложного изображения.
В данном режиме не следует использовать цвет C o l o r . b l a c k , поскольку на мно
гих платформах он представляется нулевым значением и результаты операции
XOR будут совпадать с первоначальным цветом пикселей. Ч т о б ы вернуться в нор
мальный режим рисования, надо вызвать метод s e t P a i n t M o d e .
public R e c t a n g l e g e t C l i p B o u n d s ( )
Этот метод возвращает прямоугольник, определяющий текущую область отсече
ния. В некоторых случаях может быть возвращено значение n u l l .
p u b i c void setClip(Shape c l i p p i n g R e g i o n )
Данный метод устанавливает новую область отсечения.
Внимание!
Листинг 9 . 1 1 . JavaManl. j a v a
import Java.applet.Applet;
import java.awt.*;
/ * * Аплет, загружающий и з о б р а ж е н и е , у к а з а н н о е посредством
* о т н о с и т е л ь н о г о URL.
V
p u b l i c c l a s s JavaManl e x t e n d s A p p l e t {
p r i v a t e Image javaMan;
public void i n i t O {
javaMan = g e t I m a g e ( g e t C o d e B a s e ( ) , " i m a g e s / J a v a - M a n . g i f " )
}
</BODY>
</HTML>
9 . 1 2 . Вывод и з о б р а ж е н и й 343
НМ'Ги11|Д|1-|1Н1'И
</BODY>
</HTML>
9 . 1 2 . Вывод и з о б р а ж е н и й 345
• A j j d t e s s j ^ Ы1р/'/\^wwcofewebptogtarnrningcorn/JavaMan2htm| J ^ ^fi^So
JavaMan2
М е т о д и к а профессионалов
import java.awt.*;
import javax.swing.*;
public JavaMan3 () {
String imageFile = System.getProperty("user.dir") +
"/images/Java-Man.gif";
javaMan = getToolkitO .getImage(imageFile);
setBackground(Color.white);
Листинг 9 . 1 6 . P r e l o a d . J a v a
import java.awt.^;
import Java.awt.event.*;
import javax.swing.*;
import java.net.*;
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (draw) {
g.drawlmage(plate, 0, 0, this);
showTime();
}
}
if (args.length == 0) {
System.out.println("Must provide URL");
System.exit(0);
}
if (args.length == 2 && args[1].equals("-preload")) {
preload = new Preload(args[0], true);
} else {
preload = new Preload(args [0], false);
}
WindowUtilities.setNativeLookAndFeel();
WindowUtilities.openlnJFrame(preload, 1000, 750);
}
350 Глава 9. Аплеты и основные действия с графикой
Листинг 9.17.ImageBox.Java
import Java.applet.Applet/
import java.awt.*;
p u b l i c c l a s s ImageBox e x t e n d s A p p l e t {
p r i v a t e i n t imageWidth, imageHeight;
p r i v a t e Image i m a g e ;
public void i n i t O {
S t r i n g imageName = g e t P a r a m e t e r ( " I M A G E " ) ;
i f (imageName != n u l l ) {
image = g e t l m a g e ( g e t D o c u m e n t B a s e ( ) , imageName);
} else {
image = g e t l m a g e ( g e t D o c u m e n t B a s e ( ) , " e r r o r . g i f " ) ;
}
setBackground(Color.white);
p u b l i c v o i d p a i n t ( G r a p h i c s g) {
g . d r a w l m a g e ( i m a g e , 0, 0, t h i s ) ;
g . d r a w R e c t ( 0 , 0, i m a g e W i d t h , i m a g e H e i g h t ) ;
}
352 Глава 9. Аплеты и основные действия с графикой
Листинг 9 . 1 8 . I m a g e B o x , h t m l
•
^ » Рис. 9.10. Определяя размеры изображения
« ] Done J^ MyCorapUa
Щ до окончания его загрузки, вы можете получить
неверные результаты
MediaTracker
public void a d d l m a g e ( l m a g e i m a g e , int id)
public void a d d l m a g € ( l m a g e i m a g e , int id, int width, int height)
Данные методы регистрируют обычное или масштабированное изображение под
определенным идентификационным кодом. Зарегистрировав одно или несколько
изображений, вы можете проверять их состояние либо дожидаться изображения с
определенным идентификатором. Вы также можете ожидать загрузки всех изо
бражений; в этом случае система старается загрузить первыми изображения с бо
лее низкими значениями идентифик ционных номеров.
9.14. Управление загрузкой изображений... 353
public b o o l e a n checkAll()
public b o o l e a n c h e c k A l l ( b o o l e a n startLoading)
Данные методы возвращают значение t r u e , если загрузка всех изображений, за
регистрированных с помощью M e d i a T r a c k e r , завершена. В противном случае
возвращается значение f a l s e . Если значение параметра s t a r t L o a d i n g равно
t r u e , система начнет загружать те изображения, загрузка которых еще не нача
лась. Для ожидания загрузки изображений не следует помещать вызов C h e c k A l l в
цикл, лучше использовать метод w a i t F o r A l l , который позволяет добиться тех же
результатов, более экономно используя ресурсы центрального процессора.
public b o o l e a n c h e c k I D ( i n t id)
public b o o l e a n c h e c k I D ( i n t id, b o o l e a n startLoading)
Данные методы похожи на c h e c k F o r A l l , но с их помощью проверяется лишь со
стояние изображения с конкретным идентификатором.
p u b l i c Object[ ] getErrorsAnyO
p u b l i c Object[ ] getErrorsID(int id)
Данные методы возвращают массив изображений, в процессе загрузки которых
возникла ошибка.
public b o o l e a n isErrorAnyO
public b o o l e a n isErrorID(int id)
Эти методы возвращают значение t r u e , если в процессе загрузки изображения
возникла ошибка. В противном случае возвращается значение f a l s e .
Листинг 9.19.BetterImageBox.java
if (tracker.isErrorAnyО) {
System.out.println("Error while loading image");
)
// К этому моменту загрузка изображения завершена.
imageWidth = image.getWidth(this);
imageHeight = image.getHeight(this);
}
p u b l i c v o i d p a i n t ( G r a p h i c s g) {
g . d r a w l m a g e ( i m a g e , 0, 0, t h i s ) ;
g . d r a w R e c t ( 0 , 0, i m a g e W i d t h , i m a g e H e i g h t ) ;
}
Листинг 9 . 2 0 . B e t t e r I m a g e B o x . h t m l
J
ImageBox
someImage = getImage(...);
doSomeOtherStuff();
if (TrackerUtil.waitForlmage(somelmage, this))
// Загрузка somelmage завершилась,
else
// Ошибка при загрузке somelmage.
Аналогично, код, в котором используется метод wait For Images, имеет вид
imagel = getlmage(...);
image2 = getlmage(...);
imageN = getlmage(...);
doSomeOtherStuff() ;
Image[] images = { imagel, image2, ... , imageN };
if (TrackerUtil.waitForlmages(images, this))
// Загрузка всех изображений завершилась,
else
/ / В о время загрузки изображения возникла ошибка.
Если вам требуется такая степень контроля над загрузкой изображения, которую
не может обеспечить класс M e d i a T r a c k e r , надо переопределить метод i m a g e U p d a t e
окна. Дополнительную и н ф о р м а ц и ю вы найдете в документации по API.
Листинг 9 . 2 1 . T r a c k e r U t i l , J a v a
import java.awt.*;
/** Вспомогательный класс, который позволяет загружать
* изображения и дожидаться окончания этой процедуры.
* Если вам необходимо последовательно загрузить несколько
* изображений, вызовите несколько раз waitForlmage. Если
* вам надо, чтобы изображения загружались одновременно,
* используйте метод waitForImages; при этом вы можете
* выиграть в скорости.
*/
}
try {
tracker.waitForAll();
} catch(InterruptedException ie) {}
if (tracker.isErrorAny0) {
return(false);
} else {
return(true);
}
9.15. Резюме
Аплеты представляют собой графические программы, встраиваемые в Web-
страницы. Аплеты выполняются на клиентских машинах и на их работу накладывается
ряд ограничений, связанных с безопасностью системы. Аплет создается как подкласс
класса j a v a . a p p l e t .Applet и связывается с Web-страницей посредством элемента
APPLET. При создании аплета могут быть использованы новые графические компонен
ты Swing, но большинство броузеров не поддерживает их. Для работы аплетов, приме
няющих Swing, необходимо использовать Java Plug-In либо копировать классы Swing по
сети. Оба этих подхода неприменимы для клиентов, подключенных к Internet.
Графические Java-программы, не предназначенные для работы в Web, создаются
на основе класса JFrame. В аплетах рисование обычно осуществляется в теле метода
p a i n t . В приложениях операции рисования выполняются в методе p a i n t Component
"легковесного" компонента Swing; для этого к JFrame часто добавляется J P a n e l .
Обоим методам в качестве параметра передается объект G r a p h i c s , в котором реали
зован набор методов для поддержки простых операций рисования. Если вам надо,
чтобы изображение на экране выглядело профессионально, необходимо использо
вать средства Java 2D API, которые будут рассмотрены в следующей главе.
При работе с графическими изображениями приходится применять метод
drawlmage, который позволяет отображать изображения в формате GIF или JPEG,
загруженные ранее посредством метода g e t Image класса Applet или T o o l k i t . Изо
бражения загружаются в фоновом потоке. Процесс загрузки можно непосредственно
контролировать с помощью MediaTracker. Для аплета изображения могут копиро
ваться только с того компьютера, с которого был загружен сам аплет.
JAVA 2D:
ГРАФИКА
В JAVA 2
В этой главе...
• Вывод 20-форм.
// Отобрсикение формы.
g.drawstring(. . . ) ;
g.drawLine(...
g.drawRect(... // контур
g.fillRect(... // заполнение
g.drawPolygon( . . ) ; // контур
g.fillPolygon( . . ) ; // заполнение
g.drawOval(... // контур
g.fillOvaK. . . ] // заполнение
1 0 . 1 . О б щ и е с в е д е н и я о Java 2 D 361
}
Методика профессионалов
g2d.setPaint(fillColorOrPattern) ;
g2d.setStroke(penThicknessOrPattern);
g2d.setComposite(someAlphaComposite);
g2d.setFont(someFont);
g2d.translate(...);
g2d.rotate(...);
g2d.scale(...);
g2d.shear(...);
g2d.setTransform(someAffineTransform);
p u b l i c v o i d fill(Shape shape)
Данный метод выводит заполненную форму в соответствии с текущими установ
ками контекста G r a p h i c s 2D. Вопросы позиционирования рассмотрены в описа
нии метода d r a w .
p u b l i c v o i d s c a l e ( d o u b l e x s c a l e , d o u b l e yscale)
Данный метод выполняет операции линейного масштабирования по осям х и у.
Значения, превышающие 1.0, растягивают оси, а значения менее 1.0— сжимают
их. Если для x s c a l e задано значение, равное -1, полученное изображение являет
ся зеркальным отображением исходного относительно оси х. Если значение
y s c a l e равно -1, генерируется зеркальное отображение относительно оси у.
364 Глава 10. Java 2D: графика в Java 2
Классы Shape
Параметры, передаваемые методам draw и f i l l класса Graphics2D, должны реа-
лизовывать интерфейс Shape. Вы можете создавать собственные формы либо ис
пользовать встроенные классы, например Arc2D, Area, CubicCurve2D, E l l i p s e 2 D ,
G e n e r a l P a t h , Line2D, QuadCurve2D, Rectangle2D и RoundRectangle2D. Эти клас
сы содержатся в пакете J a v a , awt. geom. Каждый из этих классов, за исключением
Area, Polygon и R e c t a n g l e , содержит конструкторы f l o a t и double.
Классы Polygon и R e c t a n g l e , которые поддерживались еще в Java 1.1, также реа
лизуют интерфейс Shape. Эти формы были рассмотрены в главе 9.
Наиболее часто используемые конструкторы объектов Shape приведены ниже.
p u b l i c GeneralPathO
Класс G e n e r a l P a t h интересен тем, что позволяет определять отрезки различных
линий для создания нового объекта S h a p e . Этот класс поддерживает такие методы
построения и объединения прямых и кривых Безье, как c l o s e P a t h , c u r v e T o ,
l i n e T o , moveTo и quadTo. Если вы попытаетесь добавить к G e n e r a l P a t h отрезок,
не вызвав перед этим метод moveTo, будет сгенерировано сообщение об ошибке
I l l e g a l P a t h S t a t e E x c e p t i o n . Пример создания G e n e r a l P a t h приведен ниже.
G e n e r a l P a t h p a t h = new G e n e r a l P a t h O ;
p a t h . m o v e T o ( 1 0 0 , 100) ;
p a t h . l i n e T o ( 3 0 0 , 205) ;
p a t h . q u a d T o ( 2 0 5 , 2 5 0 , 34 0 , 3 0 0 ) ;
p a t h . l i n e T o ( 3 4 0, 350) ;
path.closePath();
p u b l i c Line2D.Float(Point p i . P o i n t p2)
p u b l i c L i n e 2 D . D o u b l e ( P o i n t p i . P o i n t p2)
Данные конструкторы создают форму L i n e 2 D , которая описывает отрезок пря
мой, ограниченный точками р 1 и р2 (точки представлены объектами P o i n t ) .
Листинг 10.3.ShapeExample.Java
Классы рисования
Объект, передаваемый в качестве параметра методу s e t P a i n t класса G r a p h i c s 2 D , и
значение, возвращаемое методом g e t P a i n t , должны реализовывать интерфейс P a i n t .
Ниже описаны основные встроенные классы P a i n t .
Color
Класс C o l o r содержит те же константы для определения цвета, что и AWT-версия,
но предоставляет дополнительный конструктор, позволяющий задать значение про
зрачности. Цвет представляется 4-байтовым целым числом, в котором три младших
байта соответствуют красному, зеленому и синему цветам, а старший байт задает значе
ние прозрачности ( a l p h a ) . По умолчанию значение прозрачности равно 255, что соот
ветствует непрозрачному цвету. Для полностью прозрачного цвета a l p h a равно 0. Кон
структоры C o l o r имеют следующий вид:
GradientPaint
Объект G r a d i e n t P a i n t представляет плавный переход от одного цвета к другому.
Градиентная линия задается с помощью двух точек. Одной точке соответствует один
цвет, а другой точке — другой цвет. Цвет плавно изменяется вдоль градиентной ли
нии, а линии, расположенные перпендикулярно ей, закрашиваются одним цветом.
В зависимости от значения логического параметра цветовой шаблон повторяется
вдоль продолжения градиентной линии до конца формы.
TexturePaint
Класс T e x t u r e P a i n t представляет изображение, повторяющееся в пределах фор
мы. Создавая объект T e x t u r e P a i n t , надо задать изображение и указать его размеры.
Листинг 1 0 . 4 . GradientPaintEacample. j a v a
import java.awt.^;
/** Пример градиентного заполнения круга. Цвет изменяется
* от красного, в точке (0,0) до желтого — в точке (175,175).
V
public class GradientPaintExample extends ShapeExample {
private GradientPaint gradient =
new GradientPaint(0, 0, Color.red, 175, 175, Color.yellow,
true); // true означает повторение шаблона
public void paintComponent(Graphics g) {
clear (g);
Graphics2D g2d = (Graphics2D)g;
drawGradientCircle(g2d);
}
protected void drawGradientCircle(Graphics2D g2d) {
g2d.setPaint(gradient);
g2d.fill(getCircle());
g2d.setPaint(Color.black);
g2d.draw(getCircle0);
}
TexturePaint texture =
new TexturePaint(bufferedlmage,
new Rectangle(0, 0, width, height));
import javax.swing.*;
import java.awt.*;
import Java.awt.geom.*;
import Java.awt.image.*;
image.getHeight() ) ;
imagePaintl = new TexturePaint(image, imageRect);
image = ImageUtilities.getBufferedlmage(imageFile2, this);
imagePaint2 =
new TexturePaint(image, new Rectangle(0, 0, 32, 32));
Листинг 10.6.ImageUtilities.Java
import java.awt.*;
import Java.awt.image.*;
Bufferedlmage bufferedlmage =
new Bufferedlmage(image.getWidth(c), image.getHeight(c),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedlmage.createGraphics();
g2d.drawImage(image, 0 , 0 , c ) ;
return(bufferedlmage);
}
a l p h a равен O.Of; по мере движения вправо его значение возрастает и для самого пра
вого квадрата оно равно 1 .Of.
Как говорилось в разделе 10.3, значение прозрачности может задаваться при соз
дании цвета. В данном примере прозрачность красного квадрата указывается как па
раметр конструктора класса Color.
p r i v a t e void drawSquares(Graphics2D g2d, f l o a t alpha) {
g2d.setPaint(Color.blue);
g2d.fill(blueSquare) ;
Color c o l o r = new Color(1, 0, 0, alpha); //Красный
g2d.setPaint(color);
g2d.fill(redSquare) ;
}
import javax.swing.*;
import java.awt.*;
import Java.awt.geom.*;
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
for(int i=0; i<ll; i++) {
drawSquares(g2d, i*0.IF);
g2d.translate(deltaX, 0 ) ;
}
^hw.'^l!li^•rjlm•{^lM[rj^fiMl^^lii,тl[^•^jlf^irl'^^^^^l^^^l^^l/ilf1^,тlHl^я^
GrapicsEnvironment.getLocalGraphicsEnvironment();
Затем вызывается метод
env.getAvailableFontFamilyNames ();
или
env.getAllFontsо; / / Намного м е д л е н н е е !
Разделы документации по API, касающиеся работы со шрифтами, могут ввести
разработчика в заблуждение. Так, например, если вы попытаетесь использовать ло-
1 0 . 5 . Использование локальных шрифтов 379
Внимание!
import j a v a . a w t . * ;
/** Вывод имен доступных шрифтов. */
public class ListFonts {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
S t r i n g [ ] fontNames = env.getAvailableFontFamilyNames();
System.out.println("Available Fonts:");
f o r ( i n t 1=0; i<fontNames.length; i++)
S y s t e m . o u t . p r i n t l n ( " " + fontNames[i]);
}
Листинг 1 0 . 9 . F o n t E x a m p l e . J a v a
import java.awt.*;
\шшшшшвшшшшшл MHHBHHaiMiiHi'
nfava 211
ovi^fl^HHr 1
Рис. 10.5. Java 2D позволяет отображать
текст любым из шрифтов, установленных
на локальном компьютере
10.6. Стили пера 381
Атрибуты пера
Объекты, передаваемые в качестве параметров методу s e t S t r o k e , должны ис
пользовать и н т е р ф е й с S t r o k e . Такому требованию отвечает класс B a s i c S t r o k e .
Ниже описаны конструкторы B a s i c S t r o k e .
p u b l i c BasicStrokeO
Данный конструктор создает объект B a s i c S t r o k e с толщиной пера 1.0. По умол
чанию устанавливаются стиль оформления конца отрезка CAPSQUARE и стиль со
единения л и н и й JOIN_MITER. П р и м е р ы рисования линиями различной ширины,
оформления концов отрезков и соединения линий будут приведены ниже.
p u b l i c BasicStroke(float penWidth)
Этот конструктор создает объект B a s i c S t r o k e с указанной толщиной пера. Как и
в предыдущем случае, по умолчанию устанавливаются стили (CAP_SQUARE и
JOIN_MITER).
Листинг 10.10.StrokeThicknessExample.Java
import j a v a . a w t . * ;
/** Пример управления толщиной пера.
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
WindowUtilities.openlnJFrame(new StrokeThicknessExample(),
380, 400);
}
10.6. Стили пера 383
import java.awt.*;
import javax.swing.*;
import java.awt.*;
import Java.awt.geom.*;
/** Примеры различных способов соединений отрезков.
* Внешний вид концов линий задается параметром capStyle.
public LineStylesO {
path = new GeneralPath();
path.moveTo(x, y ) ;
plLarge = new Circle(x, у thickness/2);
plSmall = new Circle(x, у 2);
path.lineTo(x + deltaX, у - deltaY);
p2Large = new Circle(x + deltaX, у - deltaY, thickness/2);
p2Small = new Circle(x + deltaX, у deltaY, 2 ) ;
path.lineTo(x + 2*deltaX, y ) ;
p3Large = new Circle(x + 2*deltaX, thickness/2)
p3Small = new Circle(x + 2*deltaX, 2);
setFont(new Font("SansSerif", Font.BOLD, 20));
}
}
На заметку
Объект Shape следует преобразовывать перед рисованием. Метод
createTransformedShape Aff IneTransform создает новый объект
Shape, преобразованный в соответствии с правилами, заданными с
помощью объекта Aff IneTransform.
Листинг 10.13.RotationExample.Java
import j a v a . a w t . * ;
/** Пример преобразования системы координат с последующим
* рисованием.
Нелинейное масштабирование
п р и нелинейном масштабировании система координат "растягивается" параллельно
осям. Если вы зададите ненулевое значение х-масштабирования, координата х сдвигает
ся тем больше, чем дальше точка отстоит от начала координат по оси у. Например, зна
чение х-масштабирования, равное 0.1, указывает на то, что координата х сдвигается на
10% от расстояния по оси у. Аналогично, сдвиг координаты у пропорционален расстоя
нию по оси X. И х- и у-масштабирование могут задаваться одновременно.
Лучше всего продемонстрировать нелинейное масштабирование на конкретном
примере. Код примера приведен в листинге 10.14, а результаты его выполнения пока
заны на рис. 10.10. Здесь значение х-масштабирования возрастает от 0.0 для первого
квадрата до +0.8 для пятого квадрата. Значение у-масштабирования остается неиз
менным.
Листинг 1 0 . 1 4 . S h e a r E x a m p l e . j a v a
import javax.swing.^;
import java.awt.*;
import Java.awt.geom.*;
p u b l i c void paintComponent(Graphics g) {
s u p e r . paintComponent (g). ;
Graphics2D g2d = (Graphics2D)g;
for ( i n t i = 0 ; i < 5 ; i++) {
g2d.setPaint(Color.red);
g2d.fill(rect) ;
// Для- каждого нового квадрата значение
// х-масштабирования увеличивается на 0.2.
390 Глава 10. Java 2D: графика в Java 2
g2d.shear(0.2, 0.0);
g2d.translate(2*gap + width, 0) ;
}
10.8. Прочие возможности Java 2 D 391
М е т о д и к а профессионалов
10.9. Резюме
Java 2D предоставляет разработчику средства для вывода высококачественных гра
фических изображений. В частности, Java 2D обеспечивает следующие возможности.
• Рисование контуров и заполнение произвольного объекта Shape. Для этого
используются методы draw и f i l l объекта Graphics2D. В качестве параметра
данным методам передается объект Shape.
• Применение метода s e t P a i n t класса Graphics2D для отображения форм од
ним цветом (Color), реализации градиентного заполнения ( G r a d i e n t P a i n t )
или заполнения повторяющимися изображениями ( T e x t u r e P a i n t ) .
• Реализация прозрачных форм и изменение правил объединения цветов при
отображении нескольких форм. Правила объединения, реализованные в классе
AlhpaComposite, определяют отображение форм на имеющемся фоне.
• Преодоление ограничения, согласно которому вы можете рисовать лишь пе
ром толщиной в один пиксель и создавать объекты B a s i c S t r o k e , позволяю
щие управлять толщиной пера, отображать штриховые линии и задавать пра
вила соединения отрезков.
392 Глава 10. Java 2D: графика в Java 2
В ЭТОЙ главе...
Н
екоторые действия пользователя, например щелчок кнопкой мыши, нажатие
клавиши на клавиатуре, перемещение окна, классифицируются как события.
Обработка событий в Java не предполагает явной проверки состояния соот
ветствующих устройств или объектов. Вместо этого вы сообщаете системе приблизи
тельно следующее: "Если произойдет событие определенного типа, связанное с дан
ным окном, об этом следует оповестить указанный объект". Получив такое сообще
ние, система ожидает возникновения событий указанного типа и оповещает об этом
специальные объекты, называемые объектами прослушивания, или обработчиками собы
тий. Обработка событий включает следующие действия.
1. Определение типа интересующего вас события.
Существует 11 типов объектов прослушивания AWT, которые перечислены в
табл. 1.1. Выберите объект, соответствующий действиям, которые вы хотите
отслеживать. Например, объект K e y L i s t e n e r соответствует нажатию и отпус
канию клавиш клавиатуры, объект M o u s e L i s t e n e r — действиям пользователя с
кнопками мыши, объект F o c u s L i s t e n e r позволяет выявлять события, связан
ные с получением и потерей фокуса элементами пользовательского интерфей
са и т. д.
2. Создание класса требуемого типа.
Один из способов решения данной задачи состоит в непосредственной реали
зации классом одного из интерфейсов прослушивания ( M o u s e L i s t e n e r ,
K e y L i s t e n e r , F o c u s L i s t e n e r и т.д.) В создаваемом классе надо создать мето
ды, соответствующие конкретной подкатегории интересующих вас событий.
Так, например, если вам необходимо поддерживать нажатие и отпускание
кнопки мыши, надо реализовать интерфейс M o u s e L i s t e n e r , в частности раз
работать методы, соответствующие этим событиям. Если интерфейс включает
больше одного метода, вы можете воспользоваться классом адаптера, в кото
ром реализованы все методы. Реализация этих методов не выполняет никаких
действий, поэтому интересующие вас методы следует переопределить. Адапте
ры подробно обсуждаются ниже в этой главе.
396 Глава 1 1 . События, связанные с мышью и клавиатурой
Листинг 1 1 . 1 . CiickListener.java
import Java.awt.event.*;
/ * * Обработчик событий, используемый C l i c k R e p o r t e r . */
p u b l i c c l a s s C l i c k L i s t e n e r e x t e n d s MouseAdapter {
p u b l i c void mousePressed(MouseEvent event) {
S y s t e m . o u t . p r i n t l n ( " M o u s e p r e s s e d a t (" +
event. getXO + " , " +
event.getY0 + " ) . " ) ;
}
}
11.1. Поддержка событий. 397
iS iiwupai'rrpummiffmi
fife £{fe Vtew F^vontes Tods Иёр
l-.lii.lAJ.i!. fifxil
JMouse p r e s s e d at ( 2 6 , 2 2 ) .
jMouse p r e s s e d at ( 6 5 , 6 3 ) ,
jMouse p r e s s e d at (110,106)
;House p r e s s e d ac (160,137)
jMouse p r e s s e d at ( 2 1 0 , 1 7 1 ) .
JKouse p r e s s e d at (275,211)
JHouse p r e s s e d at ( 3 6 7 , 2 7 4 ) .
Mouse pressed at ( 3 9 0 , 3 2 5 ) .
JMouse p r e s s e d at ( 4 2 6 , 3 2 7 ) .
Отображение кругов
Теперь изменим код аплета так, чтобы вместо вывода координат курсора мыши он
отображал круг с центром в той точке, в которой находился курсор в момент нажатия
кнопки. Получить объект G r a p h i c s за пределами метода paint довольно просто: для
этого достаточно вызвать метод g e t G r a p h i c s . Проблема состоит в том, что обра
ботчик событий не принадлежит классу Applet и, следовательно, не содержит метод
398 Глава 1 1 . События, связанные с мышью и клавиатурой
Листинг 1 1 . 3 . C i r c l e L i s t e n e r . j a v a
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
/** Обработчик, используемый C i r c l e D r a w e r l . Для
* получения ссылки на аплет вызывается метод getSource.
V
p u b l i c c l a s s C i r c l e L i s t e n e r extends MouseAdapter {
p r i v a t e i n t r a d i u s = 25;
p u b l i c void mousePressed(MouseEvent event) {
Applet app = ( A p p l e t ) e v e n t . g e t S o u r c e 0 ;
Graphics g = app.getGraphics ( ) ;
g.fillOval(event.getX()-radius,
event.getY()-radius,
2*radius,
2*radius);
import Java.applet.Applet;
import java.awt.*;
d
Using External Listeners for Event Handling
Click ill the applet to di aw circles.
Листинг 1 1 . 5 . C i r c l e D r a w e r 2 . J a v a
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
p r i v a t e I n n e r t e s t = new I n n e r ( ) ;
М е т о д и к а профессионалов
Листинг 1 1 . 6 . C i r c l e D r a w e r 3 . J a v a
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
addMouseListener(new CircleListener());
}
C o l o r someColor = p i c k C o l o r O ;
add(new P a n e l ( ) {
p u b l i c Color o r i g C o l o r = someColor;
public void i n i t O {
setBackground(origColor);
}
});
K e y A d a p t e r myAdapter =
new K e y A d a p t e r 0 {
p u b l i c void keyPressed(KeyEvent event) { ... }
};
addKeyListener(myAdapter);
Листинг 11.7.CircleDrawer4.java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
ActionListener addActionListener
AdjustmentListener addAdjustmentListener
ComponentListener ComponentAdapter addComponentListener
ContainerListener ContainerAdapter addContainerListener
FocusListener FocusAdapter addFocusListener
ItemListener addltemListener
KeyListener KeyAdapter addKeyListener
MouseListener MouseAdapter addMouseListener
MouseMotionListener MouseMotionAdapter addMouseMotionListene
r
TextListener addTextListener
WindowListener WindowAdapter addWindowListener
Обработчики содержат методы, переопределив которые вы можете контролиро
вать события. Каждому из этих методов передается единственный параметр, пред
ставляющий собой подкласс AWTEvent. AWTEvent содержит четыре важных метода:
consume (удаление события), i s C o n s u m e d (возвращает логическое значение, опре
деляющее, было ли событие обработано другим обработчиком), g e t ID (возвращает
целочисленное значение, представляющее тип события) и g e t S o u r c e (возвращает
объект O b j e c t , определяющий источник события).
ActionListener
Данный интерфейс определяет единственный метод:
public void actionPerformed(ActionEvent event)
Поскольку интерфейс содержит только один метод, соответствующий класс адап
тера отсутствует. Обработчик такого типа применяется для работы с кнопками,
списками, меню и полями редактирования. Метод a c t i o n P e r f o r m e d вызывается
тогда, когда пользователь щелкает на кнопке, нажимает клавишу <Enter>, введя
текст в поле редактирования, и в других подобных случаях. Кроме стандартных
методов AWTEvent, A c t i o n E v e n t содержит два дополнительных метода:
g e t A c t i o n C o m m a n d (он возвращает "командную строку" источника в виде объекта
String) и g e t M o d i f i e r s (возвращает набор флагов, определяющих состояние кла
виш <Shift>, <Ctrl> и т.д. П о умолчанию для кнопки "командная строка" источника
совпадает с надписью на кнопке, однако для кнопок, надписи на которых изменя
ются, она может быть задана отдельно. В большинстве случаев наиболее важным
оказывается метод g e t S o u r c e , который позволяет определить конкретный ком
понент, сгенерировавший событие.
11.5. Стандартные обработчики событий 405
AdjustmentListener
В составе данного интерфейса содержится один метод:
p u b l i c void adjustmentValueChanged(AdjustmentEvent event)
Класс адаптера, соответствующий A d j u s t m e n t L i s t e n e r , отсутствует. Данный объ
ект прослушивания применяется только при работе с полосами прокрутки, и метод
a d j u s t m e n t V a l u e C h a n g e d вызывается тогда, когда состояние полосы прокрутки
изменяется. По сравнению со стандартными методами AWTEvent Ad j u s t m e n t E v e n t
содержит несколько новых методов. В частности, g e t A d j u s t a b l e возвращает ис
ходную полосу прокрутки, g e t A d j u s t m e n t T y p e возвращает одну из констант
UNIT_DECREMENT, UNIT_INCREMENT, BLOCK_DECREMENT, BLOCK_INCREMENT или
TRACK; g e t V a l u e позволяет определить текущие установки.
ComponentListener
Интерфейс C o m p o n e n t L i s t e n e r определяет следующие четыре метода:
public void componentResized(ComponentEvent event)
public void componentMoved(ComponentEvent event)
public void componentShown(ComponentEvent event)
public void componentHidden(ComponentEvent event)
Java API предоставляет класс C o m p o n e n t A d a p t e r , содержащий "пустые'' реализа
ции каждого из указанных методов. Используя данный класс, вы можете переоп
ределить нужные методы и не заботиться об остальных. Перечисленные выше ме
тоды вызываются тогда, когда размеры компонента изменяются, компонент пере
мещается, становится видимым и исчезает из области видимости. Метод
g e t C o m p o n e n t класса C o m p o n e n t E v e n t возвращает объект Component, сгенери
ровавший событие. Использовать метод g e t C o m p o n e n t удобнее, чем вызывать
метод g e t S o u r с е , а затем приводить возвращаемый результат к типу Component.
ContainerListener
В данном интерфейсе определены два следующих метода:
public void componentAdded(ContainerEvent event)
public void componentRemoved(ContainerEvent event)
Класс ContainerAdapter реализует оба метода. Методы ContainerListener
вызываются тогда, когда компоненты добавляются к контейнеру либо удаляются
из него. Класс ContainerEvent содержит методы getContainer и getChild для
доступа к окну и соответствующему компоненту.
FocusListener
Интерфейс FocusListener содержит два метода:
public void focusGained(FocusEvent event)
public void focusLost(FocusEvent event)
"Пустые" версии данных методов реализованы в классе F o c u s A d a p t e r . Класс
F o c u s E v e n t содержит метод i s T e m p o r a r y , который возвращает логическое значе
ние, определяющее, является ли изменение фокуса временным или постоянным.
406 Глава 1 1 . События, связанные с мышью и клавиатурой
ItemListener
Данный интерфейс определяет единственный метод:
public void itemStateChanged(ItemEvent event)
Класс адаптера, соответствующий интерфейсу I t e m L i s t e n e r , отсутствует. Обра
ботчик этого типа применяется при работе с объектами Checkbox,
CheckboxMenuItem, C h o i c e и L i s t . Метод вызывается тогда, когда состояние
объекта изменяется. Класс I t e m E v e n t содержит три метода: g e t l t e m S e l e c t a b l e
(определяет объект источника), g e t I t e m (определяет выбранный пункт) и
g e t S t a t e C h a n g e (возвращает целочисленное значение I t e m E v e n t . SELECTED
или I t e m E v e n t . DESELECTED).
KeyListener
Интерфейс K e y L i s t e n e r объявляет три метода:
p u b l i c void keyPressed(KeyEvent event)
p u b l i c void keyReleased(KeyEvent event)
p u b l i c v o i d keyTyped(KeyEvent event)
Класс K e y A d a p t e r содержит "пустые" варианты этих методов, таким образом, вы
можете переопределить один или два из них и не заботиться о реализации осталь
ных. Для вызова обработчика клавиша должна быть нажата в тот момент, когда ком
понент имеет фокус, поэтому обычные окна, такие как P a n e l или C a n v a s , должны
явно запрашивать фокус, вызывая метод r e q u e s t F o c u s . Методы k e y P r e s s e d и
k e y R e l e a s e d сл)'жат для перехвата низкоуровневых действий; в этом случае состоя
ние клавиш-модификаторов <Shift>, <Ctrl> и др. передается отдельно. Если вы не хо
тите, чтобы код клавиши был доступен компоненту, используйте consume в теле ме
тода k e y P r e s s e d . Поступая таким образом, вы ограничите набор символов, кото
рые пользователь может ввести в поле редактирования. Если вас интерес)тот только
отображаемые символы, вам надо переопределить метод keyTyped.
Класс KeyEvent определяет ряд методов и констант. При написании программы
большую помощью могут оказать два важных метода— getKeyChar и setKeyChar.
Метод getKeyChar возвращает код введенного символа, а метод s e t K e y C h a r по
зволяет заменить один символ другим. Это позволяет заменять символы табуляции и
перевода строки пробелами, преобразовывать регистр символов и выполнять другие
подобные действия. В классе KeyEvent содержатся также методы g e t M o d i f i e r s и
s e t M o d i f i e r s , которые позволяют определять и заменять клавиши-модификаторы,
а также логический метод i s A c t i o n K e y , который дает возможность отличать функ
циональные клавиши и клавиши управления курсором от других клавиш. Вы также
можете использовать методы, унаследованные от класса I n p u t E v e n t : isAltDown,
i s C o n t r o l D o w n , isMetaDown и i s S h i f tDown. Вместо символьных значений, полу
чаемых с помощью метода g e t K e y C h a r , вы можете обрабатывать целочисленные
величины, возвращаемыми g e t K e y C o d e , передавая их затем методу getKeyText.
Такой подход часто используется при работе с национальными кодировками. В до
полнение к g e t K e y C o d e в составе класса содержится также метод setKeyCode.
Объект Component, пол)^ающий событие, может быть определен с помощью мето
да getComponent, а время нажатия клавиши возвращает метод getWhen.
11.5. Стандартные обработчики событий 407
MouseListener
Данный интерфейс объявляет следующие пять методов:
p u b l i c void mouseEntered(MouseEvent event)
p u b l i c void mouseExited(MouseEvent event)
p u b l i c void mousePressed(MouseEvent event)
p u b l i c void mouseReleased(MouseEvent event)
p u b l i c void mouseClicked(MouseEvent event)
Методы m o u s e E n t e r e d и m o u s e E x i t e d соответствуют пересечению курсором мы
ши границы компонента, использующего обработчик. Метод m o u s e E n t e r e d вызы
вается тогда, когда курсор мыши входит в область, занимаемую компонентом, а
m o u s e E x i t e d — при выходе курсора из этой области. Кроме того, m o u s e E x i t e d вы
зывается в том случае, когда курсор указывает на другой компонент, который распо
ложен поверх компонента, связанного с обработчиком. Предположим, например,
что в области, занимаемой аплетом, расположена кнопка и вы перемещаете курсор
из-за пределов аплета на кнопку, а затем снова за пределы аплета. Сначала аплет по
лучит событие m o u s e E n t e r e d (это произойдет тогда, когда курсор пересечет грани
цу аплета), затем— событие m o u s e E x i t e d (при помещении курсора на кнопку), по
сле этого будет снова сгенерировано событие m o u s e E n t e r e d (когда курсор выйдет
за пределы кнопки и окажется в области аплета) и, наконец, событие m o u s e E x i t e d
(когда курсор покинет область аплета). Обратите внимание на то, что координаты х
и у, полученные в методе m o u s e E x i t e d , могут лежать за пределами аплета; более то
го, позиция курсора, определяемая в теле m o u s e E x i t e d , часто не имеет смысла.
Метод m o u s e P r e s s e d соответствует нажатию кнопки мыши, метод m o u s e R e l e a s e d —
отпусканию кнопки, а метод m o u s e C l i c k e d — ситуации, когда между нажатием и от^
пусканием координаты мыши не изменились. Так, например, если вы нажмете и отпус
тите кнопку, не передвигая мышь, будут вызваны методы m o u s e P r e s s e d ,
m o u s e R e l e a s e d и m o u s e C l i c k e d (в указанной последовательности). Если же вы на
жмете кнопку, передвинете мышь, затем отпустите кнопку, будут вызваны только
m o u s e P r e s s e d и m o u s e R e l e a s e d ; метод m o u s e C l i c k e d не получит управления.
Если вы хотите переопределить некоторые (но не все) методы, применяемые для
обработки событий, вы можете использовать класс адаптера Mouse A d a p t e r . Если
вы удалите (consume) событие в методе m o u s e P r e s s e d , графический компонент
не воспримет щелчок мышью. Для того чтобы определить, какая из кнопок была
нажата, можно использовать метод g e t M o d i f i e r s . Поскольку Java-программы мо
гут выполняться в системах, использующих однокнопочную (MacOS), двухкнопоч-
ную (Windows) или трехкнопочную (Unix) мышь, отдельные события для каждой
из кнопок в Java не предусмотрены. Значение, возвращаемое event.getModifiers(),
может быть равным M o u s e E v e n t . Button2_MASK, если нажата средняя кнопка,
или M o u s e E v e n t .Button3_MASK, если нажата правая кнопка мыши. Значение
M o u s e E v e n t . Button3_MASK соответствует правой кнопке даже в том случае, если
в системе используется двухкнопочная мышь. П р и наличии нескольких модифика
торов метод e v e n t . g e t M o d i f i e r s () может возвращать несколько установлен
ных флагов. Поэтому вместо проверки
(event.getModifiersО == event.ALT_MASK)
408 Глава 1 1 . События, связанные с мышью и клавиатурой
MouseMotionListener
В данном интерфейсе объявлены два метода:
p u b l i c v o i d mouseMoved(MouseEvent e v e n t ) —
p u b l i c v o i d mouseDragged(MouseEvent e v e n t )
"Пустые" варианты этих методов реализует класс адаптера Мои seMot i o n A d a p t e r .
Методы, принадлежащие M o u s e M o t i o n L i s t e n e r , вызываются при перемещении
мыши. Класс M o u s e E v e n t был описан при рассмотрении M o u s e L i s t e n e r .
TextListener
В составе этого интерфейса содержится единственный метод:
public void textValueChanged(TextEvent event)
Класса адаптера, соответствующего интерфейсу TextListener, не существует.
Данный обработчик применяется при работе с Text Area, Text Field и подкласса
ми класса TextComponent. Метод textValueChanged вызывается тогда, когда
текст изменяется, независимо от того, произошло ли это изменение в результате
действий пользователя или было выполнено программой (например, с помощью
setText или append).
WindowListener
Интерфейс WindowListener содержит семь методов:
public void windowOpened(WindowEvent event)
public void windowClosing(WindowEvent event)
public void windowClosed(WindowEvent event)
public void windowlconifled(WindowEvent event)
public void windowDeiconifled(WindowEvent event)
public void windowActivated(WindowEvent event)
public void windowDeactivated(WindowEvent event)
11.6. Низкоуровневая обработка событий 409
Если вам надо переопределить один или два метода, лучше всего воспользоваться
классом адаптера W i n d o w A d a p t e r , в котором реализованы "пустые" варианты ука
занных выше методов. Метод windowOpened вызывается при первом открытии
окна, метод w i n d o w C l o s i n g — тогда, когда пользователь пытается закрыть окно, а
метод w i n d o w C l o s e d соответствует реальному закрытию окна. Методы w i n d o w -
I c o n i f i e d и w i n d o w D e i c o n i f i e d вызываются соответственно при минимизации
окна и восстановлении его размеров. Методы w i n d o w A c t i v a t e d и w i n d o w -
D e a c t i v a t e d соответствуют тем ситуациям, когда окно заслоняется другим ок
ном, минимизируется либо деактивизируется любым другим способом. Метод
getWindow класса WindowEvent возвращает объект Window, определяюш^ий окно,
над которым выполняются действия.
Методика профессионалов
Листинг. 1 1 . 8 . M o u s e R e p o r t e r . J a v a
import java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
event.getXO + "," +
event.getYO + ").");
// В случае использования обработчика MouseListener:
super.processMouseEvent(event);
}
public void processMouseMotionEvent(MouseEvent event) {
System.out.println("Mouse move/drag at (" +
event.getXO + ", " +
event.getYO + ").");
// В случае использования обработчика MouseMotionListener:
super.processMouseMotionEvent(event);
}
t-4-l'i''IHJ-l'lU4'rl.H.H'NIHH.Ht4'-l
•j^ -;; "3 -Ti ^- ,^ • j ^ rf '^ -M a
Mouse Event Reporter Mouse enter/exit or click at (7.0).
Mouse move/drag at (7,0).
Mouse move/drag at (9.2).
Mouse move/drag at (11.4).
Mouse move/drag at (17.6).
Mouse move/drag at (23,14).
Mouse move/drag at (29.16).
Mouse move/drag at (31,18).
Mouse move/drag at (32,20)
Mouse move/drag at (34.22)
Mouse move/drag at (36.23).
Mouse move/drag at (38,24)
Mouse move/drag at (38,25).
Mouse enter/exit or click at (38.25)
Mouse enter/exit or click at (38.25)
Mouse enter/exit or click at (38.25)
Ш _J^
;isg*;«^j>»r Appiet Mo«.isefi»{
Листинг 1 1 . 9 . LanguageField.Java
import java.awt.^;
import Java.awt.event.*;
/ * * Компонент T e x t F i e l d , предназначенный для ввода н а з в а н и й
* языков программирования и к о р р е к т и р о в а н и я в в е д е н н о г о
* текста.
V
public class LanguageField extends TextField {
private String[] substrings =
{ "", "J", "Ja", "Jav", "Java" };
public LanguageField() {
addKeyListener(new SpellingCorrector ());
addActionListener(new WordCompleter());
addFocusListener(new SubliminalAdvertiser());
11.7. Поле редактирования с проверкой орфографии 413
import Java.applet.Applet;
import java.awt.*;
H,ti№HiflTlil'l'H'Hi'ii№k№a, рт1^Ш1-1пЩ|
d
Choose a Language, Any Language
J:
i^HyCompulef
Листинг 11.11.SimpleWhiteboard.Java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
X о
[ID
^_ ^,. . ^ ........ J
i # = ^ "' Ai^JtetS^rfeWhfteboafdrynntnQ ; >,^ У^ J ^ Q ^/^
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
/ • • Модифицированная ''чертежная доска" позволяет
* дополнять изображение текстом.
1 :^ Э ^1 j^. Ы ~s ё: ;3 13 Д:
Whiteboard Applet
Route
Park
29 Here О - Pond
- K-Ceiitei
• -•
11.9. Резюме
Аплет, созданный в последнем разделе данной главы, не так уж плох, если принять
во внимание размеры исходного кода. Однако в нем недостает многих важных
средств. Пользователь не может выбирать цвет и шрифт, задавать тип операций
(рисование отрезков прямых, окружностей, прямоугольников и др.). Кроме того,
изображение, нарисованное пользователем, недолговечно. Поскольку рисование
осуществляется непосредственно в окне, то как только область, занимаемая аплетом,
будет закрыта на время другим окном, изображение безвозвратно исчезнет. В главе 16
мы обсудим некоторые подходы, позволяющие разрешить эту проблему. Наиболее
часто используется двойная буферизация — технология, позволяющая рисовать изо
бражения вне экрана. В главе 13, посвященной компонентам AWT, мы рассмотрим
списки, раскрывающиеся меню и другие элементы графического пользовательского
интерфейса. Наконец, созданный аплет должен быть доступен большому числу поль
зователей. Способы создания серверов будут обсуждаться в главе 17.
ДИСПЕТЧЕРЫ
КОМПОНОВКИ
В ЭТОЙ главе...
Листинг 1 2 . 1 . FlowTGSt.Java
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
/** Диспетчер компоновки FlowLayout размещает компоненты
по строкам.
V
p u b l i c c l a s s FlowTest extends Applet {
p u b l i c void i n i t O {
f o r ( i n t i = l ; i<6; i++) {
add(new Button ("Button " -f- i) ) ;
}
}
}
Ap0et
Конструкторы FlowLayout
public FlowLayoutO
Данный конструктор создает диспетчер компоновки F l o w L a y o u t , который раз
мещает элементы по центру строки, оставляя между элементами в строке и между
строками интервал, равный пяти пикселям.
Методы FlowLayout
Диспетчер компоновки F l o w L a y o u t содержит также след)^ющие методы.
P a n e l р = new P a n e l ( ) ;
p.setLayout(new FlowLayout(FlowLayout.CENTER,10,5));
Ha первый взгляд может показаться, что второй способ более эффективен, по
скольку при этом не создается новый экземпляр F l o w L a y o u t . Однако следует учиты
вать, что изменения, выполненные таким способом, будут воздействовать и на другие
панели. Для каждой из панелей, использующей диспетчер компоновки F l o w L a y o u t ,
расстояние между элементами будет равно 10.
a d d ( b u t t o n F o r T o p , BorderLayout.NORTH);
a d d ( s c r o l l b a r F o r R i g h t S i d e , BorderLayout.EAST);
a d d ( p a n e l F o r R e m a i n i n g S p a c e , BorderLayout.CENTER);
^l4VI-)Hiyii;Hfr!l'!1tfPffiffMllirlgRl
Обратите также внимание на то, что при работе с BorderLayout не следует вклю
чать в область больше одного элемента. В противном случае новый элемент будет
размещен поверх включенного ранее. Если вам надо добавить в область несколько
элементов, разместите их в новом контейнере Panel и включите панель в требуемую
область.
424 Глава 1 2 . Д и с п е т ч е р ы компоновки
М е т о д и к а профессионалов
Конструкторы BorderLayout
public BorderLayoutO
Данный конструктор создает объект B o r d e r L a y o u t , области которого непосред
ственно граничат друг с другом.
Методы BorderLayout
Работая с контейнерами Frame и D i a l o g , в которых по умолчанию используется
рассматриваемый здесь диспетчер компоновки, не следует вызывать методы s e t H g a p
и s e t V g a p объекта, возвращаемого методом g e t L a y o u t . Подобные установки воз
действуют на все контейнеры, использующие по умолчанию B o r d e r L a y o u t . Подоб
ные рекомендации справедливы и для панелей содержимого объектов J F r a m e ,
JApplet,JWindow и JDialog.
Листинг 12.3. G r i d T e s t . J a v a
i m p o r t J a v a , a p p l e t .Applets-
import ja'va.awt.*;
/ * * Пример и с п о л ь з о в а н и я G r i d L a y o u t . */
i-Haii,!gy>"-'-'»H
Applet
Button Four Button Five Bunof) Stx 1 Рис. 12.3. Диспетчер компоновки
G r i d L a y o u t делит окно на прямоугольные
Applet started.
области одинакового размера
Конструкторы GridLayout
public GridLayout()
Данный конструктор создает в окне единственную строку, состоящую из одного
столбца. В полученной ячейке может быть размещен один компонент.
сительно своих соседей. Параметр rows или c o l s (но не оба одновременно) мо
жет быть равен 0. Если параметр rows равен О, исполняющая система Java старает
ся разделить окно на строки так, чтобы в каждом из столбцов находилось равное
(или приблизительно равное) число элементов. Аналогично, если параметр c o l s
равен О, система старается разделить окно на столбцы так, чтобы в каждой строке
находилось приблизительно равное число элементов. Данный подход иллюстри
рует код приложения, приведенный в листинге 12.4. В окне, как показано на
рис. 12.4, размещаются 11 кнопок, причем при создании диспетчера компоновки
указано нулевое число столбцов, а количество строк задается в командной строке.
Класс W i n d o w U t i l i t i e s . Java определен в листинге 14.1.
Листинг 1 2 . 4 . E l e v e n B u t t o n s . J a v a
import java.awt.*;
import javax.swing.*;
1 •
SunonS Sutton r e^ttons ' Buttond . SuttonIO
Методы GridLayout
public int getRowsO
p u b l i c void setRows(int rows)
Данные методы определяют и изменяют число строк.
p u b l i c int getHgapO
p u b l i c void setHgap(int hGap)
Данные методы определяют и изменяют интервал между столбцами.
p u b l i c int getVgapO
public void setVgap(int vGap)
Данные методы определяют и изменяют интервал между строками.
Panel cardPanel;
CardLayout layout;
Листинг 12.5.CardDemo.Java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
layout.next(cardDisplayPanel);
else
layout.show(cardDisplayPanel, source.getLeUDel0);
return;
}
}
Листинг 12.6.CardPanel.Java
import java.awt.*;
import java.net.*;
\ШЕшшшшшшшшшяшшштшшт
Applet , , ; ,
__^ Jack
yiie^si 1 1
'1
King
•
AC€
E
Last
Pr«vi«ii$
Г
Nesd; \ Ljji
Applet started.
Конструкторы CardLayout
public CardLayoutO
Данный конструктор создает экземпляр CardLayout, который располагает ком
поненты в верхнем левом углу окна.
Методы CardLayout
Класс CardLayout содержит перечисленные ниже методы. Заметьте, что пара
метр C o n t a i n e r указывает на окно, использующее CardLayout, а не на компонент.
G r i d B a g L a y o u t l a y o u t = new G r i d B a g L a y o u t ( ) ;
setLayout(layout) ;
GridBagConstraints c o n s t r a i n t s =
new G r i d B a g C o n s t r a i n t s ( ) ;
12.5. Диспетчер компоновки GridBagLayout 433
Объект GridBagConstraints
Помимо диспетчера компоновки, связываемого с контейнером, необходимо соз-
ать объект G r i d B a g C o n s t r a i n t s , который определяет ограничения при размеще-
ии каждого компонента. При включении компонента в контейнер метод)^ add также
ередается объект G r i d B a g C o n s t r a i n t s . После завершения работы метода add со-
гояние объекта G r i d B a g C o n s t r a i n t s может быть изменено, поэтому создавать от
ельный объект такого типа для каждого элемента Component нет необходимости. В
Tiacce G r i d B a g C o n s t r a i n t s определено большое количество полей; значения мно-
лх из них должны быть установлены для каждого компонента. Поля GridBagConst-
a i n t s описаны ниже.
0 1 2 3
0 Текстовая
область
V J
1 [ Кнопка ^ (Г1ол€ редактироЕ ания
Z)\ Рис. 12.6. Расположение компонентов и нап
2 (^Заполнитель J (^ Кнопка ) (^ Кнопка ) |
равление, в котором они должны расширяться
Листинг 1 2 . 7 . G r i d B a g T e s t . J a v a
import java.awt.*;
import Java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public GridBagTest0 {
setLayout(new GridBagLayout());
setBorder(BorderFactory.createEtchedBorder());
с = new GridBagConstraints0;
// Текстовая область.
с.gridx = О;
c.gridy = 0;
с.gridwidth = GridBagConstraints.REMAINDER;
с.gridheight = 1;
с.weightx = 1.0;
с.weighty = 1.0;
с.fill = GridBagConstraints.BOTH;
c.insets = new Insets(2,2,2,2); //t,l,b,r
add(textArea,c);
// кнопка Save A s .
с .gridx = 0;
с .gridy = 1;
с .gridwidth = 1;
с .gridheight = 1;
с .weightx = 0. 0
с .weighty = 0. 0
с .fill =
= Giri<
GridBagConstraints.VERTICAL;
асid(bSaveAs, c) .
// Поле редактирования.
с.gridx = 1;
с.gridwidth = GridBagConstraints.REMAINDER;
с.gridheight = 1;
с.weightx = 1.0;
с.weighty = 0.0;
c.fill = GridBagConstraints.BOTH;
add(fileField, c) ;
// Кнопка OK.
с.gridx = 2;
c.gridy++;
12.5. Диспетчер компоновки GridBagLayout 437
с.gridwidth = 1;
c.gridheight = 1;
с.weightx = 0.0;
с.weighty = 0.0;
с.fill = GridBagConstraints.NONE;
add(bOk,c) ;
// Кнопка Exit.
c.gridx = 3;
c.gridwidth = 1;
c.gridheight = 1;
с.weightx = 0.0;
с.weighty = 0.0;
c.fill = GridBagConstraints.NONE;
add(bExit,c);
// Заполнитель, используемый для того, чтобы
// столбец 1 имел ненулевую ширину.
Component filler = Box.createRigidArea(new Dimension(1,1))
c.gridx =1;
с.weightx = 1.0;
add(filler,c);
OK 1 P ^ 11 OK I
Рис. 12.7. Используя объект GridBag Рис. 12.8. Так выглядит контейнер с
Cons t r a i n t s , можно осуществлять диспетчером компоновки GridBag
контроль за расположением элементов, Layout, если в столбце 1 отсутствует
однако код программы становится элемент Box
достаточно сложным
438 Глава 12. Диспетчеры компоновки
Конструктор GridBagLayout
p u b l i c GridBagLayoutO
Диспетчер компоновки G r i d B a g L a y o u t содержит только один конструктор. Осо
бенности размещения компонентов задаются с помощью объекта G r i d B a g
Constraints.
Методы GridBagLayout
Диспетчер G r i d B a g L a y o u t содержит следующие методы.
p u b l i c GridBagConstraints g e t C o n s t r a i n t s ( C o m p o n e n t с)
Данный метод возвращает копию объекта G r i d B a g C o n s t r a i n t s , который был
использован при включении указанного компонента в состав контейнера.
p u b l i c P o i n t getLayoutOrigin()
Данный метод возвращает расположение левого верхнего угла G r i d B a g L a y o u t
относительно окна.
public d o u b l e [ ][ ] getLayoutWeights()
Метод g e t L a y o u t W e i g h t s возвращает значения w e i g h t x и w e i g h t y .
public v o i d s e t C o n s t r a i n t s ( C o m p o n e n t c o m p o n e n t , GridBagConstraints
constraints)
Данный метод регистрирует ограничения для указанного компонента. Этот метод
применяется редко, поскольку гораздо удобнее задать ограничения при включе
нии компонента в контейнер. Так, например, вместо
container.add(component);
layout.setConstraints(constraints);
удобнее использовать выражение
container.add(component, constraints);
12.6. Диспетчер ком поновки BoxLayout 439
JComponent.setAlignmentX(Component.Xxx_ALIGNMENT);
JComponent.setAlignmentY(Component.Xxx_ALIGNMENT);
Для большинства Swing-компонентов по умолчанию задано горизонтальное вы
равнивание по центру (Component .CENTER_ALIGNMENT). Компоненты J B u t t o n ,
JComboBox, J L a b e l и JMenu являются исключением из общего правила и выравни
ваются по левому краю ( C o m p o n e n t . LEFT_ALIGNMENT).
Простой пример использования диспетчера компоновки B o x L a y o u t с вертикаль
ным расположением ( B o x L a y o u t . Y_AXIS) представлен в листинге 12.8. В данном
примере фрагмент статического текста расположен в верхней части окна и по умол
чанию выравнивается по левому краю. Н и ж е текста находятся три кнопки. П р и акти
визации одной из них вызывается метод, который изменяет тип выравнивания для
всех трех кнопок и перестраивает содержимое контейнера (вызывает метод
r e v a l i d a t e ) . Для статического текста тип выравнивания не изменяется.
440 Глава 12. Диспетчеры компоновки
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
/** Пример использования BoxLayout. */
public BoxLayoutTest() {
layout = new BoxLayout (this, BoxLayout .Y__AXIS) ;
s e tLayou t (1 ayou t) ;
add(label);
add(topButton);
add(middleButton);
add(bottomButton);
setBackground(Color.white);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == topButton) {
refresh (Component. LEFT__ALIGNMENT) ;
} else if (event.getSource() == middleButton) {
refresh (Component. CENTER__ALIGNMENT) ;
} else if (event.getSource() == bottomButton) {
refresh(Component.RIGHT_ALIGNMENT);
}
}
private void refresh(float a l i g n m e n t ) !
topButton.setAlignmentX(alignment);
middleButton.setAlignmentX(alignment);
bottomButton. setAlignmentX (alignment) ;
revalidate();
System.out.println("x: "+layout.getLayoutAlignmentX(this));
}
public static void main(String[] args) {
WindowUtilities.setNativeLookAndFeel();
WindowUtilities.OpenlnJFrame(new BoxLayoutTest(), 300, 135,
"BoxLayoutTest");
12.6. Диспетчер компоновки BoxLayout 441
^::.:].|ми|р>ишм llllllll^ i
BoxLayout Demo BoxLayout Demo
|Lj-E!:^^?P'!*^„j| 1 LeftAiignment
(а) (6)
Рис. 12.9. (a) Расположение компонентов с помощью BoxLayout, если
для всех компонентов установлено значение выравнивания 0.0 (вырав
нивание по левому краю); (б) Расположение компонентов с помощью
BoxLayout, если выравнивание для статического текста равно 0.0, а для
кнопок— 1.0
Конструктор BoxLayout
Для диспетчера компоновки BoxLayout определен только один конструктор.
Внимание!
Методы BoxLayout
Ниже описаны наиболее часто используемые методы BoxLayout.
Листинг 12.9. N u l l T e s t . J a v a
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
/** Диспетчеры компоновки удобны в использовании, однако
* разработчик <В>не обязан</В> применять их.
* Чтобы отключить диспетчер компоновки, надо в качестве
* параметра метода setLayout задать значение n u l l .
Ч
public c l a s s NullTest extends Applet {
p u b l i c void i n i t O {
setLayout(null);
Button bl = new Button("Button 1")
Button b2 = new Button("Button 2")
Button b3 = new Button("Button 3")
Button b4 = new Button("Button 4")
Button b5 = new Button("Button 5")
444 Глава 12. Диспетчеры компоновки
Sutton 2 Button 3
И с п о л ь з о в а н и е влолсенных к о н т е й н е р о в
Ни в одном руководстве по программированию не сказано, что всю работу по раз
мещению компонентов в контейнере следует выполнять с помощью одного дис
петчера компоновки. Следуйте принципу "разделяй и властвуй".
Создание с о б с т в е н н ы х д и с п е т ч е р о в к о м п о н о в к и
Если вам не подходит ни один из стандартных диспетчеров компоновки, создайте
собственный.
12.8. Эффективное использование диспетчеров компоновки 445
Р е з е р в и р о в а н и е п у с т о г о п р о с т р а н с т в а вокруг к о м п о н е н т о в
Если в размещении компонентов вас устраивает все, за исключением интервалов
между ними, решить эту проблему помогут методы диспетчеров компоновки.
решений данной задачи. На этом примере хорошо видно, что код, реализующий вло
женные контейнеры, гораздо проще кода, приведенного в листинге 12.7, где для раз
мещения элементов используется один диспетчер компоновки GridBagLayout. Ре
зультат выполнения программы показан на рис. 12.12.
Текстовая область
Листинг 12.10.NestedLayout.Java
import java.awt.*;
import Java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
public NestedLayout() {
setLayout(new BorderLayout(2,2));
setBorder(BorderFactory.createEtchedBorder0);
add(textArea,BorderLayout.CENTER);
subPanell.add(bSaveAs,BorderLayout.WEST) ;
subPanell.add(fileField,BorderLayout.CENTER);
subPanel2.add(bOk) ;
subPanel2.add(bExit);
bottomPanel.add(subPanell);
bottomPanel.add(subPanel2);
add(bottomPanel,BorderLayout.SOUTH);
ШШШШШШШЩ
1
Листинг 12.11.ButtonCol.Java
import Java.applet.Applet;
import java.awt.*;
^.||.1.!Ш||^!1!|1!'Л|!Д'1?Ц||1.^.|'ИШ
Button One
BirttonTwo
Button four
Рис. 12.13. Контейнеры в окне верхнего
ByttonFw
уровня размещаются вручную, а элементы
внутри контейнеров — автоматически
И с п о л ь з о в а н и е о б ъ е к т о в C a n v a s и B o x в качестве н е в и д и м ы х заполнителей
В AWT объект C a n v a s , который не обрабатывает события, связанные с мышью и
на котором не выполняется рисование, может рассматриваться как "пустой" эле
мент, занимающий определенную часть окна. C a n v a s часто используется для ре
зервирования пространства при работе с диспетчерами компоновки F l o w L a y o u t ,
G r i d L a y o u t , G r i d B a g L a y o u t , B o x L a y o u t либо в областях NORTH,SOUTH, EAST и
WEST диспетчера B o r d e r L a y o u t .
П р и работе со Swing-компонентами в качестве невидимого заполнителя может
применяться объект Box. Класс Box выполняет следующие функции.
Листинг 12.12.InvisibleComponentTest.Java
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public InvisibleComponentTest() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
||||"^|ri|x|
Rigid Area - 20x75 pixels
ILSLJI ^'sht 1
iM 1 . R^ j
Horizontal Glue - FlowLayout
Left 1 mm 1
Horizontal Glue - BoxLayout
Рис. 12.14. Невидимый элемент Box
позволяет управлять расположением
Left 1 Right 1
компонентов
452 Глава 12. Диспетчеры компоновки
12.9. Резюме
Диспетчеры компоновки позволяют размещать элементы в окне. Использовать их
очень удобно в тех случаях, когда необходимо изменять размеры окна, добавлять
компоненты и переносить программу на другие платформы. Чаще всего используют
ся диспетчеры компоновки FlowLayout, BorderLayout, GridLayout, CardLayout
и GridBagLayout. В Java 2 для обеспечения гибкости при разработке программ до
бавлен дополнительный диспетчер BoxLayout. Если ни один из диспетчеров не под
ходит вам, можете отключить их и размещать компоненты вручную, однако не забы
вайте, что практически любую задачу создания интерфейса можно решить с помощью
вложенных контейнеров.
К настоящему времени вы уже имеете сведения об окнах и даже познакомились с
диспетчерами компоновки. Однако окна надо чем-то заполнять. В главе 13 вы узнаете
о кнопках, флажках и переключателях опций, полосах прокрутки и других компонен
тах графического пользовательского интерфейса.
КОМПОНЕНТЫ AWT
В ЭТОЙ главе...
• Класс Component.
1 3 . 1 . Класс Canvas
Компонент Canvas представляет собой простейшее окно, которое не может со
держать другие управляющие элементы. Поскольку независимый элемент Canvas су
ществовать не может, его обязательно надо помещать в другое окно. С Canvas нельзя
связать диспетчер компоновки. В программах объект Canvas обычно выполняет две
основные функции.
1. Создание областей рисования. Предположим, что вы создаете сложный графиче
ский интерфейс, в котором необходима поддержка операций рисования. Вместо
того чтобы рисовать непосредственно в окне, удобнее создать для этой цели от
дельный объект Canvas. Заметьте, что данный объект должен самостоятельно вы
полнять операции рисования, поэтому в нем надо переопределить метод p a i n t .
2. Создание новых компонентов. Многие компоненты, определяемые разработ
чиком, такие как статические картинки и кнопки с изображениями, создаются
на базе объектов Canvas.
В обоих случаях необходимо создавать подклассы Canvas. Непосредственно дан
ный класс применяется достаточно редко. Выполнять рисование с помощью объекта
G r a p h i c s , полученного посредством метода g e t G r a p h i c s , не рекомендуется, по
скольку методы u p d a t e и p a i n t класса Canvas взаимодействуют друг с другом. Вме
сто этого внешние программы должны создавать данные, доступные Canvas, а затем,
когда необходимо выполнить рисование, вызывать метод r e p a i n t класса Canvas.
1 3 . 1 . Класс Canvas 457
М е т о д и к а профессионалов
Листинг 1 3 . 1 . C i r c l e . J a v a
import java.awt.*;
/** Компонент Circle, созданный с использованием Canvas. */
setForeground(foreground);
width = 2*radius;
height = 2*radius;
setSize(width, height);
Листинг 13.2.CircleTest.Java
import java.awt.*;
import Java.applet.Applet;
/** Включение трех кругов в аплет, использующий FlowLayout.
Applet
На заметку
Листинг 13.3. C i r c l e T e s t : 2 . j a v a
import java.awt.*;
import Java.applet.Applet;
^ ^Ы Ж A ^^- Ш ^^ Ш Ш\
CircIeTest2
» .
Рис. 13.2. В AWT окна и управляющие
элементы имеют прямоугольную форму
'i^^ ••"^ф)"
и непрозрачны
460 Глава 13. Компоненты AWT
public v o i d a d d ( P o p u p M e n u m e n u )
public void r e m o v e ( M e n u C o m p o n e n t m e n u )
Метод a d d связывает с компонентом объект PopupMenu. Меню не отображается
на экране автоматически; для этого используется метод show класса PopupMenu.
Метод r e m o v e удаляет меню из компонента.
public v o i d addNotifyO
public void removeNotifyO
Метод a d d N o t i f y создает платформенно-ориентированный объект, связанный с
компонентом. Если для выполнения каких-либо действий надо, чтобы платфор
менно-ориентированный объект существовал, следует вызвать данный метод либо
метод s e t V i s i b l e . П р и определении новых компонентов необходимо вызвать
метод s u p e r . a d d N o t i f y . Метод r e m o v e N o t i f y удаляет платформенно-ориенти
рованный объект. Имена методов не совсем точно отображают выполняемые ими
действия. Назначение методов было бы более понятно, если бы они имели имена
createPeer и destroyPeer.
public F o n t M e t r i c s g e t F o n t M e t r i c s ( F o n t f)
Метод g e t F o n t M e t r i c s возвращает объект F o n t M e t r i c s , созданный на базе за
данного шрифта. Объект F o n t M e t r i c s используется для определения ширины и
высоты символов или строк, отображаемых данным шрифтом.
public Color g e t F o r e g r o u n d ( )
public void s e t F o r e g r o u n d ( C o l o r fgColor)
Данные методы определяют и устанавливают цвет переднего плана для компонен
та. Объект G r a p h i c s наследует цвет переднего плана компонента.
public P o i n t getLocationO
public void setLocation(int x, int y)
public void s e t L o c a t i o n ( F o i n t p)
Метод g e t L o c a t i o n возвращает объект P o i n t (содержащий поля x и у), который
указывает расположение верхнего левого угла компонента в системе координат
включающего окна. Для получения абсолютных координат используется метод
g e t L o c a t i o n O n S c r e e n . Варианты метода s e t L o c a t i o n перемещают верхний ле
вый угол компонента в позицию, заданную в системе координат включающего ок
на. Если включающее окно связано с диспетчером компоновки, диспетчер отменя
ет установленную позицию компонента.
p u b l i c Container getParent()
Метод g e t P a r e n t возвращает включающее окно (если объект Frame или
Component не связан с окном, возвращается значение n u l l ) .
p u b l i c D i m e n s i o n getSize()
public void setSize(int w i d t h , int height)
p u b l i c void s e t S i z e ( D i m e n s i o n d)
Метод g e t S i z e возвращает текущие размеры компонента в виде объекта Dimension,
содержащего поля w i d t h и h e i g h t . Метод s e t S i z e изменяет размеры компонента,
вызывая s e t B o u n d s . При вызове методу s e t B o u n d s передаются заданные ширина и
высота, а также текущие координаты верхнего левого угла компонента.
p u b l i c Toolkit getToolkit()
Данный метод возвращает объект T o o l k i t , который используется для загрузки изо
бражений ( g e t l m a g e ) , поиска доступных шрифтов ( g e t F o n t L i s t ) , определения раз
меров экрана ( g e t S c r e e n S i z e ) , его разрешения ( g e t S c r e e n R e s o l u t i o n ) и т.д.
p u b l i c void invalidateO
p u b l i c void validateO
Метод i n v a l i d a t e устанавливает внутренний флаг, указывающий на то, что дан
ный компонент и все вложенные компоненты некорректны и перед выводом не
обходимо проверить их расположение. Метод v a l i d a t e используется совместно с
классом C o n t a i n e r и предназначен для обновления размещения данного компо
нента и всех вложенных компонентов.
p u b l i c b o o l e a n isEnabled()
Метод i s E n a b l e d определяет, доступен ли данный компонент (см. описание ме
тода s e t E n a b l e d ) .
p u b l i c b o o l e a n isFocusTraversable()
Метод i s F o c u s T r a v e r s a b l e указывает, может ли компонент получить фокус по
сле нажатия пользователем клавиши <ТаЬ> или комбинации клавиш <Shift+Tab>.
Если метод возвращает значение f a l s e , компонент, тем не менее, может явно за
просить фокус с помощью метода r e q u e s t F o c u s .
464 Глава 1 3 . Компоненты AWT
М е т о д и к а профессионалов
public v o i d s e t £ n a b l e d ( b o o l e a n enabledFlag)
Метод s e t E n a b l e d делает AWT-компонент доступным ( t r u e ) или запрещает дос
туп к нему ( f a l s e ) . В большинстве операционных систем запрет управляющего
элемента приводит к тому, что оно отображается затененным на экране.
public void u p d a t e ( G r a p h i c s g)
Данный метод вызывается потоком передачи событий AWT после вызова метода
r e p a i n t . П о умолчанию при этом очищается экран, а затем вызывается метод
p a i n t ( g ) . Часто u p d a t e переопределяется так, чтобы перед вызовом p a i n t эк
ран не очищался. Данный подход типичен для рисования вне экрана с помощью
карты пикселей. Более детально рисование вне экрана мы обсудим в главе 16 при
рассмотрении двойной буферизации.
Листинг 1 3 . 4 . B e t t e r C i r c l e . J a v a
import java.awt.*;
/•• Модифицированный вариант класса Circle, использующий
* вместо Canvas "легковесные" компоненты Java 1.1.
import java.awt.*;
import java.applet.Applet;
BetterCircleTest
Внимание!
Если вы поместите пустой элемент Panel в контейнер, с которым ^
связан диспетчер компоновки FlowLayout, панель не будет видна на
экране.
470 Глава 13. Компоненты AWT
Листинг 1 3 . 6 . B u t t o n T e s t l . j a v a
import Java.applet.Applet;
import java.awt.'^;
/ * * В окно а п л е т а , использующего д и с п е т ч е р компоновки
* F l o w L a y o u t , включаются восемь кнопок, не объединенных
* в группы.
V
public class ButtonTestl extends Applet {
public void init() {
String[] labelPrefixes = { "Start", "Stop", "Pause",
"Resume" };
for (int i=0; i<4; i++) {
add(new Button(labelPrefixes[i] + " Threadl"));
}
for (int 1=0; i<4; i++) {
add(new Button(labelPrefixes[i] + " Thread2"));
}
}
}
13.4. Класс Panel 471
K3S3|
• Fte £cW V)«rt4 Favortfes Joote HeJp
Листинг 13.7.ButtonTest2.java
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
/** В каждую из панелей включаются четыре кнопки. */
p u b l i c c l a s s ButtonTest2 extends Applet {
p u b l i c void i n i t O {
S t r i n g [ ] l a b e l P r e f i x e s = { " S t a r t " , "Stop", "Pause",
"Resume" };
Panel p i = new P a n e l ( ) ;
for ( i n t i=0; i<4; i++) {
pi.add(new B u t t o n ( l a b e l P r e f i x e s [ i ] + " T h r e a d l " ) ) ;
}
Panel p2 = new P a n e l ( ) ;
for ( i n t i=0; i<4; i++) {
p2.add(new B u t t o n ( l a b e l P r e f i x e s [ i ] + " Thread2"));
}
add(pi);
add(p2);
ButtonTest2
j Staff Threadl j StopThreadl | Paute Threadl j Resume Threadl |
public C o m p o n e n t a d d ( C o m p o n e n t с)
public C o m p o n e n t a d d ( C o m p o n e n t с, Object constraints)
Первый из указанных методов помещает компонент в последнюю позицию масси
ва компонентов и используется со всеми стандартными диспетчерами компонов
ки. Единственным исключением является B o r d e r L a y o u t , где необходимо явно
задавать область B o r d e r L a y o u t .NORTH, B o r d e r L a y o u t . SOUTH, B o r d e r L a y o u t .
EAST, B o r d e r L a y o u t . WEST или B o r d e r L a y o u t .CENTER. Помимо двух приведен
ных методов a d d , класс Component содержит методы, позволяющие при включе
нии нового компонента задавать индекс в массиве компонентов. Подробнее эти
вопросы рассмотрены в разделе документации по API, посвященном j a v a . a w t .
Container.
public int g e t C o m p o n e n t C o u n t O
Данный метод возвращает число компонентов, содержащихся в контейнере. Под-
считываются все компоненты, в том числе невидимые (см. описание метода
i s V i s i b l e класса C o m p o n e n t ) .
public C o m p o n e n t g e t C o m p o n e n t ( i n t position)
Метод g e t Component возвращает N-й элемент, содержащийся в контейнере
(окне). Номер О соответствует первому из включенных компонентов. Если вы за
дадите номер позиции больший или равный значению, возвращаемому методом
g e t C o m p o n e n t C o u n t , будет сгенерировано исключение A r r a y l n d e x O u t O f B o -
undsException.
public C o m p o n e n t [ ] g e t C o m p o n e n t s ( )
Данный метод возвращает массив компонентов, содержащихся в контейнере
(окне). Массив может иметь нулевую длину; значение n u l l никогда не возвраща
ется вместо массива.
13.5. Класс Container 473
Листинг 13.8.ScrollPaneTest-Java
import Java.applet.Applet;
import j ava.awt.*;
|.^^.f-ui»;i!^u'i''iJii.^ffViffMPf?TWT^''^^^
Apptet
1 Button 92 Button 93 Sutt8n94 Button 96 Butt* Р1ЛС. 13.6. Окно S c r o l l P a n e можно прокручивать,
Lu ^ ^1 отображая части включенного компонента, лежащие
Applet started. 1 за пределами окна
Для того чтобы создать окно Frame, размеры которого определяются размерами
компонентов, содержащихся в окне, надо написать фрагмент кода, подобный приве
денному ниже.
/ / Создание объекта Frame.
Frame frame = new F r a m e ( t i t l e S t r i n g ) ;
/ / Позиционирование компонента Frame (необязательное действие).
frame.setLocation(left, top);
/ / Добавление компонентов.
frame.add(somePanel, BorderLayout.CENTER);
/ / Растягивание компонента Frame.
frame.packO ;
/ / Отображение компонента Frame,
frame.setVisible(true);
Вызывая метод pack, вы создаете платформенно-зависимый компонент Frame
(см. описание метода addNotif у класса Component), и диспетчер компоновки распо
лагает все компоненты в контейнере. Размеры окна не превышают необходимые для
размещения компонентов.
Если вы хотите запретить пользователю изменять размеры Frame, вызовите метод
s e t R e s i z e a b l e ( f a l s e ) . Определить размеры экрана перед позиционированием
Frame можно, вызвав метод g e t S c r e e n S i z e объекта, возвращаемого методом
g e t T o o l K i t . Следующий фрагмент кода располагает окно Frame по центру экрана.
Toolkit t o o l k i t = frame.getToolkit();
Dimension s c r n S i z e = t o o l k i t . g e t S c r e e n S i z e ( ) ;
Dimension frameSize = f r a m e . g e t S i z e ( ) ;
frame.setLocation((scrnSize.width-frameSize.width)/2,
(scrnSize.height-frameSize.height)/2);
Аплеты также могут генерировать окна на базе Frame, однако они обычно поме
чаются специальными сообщениями "Unsigned Java Applet Window" — при рабо
те с Netscape (рис. 13.7) или "Warning: Applet Window" (при работе с Internet
Explorer). Это затрудняет работу с раскрывающимися окнами в аплетах.
Листинг 1 3 . 9 . F r a m e E x a m p l e l . J a v a
import java.awt.*;
p u b l i c c l a s s FrameExamplel {
public s t a t i c void main(String[] args) {
Frame f = new F r a m e ( " F r a m e Example 1")
f.setSize(400, 300);
f.setVisible(true);
}
} '
Листинг 1 3 . 1 0 . F r a m e E x a m p l e 2 . j a v a
import java.awt.*;
Листинг 13.11.CloseableFrame.Java
import java.awt.*;
import Java.awt.event.*;
Меню
Окно Frame позволят использовать строку меню, содержащую одно или несколько
раскрывающихся меню. Для работы с меню надо сначала создать объект MenuBar, а
затем один или несколько объектов Menu. В объект Menu можно включать объект
S t r i n g , другой объект Menu (для организации каскадных меню) либо объект
C h e c k b o x M e n u I t e m (для выбора пунктов с помощью флажков опций). Созданные
меню надо включить в MenuBar с помощью метода add, принадлежащего MenuBar
(при этом меню располагаются слева направо), либо посредством метода s e t H e l p -
Menu (в этом случае меню помещается в крайнюю правую позицию строки). Готовый
объект MenuBar включается в окно Frame с помощью метода s e t M e n u B a r этого объ
екта. Для поддержки событий с каждым из меню необходимо связать обработчик
A c t i o n L i s t e n e r . Для определения пункта меню, выбранного пользователем, можно
обратиться к методу e v e n t . g e t A c t i o n C o m m a n d . В листинге 13.12 приведен пример,
в котором создается меню для выбора цвета и в соответствии с решением пользовате
ля устанавливается цвет фона для окна Frame. Результаты выполнения программы
показаны на рис. 13.8.
Листинг 1 3 . 1 2 . C o l o r M e n u . J a v a
import java.awt.*;
import Java.awt.event.*;
/ * * Демонстрирует с о з д а н и е меню окна Frame
p u b l i c c l a s s ColorMenu e x t e n d s C l o s e a b l e F r a m e
implements A c t i o n L i s t e n e r {
p r i v a t e S t r i n g [ ] colorNames =
{ " B l a c k " , " W h i t e " , " L i g h t G r a y " , "Medium G r a y " ,
"Dark G r a y " };
private Color[] colorValues =
{ Color.black, Color.white, Color.lightGray,
C o l o r . g r a y , C o l o r . d a r k G r a y };
p u b l i c ColorMenu0 {
super("ColorMenu");
MenuBar b a r = new M e n u B a r ( ) ;
Menu ColorMenu = new M e n u ( " C o l o r s " ) ;
f o r ( i n t i = 0 ; i < 2 ; i++) {
ColorMenu.add(colorNames[i]);
}
Menu grayMenu = new M e n u ( " G r a y " ) ;
f o r ( i n t i = 2 ; i < c o l o r N a m e s . l e n g t h ; i++) {
grayMenu.add(colorNames[i]) ;
}
ColorMenu.add(grayMenu);
bar.add(ColorMenu) ;
setMenuBar(bar) ;
ColorMenu.addActionListener(this);
grayMenu.addActionListener(this);
1 3 . 8 . Класс Frame 481
setBackground(Color.lightGray);
setSize(400, 200);
setVisible(true) ;
}
Для того чтобы закрыть окно Frame, созданное в аплете, надо вме
сто System, exit использовать метод dispose.
482 Глава 13. Компоненты AWT
public b o o l e a n isResizable()
public void s e t R e s i z a b l e ( b o o l e a n resizeFlag)
По умолчанию пользователям разрешается изменять размеры созданного вами
окна. Вызвав s e t R e s i z a b l e ( f a l s e ) , вы запретите изменение размеров. Метод
i s Re s i z a b l e позволяет определить текущую установку.
Листинг 13.13.SavedFrame.Java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public SavedFrameO {
super("SavedFrame");
setBackground(Color.white) ;
setFont(new Font("Serif", Font.BOLD, 18));
circlePanel = new CirclePanel();
add("Center", circlePanel);
Panel buttonPanel = new Panel();
buttonPanel.setBackground(Color.lightGray);
clearButton = new Button("Clear");
saveButton = new Button("Save");
buttonPanel.add(clearButton);
buttonPanel.add(saveButton);
add(buttonPanel, BorderLayout.SOUTH);
clearButton.addActionListener(this);
saveButton.addActionListener(this);
setSizeOOO, 300) ;
setVisible(true);
}
/** После щелчка на кнопке Clear удаляются все нарисованные
* Кнопка Save позволяет сохранить на диске текущее
* состояние окна (размеры, расположение, содержимое и др.)
V
public void actionPerformed(ActionEvent event) {
if (event.getSource() == clearButton) {
circlePanel.removeAll();
circlePanel.repaint();
} else if (event.getSource() == saveButton) {
try {
FileOutputStream fileOut =
new FileOutputStreamC'SavedFraiae. ser") ;
ObjectOutputStream out =
new ObjectOutputStream(fileOut);
out.writeObject(this);
out.flush();
out.close 0 ;
} catch(lOException ioe) {
System.out.println("Error saving frame: " + ioe);
}
}
486 Глава 13. Компоненты AWT
import java.awt.*;
import Java.awt.event.*;
import java.io.*;
/** Панель, в которой отображаются круги с центром в точке,
* на которую указывает курсор мыши.
* <В> Диспетчер компоновки не используется.</В>.
Листинг 1 3 . 1 5 . C o n f i r m . J a v a
import java.awt.*;
import Java.awt.event.*;
p u b l i c Confirm(Frame p a r e n t ) {
488 Глава 13. Компоненты AWT
Листинг 13.16.ConfirmTest.Java
import java.awt.*;
import j ava.awt.event.*;
)^;г|ДДЛ^Р^ЗЯ^
»6^yeiy)i^
||ц^||^^|Ш Рис. 13.10. Модальное диалоговое окно
запрещает все действия с другими
компонентами
Листинг 1 3 . 1 7 . D i s p l a y F i l e . J a v a
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
import j a v a . i o . * ;
/** Использование F i l e D i a l o g для выбора файла. */
p u b l i c c l a s s D i s p l a y F i l e extends CloseableFrame
490 Глава 13. Компоненты AWT
implements ActionListener {
J!*] BetterScrolbai lava ^ Choice? e$J lava aJColorMenujava public class DisplayFile extends CloseableFrame
«] ColofPopupMenu implements ActionListener{
j j l BgReporter lava a j C»cte lava
e] BuHonExampte lava ^ C»clePanel.|ava Mj Confirm. Java
public static void main(StringQ args) {
jej Button! e$(1|ava ;^C«cleTe$t|ava jgjContirmTest.iava
nev^^DisplayFileO;
.<i| ButtonTesl2.iava i ^ CircleTestZiava
Щ Checkboxes. Java ^ CioseabieFrdme.iava iMj FgRepoitet java
private Button loadButton;
b] I private TextArea fileArea;
private FileDialog loader;
Fjtejoome:
FiwoTj**.
JDisplayFile.iava
JAHFilesf"") 3
Qp«n
3 public DisplayFileO{
superfUsing FileDialog^;
loadButton = new ButtonCDisplay File"),
loadButton.addActionListener(this);
Panel buttonPanel = nev^ PaneiQ,
buttonPanel add(loadButton),
add(buttonPanel, BorderLayout SOUTH).
Ы ^ 1^:
gj^e^^f^l [pteggFjgi
Рис. 13.11. В окне Frame отображаются кнопка и Рис. 13.12. После того как пользо
объект TextArea. При активизации кнопки вызывает ватель выберет файл, его содержи
ся окно F i l e D i a l o g мое отобразится в области TextArea
window.setSize(width, height);
// либо указание размеров и позиции,
size.setBounds(left, top, width, height);
// Отображение объекта Window,
window.setVisible(true);
Окно Window, размеры которого вычисляются на основе размеров содержащихся
в нем компонентов, создается следующим образом.
// Создание объекта Window.
Window window = new Window(parentFrame);
// Позиционирование окна (необязательное действие).
window.setLocation(left, top);
// Добавление компонентов.
winddow.add(somePanel, BorderLayout.CENTER);
Листинг 1 3 . 1 8 . A c t i o n E x a m p l e l , Java
import java.awt.*;
public class ActionExamplel extends CloseableFrame {
public static void main(String[] args) {
new ActionExamplel();
}
public ActionExamplel() {
super("Handling Events in Component");
setLayout(new FlowLayout());
setFont(new Font("Serif", Font.BOLD, 18));
add(new SetSizeButton(300, 200)),
add(new SetSizeButton(400, 300))
add(new SetSizeButton(500, 400))
setSize(400, 300);
setVisible(true);
}
Листинг 13.19.SetSizeButton.Java
import Java.awt.*;
import j ava.awt.event,*;
parent = getParentO;
addActionListener(this)
import j a v a . a w t . * ;
import j a v a . a w t . e v e n t . * ;
p u b l i c c l a s s ActionExample2 extends CloseableFrame
implements ActionListener {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new ActionExample2();
}
p r i v a t e Button b u t t o n l , b u t t o n 2 , b u t t o n S ;
p u b l i c ActionExample2() {
super("Handling Events in Other O b j e c t " ) ;
496 Глава 13. Компоненты AWT
setLayout(new FlowLayout());
setFont(new Font("Serif", Font.BOLD, 18))
buttonl = new Button("Resize to 300x200")
button2 = new Button("Resize to 400x300")
button3 = new Button("Resize to 500x400")
buttonl.addActionListener(this) ;
button2.addActionListener(this);
button3.addActionListener(this);
add(buttonl);
add(button2);
add(button3);
setSize(400, 300);
setvisible(true);
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == buttonl) {
updateLayout(300, 200);
} else if (event.getSource0 == button2) {
updateLayout(400, 300);
} else if (event.getSource0 == button3) {
updateLayout(500, 400);
}
}
private void updateLayout(int width, int height) {
setSize(width, height);
invalidate();
validate();
}
Конструкторы
в классе Button предусмотрены следующие два конструктора.
public ButtonO
public Button(String buttonLabel)
Первый конструктор создает кнопку без надписи. Надпись (метку) можно доба
вить позже, воспользовавшись для этого методом s e t L a b e l . Даже если надпись
13.14. Класс Button 497
import j a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
p u b l i c c l a s s Buttons extends Applet {
p r i v a t e Button b u t t o n l , b u t t o n 2 , b u t t o n s ;
p u b l i c void i n i t O {
b u t t o n l = new Button("Button One");
button2 = new Button("Button Two");
b u t t o n s = new Button("Button T h r e e " ) ;
add(buttonl);
add(button2) ;
add(buttons) ;
}
шшшшшшшшвшшяяиошш^
' ^ ^ a 5} ^, за -1. iT :!i и di
Buttons
pOn« BietonTwo Button Thf«»j
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
p u b l i c c l a s s ButtonExample extends CloseableFrame {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new ButtonExample();
}
p u b l i c ButtonExample() {
super("Using A c t i o n L i s t e n e r s " ) ;
setLayout(new FlowLayout());
Button bl = new Button("Button 1")
Button b2 = new Button("Button 2")
Button b3 = new Button("Button 3")
bl.setBackground(Color.lightGray);
b2.setBackground(Color.gray);
b3.setBackground(Color.darkGray) ;
FgReporter fgReporter = new F g R e p o r t e r ( ) ;
BgReporter bgReporter = new BgReporter();
SizeReporter s i z e R e p o r t e r = new S i z e R e p o r t e r ( ) ;
bl.addActionListener(fgReporter);
b2.addActionListener(fgReporter);
b2.addActionListener(bgReporter);
500 Глава 13. Компоненты AWT
ЬЗ.addActionListener(fgReporter);
ЬЗ.addActionListener(bgReporter);
ЬЗ.addActionListener(sizeReporter)
add(bl)
add(b2)
add(b3)
setSize(350, 100) ;
setVisible(true);
import Java.awt.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.*;
Листинг 13.25.SizeReporter.Java
import Java.awt.event.*;
impo rt j ava.awt.*;
Foreground: J a v a . a w t . C o l o r [ r = 0 , g = 0 , b = 0 ]
Foreground: j a v a . a w t . C o l o r [ r = 0 , g = 0 , b = 0 ]
Background: j a v a . a w t . C o l o r [ r = 1 2 8,g=12 8,b=12 8]
Foreground: j a v a . a w t . C o l o r [ r = 0 , g = 0 , b = 0 ]
Background: J a v a . a w t . C o l o r [ r = 6 4 , g = 6 4 , b = 6 4 ]
S i z e : 59x23
Конструкторы
Следующие три конструктора создают флажки опций, которые могут быть установ
лены либо сброшены независимо друг от друга. Два других конструктора, которые при
меняются при создании переключателей опций, будут описаны в следующем разделе.
public CheckboxO
public Checkbox(String checkboxLabel)
public Checkbox(String c h e c k b o x L a b e l , b o o l e a n state)
Первый из приведенных конструкторов создает флажок опции без надписи
(текстовой метки). По умолчанию флажок сброшен. Второй конструктор создает
502 Глава 13. Компоненты AWT
import j a v a . a w t . * ;
public class Checkboxes extends CloseableFrame
public static void main(String[] args) {
new Checkboxes();
}
public Checkboxes 0 {
super("Checkboxes");
setFont(new Font("SansSerif", Font.BOLD, 1£ )) ,
setLayout(new GridLayout(0, 2));
Checkbox box;
for(int i=0; i<12; i++) {
box = new Checkbox("Checkbox " + i ) ;
if (i%2 == 0) {
box.setState(true);
}
add(box);
}
packO ;
setVisible(true);
ШЕШЗШШШШ
И И И И Д И Д ' "'|i"ii 1 |i
F Checkbox p: Г Checkbox 1
F Checkbox 2 Г Checkbox 3
F Checkbox 4 Г Checkbox 5
F Checkbox 6 Г Checkbox 7 Рис. 13.16. Так выглядят
F Checkbox 8 Г Checkbox 9 создаваемые Java-программой
флажки опций в операционной
F Checkbox 10 Г Checkbox 11
системе Windows 98
13.15. Класс Checkbox 503
Методы Checkbox
Н и ж е описаны восемь наиболее часто используемых методов класса C h e c k b o x .
p u b l i c b o o l e a n getState()
public void setState(boolean checkedState)
Метод g e t S t a t e позволяет определить состояние элемента. Если возвращаемое зна
чение равно t r u e — флажок установлен. Значение f a l s e соответствует сброшенному
флажку. Метод s e t S t a t e позволяет установить либо сбросить флажок опции.
public v o i d a d d I t e m L i s t e n e r ( I t e m L i s t e n e r listener)
p u b l i c v o i d r e m o v e I t e m L i s t e n e r ( I t e m L i s t e n e r listener)
Метод a d d l t e m L i s t e n e r связывает объект I t e m L i s t e n e r с флажком опции, а
метод r e m o v e I t e m L i s t e n e r разрывает эту связь. Использование данных методов
мы обсудим ниже.
public v o i d p r o c e s s I t e m E v e n t ( I t e m E v e n t event)
Данный метод предназначен для низкоуровневой обработки событий. Используя
метод p r o c e s s I t e m E v e n t , надо разрешить пер>едачу событий и включить в тело
метода вызов s u p e r . p r o c e s s I t e m E v e n t .
public Object[ ] g e t S e l e c t e d O b j e c t s O
Данный метод возвращает массив, состоящий из одного элемента. В массиве со
держится либо метка (если флажок установлен), либо значение n u l l (если флажок
сброшен).
Подобно прочим элементам графического интерфейса, C h e c k b o x наследует все
методы класса Component.
Конструкторы
в данном разделе описываются конструкторы C h e c k b o x G r o u p и C h e c k b o x .
CheckboxGroup
public CheckboxGroupO
Данный конструктор создает объект C h e c k b o x G r o u p , который не имеет графиче
ского представления, а лишь объединяет элементы C h e c k b o x в одну группу.
Внешний вид элементов C h e c k b o x , объединенных с помощью C h e c k b o x G r o u p ,
также изменяется. В каждый момент времени может быть выбран лишь один эле
мент в группе.
13.16. Переключатели опций 505
Checkbox
public Checkbox(String label, CheckboxGroup group, boolean state)
public Checkbox(String label, boolean state, CheckboxGroup group)
Первый из приведенных конструкторов создает элемент переключателя, связан
ный с указанной группой и помеченный заданной кнопкой. Параметр s t a t e опре
деляет состояние компонента по умолчанию. Если значение параметра s t a t e
равно t r u e для нескольких элементов в группе, выбирается последний из этих
элементов. Второй конструктор выполняет те же функции, что и первый, но по
рядок следования параметров в нем изменен.
Листинг 13.28.CheckboxGroups.Java
import java.applet.Applet;
import j ava.awt.*;
С Strawbeny ГШда
Рис. 13.17. Переключатели опций (слева)
и флажки опций (справа), отображаемые в
Applet started.
системе Windows 98
CheckboxGroup
public Checkbox getSelectedCheckbox()
Метод g e t S e l e c t e d C h e c k b o x возвращает выбранный в данный момент пере
ключатель опции (Checkbox). Если ни один из переключателей не выбран, воз
вращается значение n u l l .
Checkbox
в дополнение к методам, описанным в предыдущем разделе, класс Checkbox со
держит также методы, специфические для элементов, объединенных в группу.
somePanel.add(choice) ;
Конструктор
в icTiacce C h o i c e определен единственный конструктор, используемый по умолча
нию.
public Choice()
Данный конструктор создает пустой раскрывающийся список. Пункты списка до
бавляются с помощью метода a d d .
Листинг 13.29.ChoiсеТвSt.Java
import java.applet.Applet;
import java.awt.*;
[Choice 1 Д
IChoice 2 1 j
Ichoice 3 1 1
i Applet started. 1
Листинг 13.30.ChoiceTest2.Java
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
510 Глава 13. Компоненты AWT
import Java.awt.event.*;
public class ChoiceTest2 extends Applet
implements ItemListener {
private Choice choice;
public void initO {
setFont(new Font("SansSerif", Font.BOLD, 36));
choice = new Choice();
choice.addltem("Choice 1");
choice.addltem("Choice 2 " ) ;
choice.addltem("Choice 3");
choice.addltemListener(this);
add(choice);
}
public void itemStateChanged(ItemEvent event) {
Choice choice = (Choice)event.getSource();
String selection = choice.getSelectedltem();
if (selection.equals("Choice 1")) {
doChoicelAction();
} else if (selection.equals("Choice 2")) {
doChoice2Action();
} else if (selection.equals("Choice 3")) {
doChoice3Action();
}
add(list);
13.18. Элемент List 511
Конструкторы
в классе L i s t предусмотрены три конструктора.
public List()
public List(int rows)
public List(int rows, b o o l e a n multiSelectable)
Первый конструктор создает окно списка, допускающее выбор лишь одного пунк
та. Ш и р и н а и высота элемента зависят от платформы. Второй конструктор созда
ет окно списка с заданным числом строк. Как и в предыдущем случае, созданный
элемент допускает выбор только одного пункта списка.
Последний из представленных выше конструкторов создает окно списка, содер
жащее указанное число строк. Число строк определяет высоту элемента, но не
максимальное число пунктов списка. Если все пункты списка не помещаются в ок
не, автоматически создается полоса прокрутки. Второй параметр указывает, дол
жен ли элемент допускать выбор нескольких пунктов списка. Как и ддя элемента
C h o i c e , конструктор L i s t создает пустое окно; пункты списка добавляются по
средством метода a d d l t e m или add. Ш и р и н а элемента зависит от платформы и,
как правило, не определяется максимальными размерами пункта списка. П р и на
писании программы вы можете явным образом указать размеры элемента (если
используемый диспетчер компоновки разрешит сделать это).
Листинг 1 3 . 3 1 . L i s t s . J a v a
import java.awt.*;
public class Lists extends CloseableFrame {
public static void main(String[] args) {
new Lists();
public Lists() {
super("Lists");
setLayout(new FlowLayout());
setBackground(Color.lightGray);
setFont(new Font("SansSerif", Font.BOLD, 18));
List listl = new List(3, false);
listl.add("Vanilla") ;
listl.add("Chocolate");
listl.add("Strawberry");
add(listl);
512 Глава 13. Компоненты AWT
public b o o l e a n isMultipleMode()
Данный метод позволяет определить, допускает ли элемент выбор одного ( f a l s e )
либо нескольких ( t r u e ) пунктов списка.
public int g e t l t e m C o u n t O
Метод g e t l t e m C o u n t возвращает число пунктов в списке.
13.18. Элемент List 513
public void d e s e l e c t ( i n t i t e m l n d e x )
Если пункт, соответствующий указанному индексу, выбран, метод d e s e l e c t отме
няет его выбор. Если пункт не выбран, никакие действия не выполняются.
public String g e t l t e m ( i n t i t e m l n d e x )
public String[] g e t l t e m s O
Первый из приведенных методов возвращает метку, соответствующую пункту в
указанной позиции. Второй метод возвращает массив меток в порядке следования
пунктов.
public int g e t S e l e c t e d l n d e x O
public int[] g e t S e l e c t e d I n d e x e s ( )
Для элемента, допускающего выбор только одного пункта списка, первый метод по
зволяет определить индекс выбранного пункта. Если ни один пункт не выбран либо
если элемент допускает выбор нескольких пунктов, возвращается значение -1. Вто
рой метод возвращает массив индексов выбранных пунктов. Если ни один пункт не
выбран, возвращается массив нулевой длины (но не значение n u l l ) .
public String g e t S e l e c t e d l t e m O
public String[ ] g e t S e l e c t e d I t e m s ( )
Для элемента, допускающего выбор только одного пункта списка, первый метод
позволяет определить метку, соответствующую выбранному пункту. Если ни один
пункт не выбран либо если элемент допускает выбор нескольких пунктов, возвра
щается значение n u l l . Второй метод возвращает массив индексов выбранных
пунктов. Он может использоваться как при работе с элементами, допускающими
выбор одного пункта, так и с элементами, позволяющими выбирать несколько
пунктов. Если ни один пункт не выбран, возвращается массив нулевой длины (но
не значение n u l l ) .
public Object[ ] g e t S e l e c t e d O b j e c t s ( )
Метод g e t S e l e c t e d O b j e c t s возвращает массив меток, соответствующих вы
бранным пунктам. Если ни один пункт не выбран, возвращается значение n u l l .
514 Глава 13. Компоненты AWT
Листинг 1 3 . 3 2 . L i s t E v e n t s . J a v a
import java.awt.*;
import Java.awt.event.*;
Листинг 13.33.SelectionReporter.Java
import java.awt.^;
import Java.awt.event.
13.18. Элемент List 517
import j ava.awt.*;
import Java.awt.event.^;
^List Event»
Choose Language Last Selection:
±J Java
Pascal
Last Action:
Perl Рис. 13.20. Внешний вид приложения после двойного щелчка
Scheme ^Pascal
на пункте "Pascal" и одного щелчка на пункте "Java"
518 Глава 13. Компоненты AWT
Листинг 13.35.ListEvents2.Java
import Java.awt.event.*;
public class ListEvents2 extends ListEvents {
public static void main(String[J-args) {
new ListEvents2();
}
/** Расширенный класс ListEvents. Ввод любого
* символа, входящего в состав "JAVA" или "Java",
* приводит к выбору пункта "Java".
public ListEvents2 () {
super ();
// Создание KeyAdapter и связывание его с languageList.
// Поскольку обработчик является внутренним классом,
// он имеет доступ ко всем данным и методам, в частности
// к методу showJava класса ListEvent.
KeyAdapter javaChooser = new KeyAdapter() {
public void keyPressed(KeyEvent event) {
int key = event.getKeyChar0;
if ("JAVAjava".indexOf(key) != -1) {
showJava{);
languageList.addKeyListener(javaChooser)
}
}
temperatureString = simulationTemperature("F");
temperatureField.setText(temperatureString);
Конструкторы
в классе T e x t F i e l d определено четыре конструктора.
p u b l i c TextFieldO
public TextField(int numChars)
p u b l i c TextField(String initialString)
public TextField(String initialString, int numChars)
Первый из приведенных здесь конструкторов создает пустое поле редактирования,
ширина которого зависит от операционной системы (обычно она равна одному сим
волу). Второй конструктор создает пустое поле редактирования, ширина которого
достаточна для размещения указанного числа символов. Заметьте, что при использо
вании пропорциональных шрифтов различные символы имеют разные горизонталь
ные размеры, поэтому для вычисления ширины элемента используется усредненная
ширина символа. Третий конструктор создает поле редактирования, инициализиро
ванное указанной строкой. Ширина его достаточна для того, чтобы разместить данную
строку. Последний из конструкторов создает элемент указанной ширины, инициали
зированный заданной строкой. Ширина поля редактирования вычисляется на основе
усредненных размеров символов, отображаемых конкретным шрифтом.
Листинг 1 3 . 3 6 . Т е х t F i e l d s . J a v a
import Java.applet.Applet;
import java.awt.*;
/** Компоненты T e x t F i e l d , с о з д а в а е м ы е каждым и з четырех
к о н с т р у к т о р о в */
520 Глава 13. Компоненты AWT
^iQjjdj
Apptet
Г
1
Initial String
; j Initial
Рис. 13.21. Элементы T e x t F i e l d , созданные каждым
Applet started.
из четырех конструкторов
Методы TextField
Класс T e x t F i e l d является подклассом класса T e x t C o m p o n e n t . Н и ж е будут описа
ны методы обоих классов. Чаще всего используются методы g e t T e x t и s e t T e x t
(получение и установка содержимого T e x t F i e l d ) , s e t E d i t a b l e (разрешение и за
прещение ввода текста), g e t C o l u m n s и s e t C o l u m n s (определение и установка ши
р и н ы элемента T e x t F i e l d ) и s e t E c h o C h a r (отображение знака "*" либо другого
символа при вводе текста; обычно используется при вводе пароля).
public b o o l e a n echoCharIsSet()
Данный метод позволяет определить, был ли установлен эхо-символ (см. описание
метода s e t E c h o C h a r ) .
Конструкторы
Разработчику, использующему T e x t A r e a , доступны пять конструкторов данного
класса.
public TextAreaO
Этот конструктор создает пустую текстовую область, содержащую вертикальную и
горизонтальную полосы прокрутки. Количество строк и столбцов зависит от one-
524 Глава 13. Компоненты AWT
p u b l i c TextArea(String initialString)
Данный конструктор создает текстовую область, которая содержит вертикальную
и горизонтальную полосы прокрутки и инициализирует элемент указанной стро
кой текста. Строка, передаваемая в качестве параметра, может содержать символы
перевода строки ( \ п ) .
Листинг 1 3 . 3 7 . T e x t A r e a s . J a v a
import Java.applet.Applet;
import java.awt.*;
iiiiiiiifc'.'.'''jM^f
Apptel
1 J Some
Initial
Text
J i
J
Рис. 13.22, Текстовые области, отображаемые
Applet started
в Windows 98
1 3 . 2 1 . Класс Label
Объект L a b e l предназначен для отображения статического текста. В большинст
ве случаев использовать L a b e l удобнее, чем выводить текст с помощью метода
d r a w s t r i n g объекта G r a p h i c s , поскольку строку, созданную с помощью L a b e l , дис
петчер компоновки автоматически размещает в контейнере. Требуемый текст указы
вается при создании объекта L a b e l , после чего этот объект помещается в окно.
Label label = new Label("...");
add(label);
Часто текст, отображаемый посредством L a b e l , предназначается для описания
другого объекта и должен выравниваться в соответствии с ним. Диспетчер компонов
ки F l o w L a y o u t мало пригоден для обеспечения такого поведения, поэтому прихо
дится использовать другие диспетчеры. П р и работе с объектами L a b e l можно изме
нять ш р и ф т и тип выравнивания. Например, в следующием фрагменте кода L a b e l
используется в качестве заголовка панели.
P a n e l r e s u l t s P a n e l = new P a n e l ( ) ;
resultsPanel.setLayout(new BorderLayout());
L a b e l t i t l e = new L a b e l ( " R e s u l t s " , Label.CENTER);
t i t l e . s e t F o n t ( n e w F o n t ( " S a n s S e r i f " , Font.BOLD, 1 8 ) ) ;
r e s u l t s P a n e l . a d d ( t i t l e , BorderLayout.NORTH);
T e x t A r e a r e s u l t s A r e a = new T e x t A r e a ( ) ;
r e s u l t s P a n e l . a d d ( r e s u l t s A r e a , BorderLayout.CENTER);
Конструкторы
в классе L a b e l предусмотрены три конструктора.
public Label()
public Label(String labelString)
public Label(String labelString, int alignment)
Первый конструктор создает пустой объект L a b e l . Текст к такому объекту можно
добавить позже, используя для этого метод s e t T e x t . Второй конструктор создает
объект, содержащий указанную строку. Последний вариант конструктора задает так
же тип выравнивания. Параметр a l i g n m e n t может принимать значения L a b e l . LEFT
(по умолчанию), L a b e l . RIGHT и L a b e l .CENTER. Если объект L a b e l содержится в
окне, с которым связан диспетчер компоновки F l o w L a y o u t , либо включен в область
E a s t или West B o r d e r L a y o u t , то тип выравнивания не имеет практически никакого
1 3 . 2 1 . Класс Label 527
Листинг 13.38.Labels.Java
import Java.applet.Applet;
import java.awt.*;
r^LWHIiMMi'." ЖЭТР-Тй^
Applet
Label
Label 2
Label 3
Label 4 | Рис. 13.23. Объекты Label могут отображать текст
Applet started
различными шрифтами с различными типами выравнивания
Листинг 1 3 , 3 9 . R e v e r s e L a b e l s . J a v a
import java.awt.*;
public ReverseLabels () {
super("Reversible Labels");
setLayout(new FlowLayout());
setBackground(Color.lightGray);
setFont(new Font("Serif", Font.BOLD, 18))
ReversibleLabel labell =
13.21. Класс Label 529
Листинг 13.40.ReversibleLabel.Java
import java.awt.*;
import Java.awt.event.*;
/** Объект Label, который при помещении на него курсора
* мыши изменяет цвет фона и цвет переднего плана.
Ч
public class ReversibleLabel extends Label {
public ReversibleLabel(String text,
Color bgColor, Color fgColor) {
super(text);
MouseAdapter reverser = new MouseAdapter() {
public void mouseEntered(MouseEvent event) {
reverseColors();
}
addMouseListener(reverser);
setText(text);
setBackground(bgColor);
setForeground(fgColor);
}
Конструкторы
в классе S c r o l l b a r предусмотрены следующие конструкторы.
public ScroUbarO
Данный конструктор создает вертикальную полосу прокрутки. Размер ползунка
(перемещаемого элемента) по умолчанию составляет 10% от общей длины области
перемещения. Внутренние минимальное и максимальное значения (они будут
описаны ниже) устанавливаются равными нулю.
public Scrollbar(int orientation, int initialValue, int bubbleSize, int min, int max)
Данный конструктор используется для создания линейного регулятора. Он создает
горизонтальный или вертикальный регулятор либо полосу прокрутки; при этом
задаются размер ползунка и диапазон значений. Размер ползунка указывается от
носительно диапазона значений. Так, если разность между величинами max и min
равна 5, то размер ползунка будет равен 20% от размера области перемещения.
Заметьте, что ряд операционных систем (например, некоторые версии MacOS) не
поддерживает изменение размеров ползунка.
Конкретное значение соответствует расположению не центра ползунка, а его ле
вого (для горизонтального регулятора) либо верхнего (для вертикального регуля
тора) края. Для горизонтальной полосы прокрутки максимальное значение соот
ветствует не крайнему правому положению левой части ползунка, а крайнему пра
вому положению его правой части. Это приводит к тому, что реальный диапазон
значений оказывается меньше разности между максимальным и минимальным
значениями. Например, приведенное ниже выражение создает полосу прокрутки,
значения которой изменяются в диапазоне от О до 45; начальное значение равно
25, а размер ползунка — 5.
new S c r o l l b a r ( S c r o l l b a r . H O R I Z O N T A L , 25, 5, О, 50);
Внимание!
Листинг 1 3 . 4 1 . S c r o l l b a r s . J a v a
import Java.applet.Applet;
import java.awt.*;
1Ч!11ПИ1!,1-!1И^
J. dL±i
Методы Scrollbar
Разработчику, использующему класс S c r o l l b a r , доступны следующие методы.
public int g e t U n i t l n c r e m e n t O
public void s e t U n i t I n c r e m e n t ( i n t i n c r e m e n t )
Метод g e t U n i t I n c r e m e n t предназначен для определения того, насколько изме
нилось значение в результате щелчка на одной из стрелок, расположенных на
концах области перемещения. Если разработчик не предусмотрел специальных
действий в методе s e t U n i t l n c r e m e n t , возвращается величина, равная 1. Заметь
те, что в некоторых реализациях класса, например в JDK 1.1 в системе Solans, дан
ный метод игнорируется. Разрабатывая приложение, необходимо предусмотреть
13.22. Полосы прокрутки и линейные регуляторы 533
public int g e t M i n i m u m ( )
public v o i d s e t M i n i m u m ( i n t minValue)
Метод g e t M i n i m u m возвращает, a метод s e t M i n i m u m устанавливает минимальное
значение для объекта S c r o l l b a r .
public int g e t B l o c k I n c r e m e n t ( )
public void s e t B l o c k I n c r e m e n t ( i n t i n c r e m e n t )
Метод g e t B l o c k l n c r e m e n t возвращает, a метод s e t B l o c k l n c r e m e n t устанавли
вает изменение значения после щелчка мышью в области перемещения за преде
лами ползунка. Изменение значения по умолчанию зависит от платформы. В сис
теме Windows 98 оно равно 10, а в системе Solaris — размеру ползунка.
Листинг 1 3 . 4 2 . B e t t e r S c r o l l b a r . Java
import java.awt.*;
import Java.awt.event.*;
13.23. Контекстные меню 535
него объекты Menu I t em, а затем проверить флаг раскрывающегося меню компонен
та, вызвав метод i s P o p u p T r i g g e r в обработчике события мыши. П р и получении
флага надо вызвать объект show для отображения меню. Когда раскрывающееся ме
ню отображается на экране, для пунктов меню генерируются события A c t i o n E v e n t .
Конструкторы
в классе PopupMenu определены следующие конструкторы.
public PopupMenu()
public P o p u p M e n u ( S t r i n g title)
Первый из указанных конструкторов создает раскрывающееся меню без заголовка,
второй добавляет к создаваемому меню указанный заголовок, который, однако, не
отображается в системах Windows 9 5 / 9 8 / N T .
Листинг 13.43.СоlorPopupMenu.java
menu.add(colorName);
colorName.addActionListener(this);
menu.addSeparator() ;
}
add(menu) ;
e n a b l e E v e n t s (AWTEvent .MOUSE__EVENT__MASK) ;
Для обработки событий, связанных с выбором пункта меню, следует связать с каж
дым из объектов M e n u l t e m обработчик A c t i o n L i s t e n e r .
Menultem i t e m = new M e n u l t e m ( " [ L a b e l ] " ) ;
menu.add(item);
item.addActionListener(someListener);
При использовании обработчика A c t i o n L i s t e n e r необходимо реализовать ме
тод a c t i o n P e r f o r m e d , которому в качестве параметра передается объект
A c t i o n E v e n t . Метод g e t A c t i o n C o m m a n d класса A c t i o n E v e n t позволяет получить
текст, соответствующий конкретному объекту M e n u l t e m .
13.24. Резюме
AWT предоставляет восемь типов окон, которые разработчик может использовать
при создании пользовательского интерфейса: C a n v a s , P a n e l , A p p l e t , S c r o l l P a n e ,
Frame, D i a l o g , F i l e D i a l o g и Window. В данной главе описаны различия между этими
окнами и рассмотрены основные вопросы, связанные с их использованием. Разработ
чику программ на Java доступны следующие типы управляющих элементов: B u t t o n ,
Checkbox (с помощью этого элемента создаются флажки опций и переключатели оп
ций). C h o i c e , L i s t , T e x t F i e l d , T e x t A r e a , L a b e l , S c r o l l b a r (используется для соз
дания полос прокрутки и линейных регуляторов) и PopupMenu. Для того чтобы исполь-
540 Глава 13. Компоненты AWT
В ЭТОЙ главе...
Отображение сообщений.
Соглашения об именовании
Имена компонентов Swing начинаются с символа "J" и представляются в формате
J Ххх, где Ххх— обозначение компонента. Примерами имен Swing-компонентов могут
служить J F r a m e , J P a n e l , J A p p l e t , J D i a l o g и J B u t t o n . Каждому AWT-компоненту
соответствует Swing-аналог. Почти для всех компонентов Swing суперклассом являет
ся J C o m p o n e n t , что обеспечивает возможность настройки внешнего вида компонен
тов, создания обрамлений, определяемых разработчиком, и окон подсказки.
"Легковесные" компоненты
Большинство компонентов Swing являются "легковесными''. Это значит, что ото
бражение компонента в окне осуществляется с помощью Java-кода; платформенно-
зависимые средства не используются. Исключениями являются J F r a m e , J A p p l e t ,
JWindow и J D i a l o g . Эти средства являются ^'тяжеловесными". Поскольку графические
изображения, выводимые в буфер, должны отображаться на экране, данные
"тяжеловесные" компоненты представляют собой средства согласования с AWT-
компонентами.
Методика профессионалов
Двойная буферизация
По умолчанию J P a n e l поддерживает двойную буферизацию (подробно она будет
описана в главе 16). В Swing единственный внеэкранный буфер, размеры которого
достаточны для поддержки экрана, управляется с помощью R e p a i n t M a n a g e r . При
выполнении метода p a i n t происходит обращение к R e p a i n t M a n a g e r для получения
внеэкранного буфера. Рисование в буфере осуществляется с помощью метода p a i n t
Component, а затем содержимое буфера копируется на экран. Вывод в J P a n e l по
средством p a i n t C o m p o n e n t на самом деле представляет собой вывод во внеэкранный
буфер. При рисовании за пределами метода p a i n t используется вызов p a n e l .
g e t G r a p h i c s ( ) , при этом вывод осуществляется непосредственно на экран и двой
ная буферизация не выполняется.
К каждому компоненту, помещенному в контейнер с двойной буферизацией, дан
ный тип буферизации применяется автоматически. Так, поскольку панель содержи
мого, включаемая в J F r a m e и J A p p l e t , представляет собой контейнер с двойной бу
феризацией, при работе Java-приложений на базе Swing также используется двойная
буферизация.
546 Глава 1 4 . Основы Swing
Архитектура "модель-просмотр-контроллер"
Структура "легковесных" Swing-компонентов соответствует архитектуре "модель-
просмотр-контроллер" (MVC —model-view-controller), показанной на рис. 14.1. Модель
представляет собой структуру данных, которая предоставляет доступ к информации с
помощью специальных методов. Структура может быть проста и включать несколько
переменных, которые задают состояние объекта, а может быть очень сложной, как,
например, массив, определяющий набор полей в таблице. Просмотр используется для
визуального представления данных модели. Контроллер представляет собой обработ
чик событий.
С каждым "легковесным" компонентом Swing связан представитель пользователь
ского интерфейса (UI), который является дочерним объектом ComponentUI. UI-
представитель управляет внешним видом компонента и особенностями обработки
событий. При создании экземпляра компонента UIManager возвращает объект, оп
ределяющий пользовательский интерфейс (LabelUI, TableUI, TreeUI и т.д.), осно
ванный на внешнем виде и поведении программы (Windows, Motif, Java). UI-
представитель сообщает минимальный, максимальный и нормальный размеры ком
понента, отвечает за вывод компонента и поддержку связанных с ним событий.
Преимущество архитектуры MVC состоит в том, что одна и та же модель может
быть связана с различными компонентами, обеспечивая таким образом различные
стили вывода данных. Представьте себе данные, отображаемые в виде таблицы и в
виде гистограммы. Оба типа отображения соответствуют одной модели. Если пользо
ватель включит в модель новые данные, будет сгенерировано событие, связанное с
моделью. В результате оба представления подвергнутся обновлению. Различные
представления сложных данных часто применяются при работе со средствами Swing.
Так, например, в главе 15 будет приведен пример отображения данных с помощью
объектов JTree и JTable.
оповещение
об обновлении
обновление
обновление визуального
содержимого представления
[ Событие J
import javax.swing.*;
import java.awt.*; // Для классов Color и Container.
/** Некоторые утилиты, упрощающие использование окон в Swing. */
public class WindowUtilities {
/** Системе сообщается о том, что стиль должен соответствовать
типичному интерфейсу конкретной платформы. По умолчанию
устанавливается стиль Metal (Java).
*/
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(
UIManager. getSystemLookAndFeelClassName ()) ;
} catch(Exception e) {
System.out.println("Error setting native LAF: " + e ) ;
}
}
Листинг 14.2.ExitListener.java
import java.awt.*;
import Java.awt.event.*;
/** Обработчик, который связывается с компонентом верхнего
* уровня JFrame приложения, так, что при закрытии окна
* приложение завершается.
V
public class ExitListener extends WindowAdapter {
public void windowClosing(WindowEvent event) {
System.exit(0);
}
ill kWf^f^
Table D$mo | Source Code |
im у>0н^¥ш
m оm
Table l>ew<?s
• Selectkw wo<ie
J column sefecfeon
Мий||^егерзе$ J' /1>
IS? Roweelec^cm
i ? У М Уwe Autore^is&rmjde
Rownelgbt
ir^r-teiupdesi$;: .
|Tt)^BHie«8rpthers
iart« фш ^тш eerjes)
ыт Who i^swTtHt^ imuth
|8lade Шпт* ф|гесЮг^ С^й>
[•теи<1уУаб1§г»«
Д0«в'еУГе ^ '^
5 Р ( * : л*-;-:Г~'
mm щ.-=^-\ 1И
Ti№leOemoMir^.^1
! S^lfeCtmu mutie
к. Reorctefbio alowed
v H o r k , Lines
!«i Row «Section
'< Veit.Unes rAiitw»$Jift?niMid8'"
c:3rrdlj^)br
First Name ; Last Name ! Favorite C(Hor Favorite Movie Favortte Number i FgvorlteFood
Mii-e Albers sBrazil
М е т о д и к а профессионалов
В листинге 14.3 показан простой пример Swing-аплета. Выглядит этот аплет так же,
как и AWT-аплет, в процессе работы которого не выполняются никакие действия, кроме
включения в окно трех кнопок, В Swing-версии для достижения аналогичного результа
та диспетчер компоновки, используемый по умолчанию, заменен на FlowLayout. На
рис. 14.5 показаны результаты выполнения аплета в среде броузера Netscape 6.
import java.awt.'^;
import javax.swing.*;
/** Небольшой пример, демонстрирующий различия в использовании
* JApplet и Applet: в окно включается панель содержимого,
* по умолчанию установлен стиль интерфейса Java (Metal),
* а размещением компонентов управляет диспетчер компоновки
* BorderLayout (вместо FlowLayout).
V
public class JAppletExample extends JApplet {
public void initO {
WindowUtilities.setNativeLookAndFeel();
Container content = getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
content.add(new JButton("Button 1"))
content.add(new JButton("Button 2")),
content.add(new JButton("Button 3")),
шюшшшшт
File Ed» ^ i e w Search Qp Book'narks lasks jHelp
Методика профессионалов
Дочерние окна автоматически закрываются при активизации соот
ветствующей кнопки, однако с главным окном JFrame следует свя
зать обработчик WindowListener. В процессе обработки события
необходимо предусмотреть вызов System, exit.
В листинге 14.4 показан код простого приложения. Оно выглядит на экране так
же, как и AWT-приложение на основе объекта Frame, в котором с окном связывается
диспетчер компоновки F l o w L a y o u t , а в окно включаются три кнопки. Результаты
выполнения приложения показаны на рис. 14.6. Коды W i n d o w U t i l i t i e s . J a v a и
E x i t L i s t e n e r . J a v a были рассмотрены в начале данной главы. Их можно скопиро
вать, обратившись по адресу h t t p : / /www. c o r e w e b p r o g r a m m i n g . com/.
Листинг 1 4 . 4 . JFrameExample. J a v a
import java.awt.*;
import javax.swing.*;
/** Небольшой пример, демонстрирующий различия в использовании
* JFrame и Frame: в окно включается панель содержимого,
* по умолчанию вместо стиля, типичного для используемой
* платформы, установлен стиль интерфейса Java (Metal).
V
public class JFrameExample {
public static void main(String[] args) {
WindowUtilities . setNativeLoolcAndFeel () ;
JFrame f = new JFrame("This is a test");
f.setSize(400, 150);
Container content = f.getContentPane();
14.4. Компонент JLabel 555
content.setBackground(Color.white);
content.setLayout(new FlowLayout()) ;
content.add(new JButton("Button 1")),
content.add(new JButton("Button 2")),
content.add(new JButton("Button 3")),
f.addWindowListener(new ExitListener()
f.setVisible(true);
I LP-4^?!yj--'i
• Для включения в текст разрыва строки надо использовать дескриптор <Р> вме
сто <BR>. В отличие от "реального" HTML, дескриптор <BR> игнорируется, а
<Р> действует как <BR>.
• О поддержке прочих НТМТ-конструкций нельзя сказать ничего определенно
го. Перед тем как использовать HTML-фрагмент в программе, обязательно
проверьте, как он отображается. Если вы позволите пользователю вводить
HTML-код в процессе выполнения программы, это может привести к возник
новению проблем.
Конструкторы JLabel
в классе J L a b e l предусмотрено семь конструкторов. Ч е т ы р е из них, которые ис
пользуются наиболее часто, описаны ниже.
14.4. Компонент JLabel 557
public JLabelO
public JLabel(String label)
public JLabel(Icon image)
public JLabel(String label, I c o n image, int hAlignment)
Указанные конструкторы позволяют создать пустой объект J L a b e l , объект
J L a b e l , отображающий фрагмент текста, и объект J L a b e l с изображением. По
следний из приведенных конструкторов отображает как пиктограмму, так и текст.
Параметр h A l i g n m e n t позволяет задавать горизонтальное выравнивание пары
"текст-пиктограмма" относительно самого объекта J L a b e l . Допустимыми значе
ниями данного параметра являются LEFT, CENTER, RIGHT, LEADING и TRAILING.
Методы JLabel
Н и ж е представлены наиболее часто используемые методы класса J L a b e l . Каждо
му из методов, устанавливающих значение свойства, соответствует метод, позволяю
щий определить установленное значение (get-метод).
import java.awt.*;
import javax.swing.*;
/** Небольшой пример, демонстрирующий использование JLabel,
* в частности поддержку HTML (только Swing 1.1,1, Java 1.2.2
* и более поздние версии).
Ч
public class JLabels extends JFrame {
public static void main(String[] args) {
new JLabels();
public JLabels0 {
superC'Using HTML in JLabels");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
Font font = new Font("Serif", Font.PLAIN, 30);
content.setFont(font);
String- labelText =
"<htmlXFONT COLOR=WHITE>WHITE</FONT> and " +
"<FONT COLOR=GRAY>GRAY</FONT> Text</html>";
JLabel coloredLabel =
new JLabel(labelText, JLabel.CENTER);
coloredLabel.setBorder
(BorderFactory.createTitledBorder("Mixed Colors"));
content.add(coloredLabel, BorderLayout.NORTH);
labelText =
"<htmlXB>Bold</B> and <I>Italic</l> Text</html>";
JLabel boldLabel =
new JLabel(labelText, JLabel.CENTER);
boldLabel.setBorder
(BorderFactory.createTitledBorder("Mixed Fonts"));
content.add(boldLabel, BorderLayout.CENTER);
labelText =
"<html>The Applied Physics Laboratory is a division " +
"of the Johns Hopkins University." +
"<P>" +
"Major JHU divisions include:" +
"<UL>" +
" <LI>The Applied Physics Laboratory" +
" <LI>The Krieger School of Arts and Sciences" +
" <LI>The Whiting School of Engineering" +
" <LI>The School of Medicine" +
14.5. Компонент JButton 559
.rJPJXl
Image I con, с помощью которого можно легко описывать файлы изображений (JPEG,
GIF, а также анимационный GIF). Проще всего связать изображение с JButton, пере
давая объект Imagelcon конструктору вместо текста либо вместе с текстом. С J B u t t o n
может быть связано семь различных изображений.
1. Основное изображение (если изображение не передано конструктору, его
можно задать с помощью метода s e t Icon).
2. Изображение, используемое при нажатии кнопки ( s e t P r e s s e d l c o n ) .
3. Изображение, которое выводится при помещении курсора мыши на кнопку
( s e t R o l l o v e r l c o n ; заметьте, что сначала надо вызвать метод
setRolloverEnabled(true)).
4. Изображение для запрещенной кнопки ( s e t D i s a b l e d l c o n ) .
5. Изображение, которое используется тогда, когда кнопка выбрана и разрешена
(setSelectedlcon).
6. Изображение, которое используется тогда, когда кнопка выбрана и запрещена
(setDisabledSelectedlcon).
7. Изображение, используемое при помещении курсора мыши на выбранную
кнопку ( s e t R o l l o v e r S e l e c t e d l c o n ) .
Изображения для выбранной кнопки ( s e t S e l e c t e d l c o n , s e t R o l l o v e r S e l e c
t e d l c o n и s e t D i s a b l e d S e l e c t e d l c o n ) не поддерживаются B J D K 1.2; их поддержка
реализована только в JDK 1.3. Выбрать кнопку можно из программы, вызвав метод
s e t S e l e c t e d ( t r u e ) . Выбор кнопки не приводит к генерации события
ActionEvent. Если вы не создаете кнопку с поддержкой состояния, вы можете ис
пользовать стандартный объект JToggleButton (см. документацию по API, описание
j a v a x . swing . JToggleButton), который допускает выбор как из программы, так и в
результате действий пользователя.
При создании интерфейса вы можете измеиигь выравнивание текста, пиктограм
мы либо пары "текст-пиктограмма", используя для этого методы s e t H o r i z o n t a l -
Alignment и s e t V e r t i c a l A l i g n m e n t (выравнивание возможно только в том случае,
если размеры компонента превышают его нормальные размеры). Вы также можете
изменить позицию текста относительно пиктограммы с помощью методов
s e t H o r i z o n t a l T e x t P o s i t i o n и s e t V e r t i c a l T e x t P o s i t i o n . Интервал между тек
стом и пиктограммой задается вызовом s e t l c o n T e x t G a p .
Компонент J B u t t o n позволяет определять "горячие клавиши" для активизации
кнопок. Это осуществляется с помощью метода setMnemonic. Если "горячая клави
ша" задана, один из символов в надписи на кнопке отображается с подчеркиванием, а
кнопка активизируется посредством комбинации клавиш <Ак+символ>.
Конструкторы JButton
в классе JButton предусмотрено пять конструкторов:
public JButtonO
public JButton(String label)
public J B u t t o n ( I c o n image)
public JButton(String label, I c o n image)
public JButton(Action action)
Первые четыре конструктора создают соответственно пустой компонент J B u t t o n ,
компонент J B u t t o n с надписью, компонент J B u t t o n с пиктограммой и компонент
J B u t t o n с надписью и пиктограммой. Пятый конструктор реализован B J D K 1.3. Ему
передается объект A c t i o n , предназначенный для разделения информации о со
стоянии с другими компонентами.
Листинг 14.6.JButtons.Java
import java.awt.*;
import javax.swing.*;
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
JButton buttonl = new JButtonC'Java") /
content.add(buttonl) ;
Imagelcon cup = new Imagelcon("images/cup.gif");
JButton button2 = new JButton(cup);
content.add(button2);
JButton buttons = new JButton("Java", cup);
content.add(button3);
JButton button4 = new JButton("Java", cup);
button4.setHorizontalTextPosition(SwingConstants.LEFT);
content.add(button4);
packO ;
setVisible(true) ;
Конструкторы JPanel
в классе JPanel определены четыре перечисленных ниже конструктора. При работе с
JPanel вы можете задавать диспетчер компоновки не только с помощью метода
s e t La у o u t . Сделать это позволяют также некоторые из конструкторов класса. Все методы
J P a n e l унаследованы от класса JComponent, поэтому в данном разделе мы не будем их
рассматривать. (За подробной информацией обращайтесь к документации по API.)
public JPanel()
public JPanel(LayoutManager manager)
public J P a n e l ( b o o l e a n i s D o u b l e B u f f e r e d )
public JPanel(LayoutManager manager, b o o l e a n isDoubleBuff ered)
Первый конструктор создает объект J P a n e l , связывает с ним диспетчер компо
новки F l o w L a y o u t и разрешает двойную буферизацию. Остальные три конструк
тора предназначены для явного определения диспетчера компоновки и управле
ния двойной буферизацией.
B e v e l B o r d e r , M a t t e B o r d e r и C o m p o u n d B o r d e r . Из 23 методов класса B o r d e r -
F a c t o r y наиболее часто используются методы, описанные ниже. Каждый из этих ме
тодов определен как p u b l i e s t a t i c .
Border c r e a t e L i n e B o r d e r ( C o l o r color)
B o r d e r createLineBorder(Color color, int thickness)
Указанные два метода создают объект L i n e B o r d e r с поддержкой цвета. По умол
чанию толщина рамки составляет один пиксель. Второй конструктор позволяет
непосредственно задавать толщину рамки в пикселях. Класс L i n e B o r d e r также
предоставляет два статических метода: c r e a t e B l a c k L i n e B o r d e r и c r e a t e G r a y -
L i n e B o r d e r . Эти методы предназначены для построения рамок, отображаемых
черной или серой линией толщиной в один пиксель.
T i t l e d B o r d e r createTitledBorder(String title)
T i t l e d B o r d e r c r e a t e T i t l e d B o r d e r ( B o r d e r b o r d e r . String title)
Данные методы создают объект T i t l e d B o r d e r с заголовком, расположенным в
позиции по умолчанию (ТОР) в левой части верхней линии рамки. По умолчанию
рамка имеет вид "гравюры". Чтобы изменить внешний вид обрамления, надо явно
указать тип рамки (это позволяет сделать второй метод). Класс T i t l e d B o r d e r
предоставляет методы s e t T i t l e P o s i t i o n и s e t T i t l e J u s t i f i c a t i o n . Позиция
заголовка задается относительно верхней части рамки с помощью следующих кон
стант: ABOVE_TOP, ТОР, BELOW_TOP, ABOVE_BOTTOM, BOTTOM и BELOW_BOTTOM.
В методе s e t T i t l e J u s t i f i c a t i o n выравнивание заголовка задается посредст
вом констант LEFT, CENTER и RIGHT. Вы также можете указать для заголовка цвет
и ш р и ф т с помощью s e t T i t l e C o l o r , s e t T i t l e F o n t и некоторых методов
BorderFactory.
Border createEtchedBorder()
Border c r e a t e E t c h e d B o r d e r ( C o l o r highlight, Color shadow)
Первый из указанных методов создает LOWERED E t c h e d B o r d e r — рамку, которая
имеет вид бороздки толщиной 2 пикселя. Бороздка окрашена в два цвета для соз
дания эффекта трехмерного элемента. По умолчанию подсветка обозначается
цветом, несколько более светлым по сравнению с цветом фона, а затенение — бо
лее темным цветом, чем фон. Второй метод позволяет явно указывать цвет для
обозначения подсветки и затенения. Чтобы вместо бороздки отображался выступ,
надо непосредственно создать объект E t c h e d B o r d e r , передавая в качестве пара
метра значение RAISED.
В дополнение к перечисленным методам B o r d e r F a c t o r y предоставляет другие
статические методы, предназначенные для создания объектов E m p t y B o r d e r , Ы г х е -
Border и E t c h e d B o r d e r . Кроме того, B o r d e r F a c t o r y позволяет создавать различ
ные типы объекта B e v e l B o r d e r ( c r e a t e B e v e l B o r d e r , c r e a t e R a i s e d B e v e l B o r d e r
566 Глава 14. Основы Swing
Листинг 1 4 . 7 . J P a n e l s . Java
import java.awt.*;
import javax.swing.*;
/** Простой пример, иллюстрирующий использование компонента
* JPanel, в частности возможность связывания рамок.
V
public class JPanels extends JFrame {
public static void main(String[] args) {
new JPanels();
}
public JPanels0 {
superC'Using JPanels with Borders");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.lightGray);
JPanel controlArea = new JPanel(new GridLayout(3, 1));
String[] colors = { "Red", "Green", "Blue",
"Black", "White", "Gray" };
controlArea.add(new SixChoicePanel("Color", colors));
String[] thicknesses = { "1", "2", "3", "4", "5", "6" };
controlArea.add(new SixChoicePanel("Line Thickness",
thicknesses));
String[] fontSizes = { "10", "12", "14", "18", "24", "36" };
controlArea.add(new SixChoicePanel("Font Size",
fontSizes));
content.add(controlArea, BorderLayout.EAST);
JPanel drawingArea = new JPanel();
// Высота компонента не имеет значения, поскольку он
// помещается в область WEST.
drawingArea.setPreferredSize(new Dimension(400, 0));
drawingArea.setBorder
(BorderFactory.createLineBorder (Color.blue, 2));
drawingArea.setBackground(Color.white);
content.add(drawingArea, BorderLayout.WEST);
pack () ;
setVisible(true) ;
14.7. Компонент JSlider 567
Листинг 14.8.SixChoicePanel.Java
import java.awt.*;
import javax.swing.*;
/** Контейнер Jpanel, содержащий четыре компонента JRadioButton. Ч
||^IHI,lipW!MJyiiffllfpi|^^
Color •j
с pieifli Г Black
(^ Green Г White
^ Blue ^ Gray
Line Thickness
r 1 Г 4
r 2 r 5
r 3 ^ 6
Font Size
^ 1 0 ^18
r 12 r 24
\^\^ ^ 36 ;
Конструкторы JSlider
в классе JSlider определено пять конструкторов:
public JSliderO
public JSlider(int orientation)
public JSlider(int m i n , int max)
public JSlider(int m i n , int max, int initialValue)
public JSlider(int orientation, int m i n , int max, int initialValue)
Первый из указанных конструкторов создает объект J S l i d e r с максимальным и
минимальным значениями, равными соответственно О и 100, и начальным значе
нием, равным 50. Второй конструктор создает объект JSlider с теми же значения
ми. От предыдущего конструктора он отличается тем, что при создании линейно
го регулятора можно задавать его ориентацию (HORIZONTAL или VERTICAL). По
следние т р и конструктора позволяют задавать произвольные минимальное,
максимальное и начальное значения.
14.7. Компонент JSIider 569
Листинг 14.9. J S l i d e r s . J a v a
import j a v a . a w t . * ;
import j a v a x . s w i n g . * ;
/** Простой пример, иллюстрирующий возможности J S l i d e r s ,
* в частности разметку шкалы.
p u b l i c c l a s s J S l i d e r s extends JFrame {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new J S l i d e r s ( ) ;
public J S l i d e r s 0 {
super("Using J S l i d e r " ) ;
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.white);
packO ;
setVisible(true) ;
JSB«9rv^thdytTtekMart<$
gSiderwt&itlfcktilafks
JSIidJif ШХх Ней Ш ? k s
I»11) > I )}» f77TV77»*7)
JSHder with ШК Itafk? $, U N t s
Конструкторы
Наиболее часто используются следующие конструкторы класса: JColorChooser.
public JColorChooser()
public JColorChooser(Color initialColor)
Первый из указанных конструкторов создает JColorChooser с первоначально
выбранным значением C o l o r . w h i t e . Второй конструктор позволяет явно зада
вать выбираемый цвет.
быть модальным или немодальным. При создании окна надо задать два объекта
A c t i o n L i s t e n e r , предназначенные для обработки событий, связанных с активи
зацией пользователем кнопок ОК и Cancel. После создания диалогового окна надо
задать цвет посредством метода s e t C o l o r и отобразить окно, вызвав метод
s e t V i s i b l e . Например:
JColorChooser chooser = new JColorChooser();
JDialog d i a l o g = new J C o l o r C h o o s e r . c r e a t e D i a l o g ( . . . ) ;
chooser.setColor(someColor);
dialog.setVisible(true);
Обработчик o k L i s t e n e r может определить выбранный цвет посредством метода
getColor.
class okListener implements ActionListener {
public void actionPerformed(ActionEvent e)) {
Color color = chooser.getColorо;
repaint();
}
}
Листинг 1 4 . 1 0 . J C o l o r C h o o s e r T e s t . J a v a
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
import j a v a x . s w i n g . * ;
/** Простой пример, иллюстрирующий использование JColorChooser. */
public c l a s s JColorChooserTest extends JFrame
implements A c t i o n L i s t e n e r {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new J C o l o r C h o o s e r T e s t ( ) ;
574 Глава 14. Основы Swing
public JColorChooserTest () {
super("Using JColorChooser");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
JButton colorButton
= new JButton("Choose Background Color");
colorButton.addActionListener(this);
content.add(colorButton);
setSize(300, 100);
setVisible(true);
}
^ C h o o s e Background Color
UJJJJJJJJ-
Recent:
шШ^шш. dddi
"-"11;
riiBlliH
D Sample Text Sample Text
D
OK I Cancel Reset
Рис. 14.11. Выбор цвета с помощью панели
образцов компонента JColorChooser
14.9. Внутренние окна 575
Конструктор JInternalFrame
в классе J I n t e r n a l F r a m e определены шесть конструкторов, позволяющих опре
делять поведение окна. Два самых простых конструктора, а также конструктор, по
зволяющий задавать все характеристики объекта, описаны ниже.
public JInternalFrameO
public JInternalFrame(String title)
public JInternalFrame(String title,
boolean resizable,
boolean closeable,
boolean maximizable,
boolean iconifiable)
По умолчанию внутреннее окно не допускает изменения размеров, закрытия, мак
симизации и минимизации. Окно, создаваемое с помощью первых дв)'х конструк
торов, можно лишь перемещать в пределах включающей панели. Последний кон
структор позволяет явно контролировать возможности окна.
М е т о д и к а профессионалов
• internalFrameActivated
• internalFrameClosed
• internalFrameClosing
• internalFrameDeactivated
• internalFrameDeiconified
• internalFramelconified
• internalFrameOpened
Метод a d d l n t e r n a l F r a m e L i s t e n e r связывает обработчик с внутренним окном,
а метод r e m o v e I n t e r n a l F r a m e L i s t e n e r разрывает эту связь.
Класс JDesktopPane содержит два метода, позволяющих определять объекты
J I n t e r n a l F r a m e , содержащиеся во включающей панели. Метод g e t A l l F r a m e s воз
вращает массив, содержащий все видимые и минимизированные внутренние окна.
Метод g e t A l l F r a m e s I n L a y e r ( l a y e r ) предоставляет сведения о всех внутренних
окнах в заданном слое JDesktopPane.
В примере, приведенном в листинге 14.11, пять пустых внутренних окон создают
ся в панели, которая, в свою очередь, содержится в составе JFrame. Заметьте, что в
JDK 1.2 для J I n t e r n a l F r a m e значение характеристики, определяющей видимость,
устанавливается равным t r u e . Однако в JDK 1.3 значение этой характеристики по
умолчанию задается равным f a l s e , поэтому для отображения окна необходимо вы
звать метод s e t V i s i b l e ( t r u e ) . На рис. 14.12,а все окна открыты, а на рис. 14.12,6
два внутренних окна минимизированы.
На з а м е т к у
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
/** Простой пример, иллюстрирующий использование внутренних окон. */
public class JInternalFrames extends JFrame {
public static void main(String[] args) {
new JInternalFrames();
public JInternalFrames() {
super("Multiple Document Interface");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.white);
578 Глава 14. Основы Swing
^ M u l t i p l e Document Interfac
^шг^^^жйлмм
'§еашаг^^.£|Г^!^Ш!^д1тг<1
(а) (б)
Рис. 14.12. Swing-компонент JFrames содержит внутренние окна: а- все внутренние окна
открыты; б — два внутренних окна минимизированы
рок!
(а) (6)1
^ showMessageOiidoe М^^Ьсм!
W^J^N!NO„MeSSAGC л 6RR0P_WESSADEIC0R
ок1 ^ oiol
(в) (г)
Рис. 14.13. Диалоговые окна (интерфейс в стиле Windows) с
различными пиктограммами: а — информационное сообщение;
б — вопрос; в — предупреждение; г — сообщение об ошибке
жк'штч
DEFAULT_OPTЮN
и OK_CANCH-_OPTION
(а) (б)
ГДГ'1П?1!П1? шшшшшвсш
Д YESJtOJ)PJЮЫ
Д YES_NO_CANCEl._OPTION
I Yes : No Yes Cancel I
No
(в) (г)
Рис. 14.14. Диалоговые окна (интерфейс в стиле Java), созданные
с помощью метода showConfirmDialog: а— окно по умолчанию;
б — 0К/Сапсе1; в — Yes/No; г — Yes/No/Cancel
14.10. Компонент JOptionPane 581
[ OK I ! CanceJ
Рис. 14.16. Диалоговое окно (интерфейс в стиле
Java) с раскрывающимся списком
НЕ ТГ?Ш!1?1
Message to appear above ь ш о п options
•V
|8utton1 ii Bu11on2 1 Buttons | Рис. 14.17. Диалоговое окно (интерфейс в стиле
Windows), содержащее произвольный набор кнопок
1 4 . 1 1 . К о м п о н е н т JToolBar 583
Листинг 14.12.ToolBarButton.Java
import java.awt.*;
import javax.swing.*;
Конструкторы JToolBar
в классе JToolBar определены два конструктора:
public JToolBarO
public JToolBar(int orientation)
Первый конструктор создает панель инструментов JToolBar, ориентированную
по умолчанию горизонтально. Второй конструктор позволяет явно задать ориен
тацию компонента: HORIZONTAL или VERTICAL.
1 4 . 1 1 . К о м п о н е н т JTooiBar 585
Методы JTooiBar
Класс JTooiBar содержит 23 метода. Ниже описаны лишь наиболее часто исполь
зуемые из них.
}
}
Вы также можете связать с J B u t t o n обработчик A c t i o n L i s t e n e r и включить
кнопку в панель инструментов, вызывая метод add (someButton). Поскольку па
нель инструментов является контейнером, ей доступны методы класса C o n t a i n e r .
В JDK 1.2 при добавлении к панели инструментов объекта A c t i o n на кнопке ото
бражаются и пиктограмма, и текст. В JDK 1.3 в этом случае выводится только пик
тограмма. Вместо вывода текста панель инструментов поддерживает подсказки.
На з а м е т к у ^^^^^
Листинг 14.13.ToolBarExample.Java
import j a v a . a w t . * ;
import j a v a x . s w i n g . * ;
import J a v a . a w t . e v e n t . * ;
/** Небольшой пример, демонстрирующий использование JToolBar. */
p u b l i c c l a s s JToolBarExample extends JFrame
implements I t e m L i s t e n e r {
p r i v a t e BrowserToolBar toolbars-
p r i v a t e JCheckBox labelBox;
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new JToolBarExample();
14.11. Компонент JToolBar 587
public JToolBarExample() {
super("JToolBar Example");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setBackground(Color.white);
packO ;
setVisible(true);
}
public void itemStateChanged(ItemEvent event) {
toolbar.setTextLabels(labelBox.isSelected());
packO ;
}
}
Листинг 14.14,BrowserToolBar.Java
import java.awt.'^;
import javax.swing.*;
иптиш?
оИ1#И!&|а1Э1
Ш
г ghSjJyfTiwtLab^^
ШЛХоШаё Exampfe
# а т\
WlfH'fflit'' '^'^-'М1*'^^^^1аУх1 8вск1Forwaml
ней?!
КИ1сй>И|@Ш1ш|
someWindow.add(new JScrollPane(htmlPane);
} catch(lOException ioe) {
System.err.println("Error displaying " + url);
}
Конструкторы JEditorPane
в классе J E d i t o r P a n e определены следующие четыре конструктора:
public JEditorPaneO
public JEditorPane(String url)
public J E d i t o r P a n e ( U R L url)
public JEditorPane(String m i m e T y p e , String d o c u m e n t )
По умолчанию J E d i t o r P a n e интерпретирует содержимое документа как обыч
ный текст. П р и указании URL документа с помощью объекта URL или String авто-
14.12. Компонент JEditorPane 591
Методы JEditorPane
Ниже описаны часто используемые методы Knacca>JEditorPane. Каждому свойст
ву Ххх соответствуют методы getXxx и setXxx.
Листинг 14,15.Browser.Java
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
/•• Чрезвычайно простой "Web-броузер", созданный с
* использованием Swing. URL, заданный в командной строке,
* определяет документ, отображаемый при запуске броузера,
* и задает расположение исходной страницы.
V
public class Browser extends JFrame implements HyperlinkListener,
ActionListener {
public static void main(String[] args) {
if (args.length == 0)
new Browser("http://www.corewebprogramming.com/");
else
new Browser(args [0]);
}
private JIconButton homeButton;
private JTextField urlField;
private JEditorPane htmlPane;
private String initialURL;
WindowUtilities.setNativeLookAndFeel();
JPanel topPanel = new JPanelO;
topPanel.setBackground(Color.lightGray) ;
homeButton = new JIconButton("home.gif");
homeButton.addActionListener(this);
JLabel urlLabel = new JLabel("URL:");
urlField = new JTextField(30);
urlField.setText(initialURL) ;
urlField.addActionListener(this);
topPanel.add(homeButton);
topPanel.add(urlLabel);
topPanel.add(urlField);
getContentPane0.add(topPanel, BorderLayout.NORTH);
try {
htmlPane = new JEditorPane(initialURL);
htmlPane.setEditable(false);
htmlPane.addHyperlinkListener(this);
JScrollPane scrollPane » new JScrollPane(htmlPane);
getContentPane().add(scrollPane, BorderLayout.CENTER)
} catch(lOException ioe) {
warnUser("Can't build HTML pane for " + initialURL
+ ": " + ioe);
}
Dimension screenSize = getToolkit().getScreenSize();
int width = screenSize.width * 8 / 10;
int height = screenSize.height * 8 / 10;
setBounds(width/8, height/8, width, height);
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
String url;
if (event.getSource () == urlField) {
url = urlField.getText0;
} else { // Clicked "home" button instead of entering URL.
url = initialURL;
}
try {
htmlPane.setPage(new URL(url));
urlField.setText(url);
} catch(lOException ioe) {
warnUser("Can't follow link to " + url + ": " + ioe);
}
}
public void hyperlinkUpdate(HyperlinkEvent event) {
if (event.getEventType 0 ==
HyperlinkEvent.EventType.ACTIVATED) {
try {
htmlPane.setPage(event.getURL());
urlField.setText(event.getURL().toExternalForm());
} catch(lOException ioe) {
warnUser("Can't follow link to "
+ event.getUIUiO.toExternalForm0 + ": " + ioe)
594 Глава 14. Основы Swing
Листинг 14.16.JIconButton.Java
import javax.swing.^;
СШмЭН APL scientists work at the frontiers of many research fields to support
technical program needs. Research Is performed in all of APL's technical
departments. However, the Milton S. Eisenhower Research and Technology
Development Center (RTDC) Is dedicated to basic and applied research in
support of APL's mission. In addition to nurturing scientifically based,
in-house expertise In newly developing areas, the RTDC provides a window
into science for APL. The RTDC contains numerous highly specialized
laboratories and conducts research programs in a number of broad areas.
Jj
Компонент JCheckBox
Swing-компонент JCheckBox (обратите внимание на прописную букву В в имени
JCheckBox) выполняет те же функции, что и AWT-компонент Checkbox. Для обработ
ки событий используются объекты A c t i o n L i s t e n e r и I t e m L i s t e n e r . При работе с
A c t i o n L i s t e n e r приходится вызывать метод i s S e l e c t e d для того, чтобы отличить
установку флажка от сброса. При использовании I t e m L i s t e n e r объект I t e m E v e n t со
держит информацию о компоненте; чтобы определить состояние JCheckBox, надо вы
звать метод g e t S t a t e C h a n g e и сравнить возвращаемое значение с константами
I t e m E v e n t . SELECTED и I t e m E v e n t . DESELECTED. Если вы не можете гарантировать,
что цвет фона JCheckBox совпадает с цветом фона контейнера, вы должны вызвать ме
тод s e t C o n t e n t A r e a F i l l e d ( f a l s e ) . Вместо квадратного поля, отображаемого по
умолчанию, вы можете задать произвольную пиктограмму (метод s e t l c o n ) . Сделав это,
не забудьте указать также пиктограмму, соответствующую установленному флажку оп
ции ( s e t S e l e c t e d l c o n ) . В листинге 14.17 показан процесс создания флажков опций и
использования обработчиков I t e m L i s t e n e r и A c t i o n L i s t e n e r . В процессе обработ
ки событий определяется состояние компонента. Результат выполнения программы
J C h e c k B o x T e s t . J a v a показан на рис. 14.21.
596 Глава 14. Основы Swing
import javax.swing.*;
import java.awt.event.*;
public JCheckBoxTest0 {
checkBoxl = new JCheckBox("Java Servlets");
checkBox2 = new JCheckBox("JavaServer Pages");
checkBoxl.setContentAreaFilled(false);
checkBox2.setContentAreaFilled(false);
checkBoxl.addltemListener(this);
checkBox2.addActionListener(this);
add(checkBoxl);
add(checkBox2) ;
}
if (event.getStateChange0 == ItemEvent.SELECTED) {
System, out .println (checkbox. getText () -f- " selected.");
} else {
System.out.println(checkbox.getText() + " deselected.");
}
}
Компонент JRadioButton
Swing-компонент JRadioButton действует аналогично AWT-компоненту Checkbox,
включенному в состав CheckboxGroup. Для создания переключателей опций создается
несколько объектов JRadioButtons, которые объединяются с помощью ButtonGroup.
Все переключатели, помещенные в ButtonGroup, образуют одну логическую группу.
Как и при работе с JCheckBox, для поддержки событий можно использовать
A c t i o n L i s t e n e r и I t e m L i s t e n e r . Переключателю, выбранному в данный момент,
передаются события ActionEvent и ItemEvent, а переключателю, для которого вы
бор был отменен, передается только событие ItemEvent. Если вы не можете гаранти
ровать, что цвет фона JRadioButton совпадает с цветом фона контейнера, вы должны
вызвать метод s e t C o n t e n t A r e a F i l l e d ( f a l s e ) . Как и для JCheckBox, вы можете за
дать пиктограмму, изменяющую внешний вид переключателя, принятый по умолчанию
(метод s e t Icon). В этом случае необходимо также задать пиктограмму, соответствую
щую выбранной кнопке переключателя ( s e t S e l e c t e d l c o n ) . Три кнопки переключате
лей опций, созданные в программе, приведенной в листинге 14.18, показаны на
рис. 14.22.
import j a v a x . s w i n g . J R a d i o B u t t o n ;
import javax.swing.ButtonGroup;
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
import j a v a x . s w i n g . * ;
p u b l i c c l a s s JRadioButtonTest extends JPanel
implements I t e m L i s t e n e r
public JRadioButtonTest0 {
S t r i n g [ ] l a b e l s = {"Java Swing","Java S e r v l e t s " ,
"JavaServer Pages"};
JRadioButton[] b u t t o n s = new J R a d i o B u t t o n [ 3 ] ;
ButtonGroup group = new ButtonGroup();
f o r ( i n t i=0; i < b u t t o n s . l e n g t h ; i++) {
b u t t o n s [ i ] = new J R a d i o B u t t o n ( l a b e l s [ i ] ) ;
buttons[i].setContentAreaFilled(false);
buttons[i].addltemListener(this);
group.add(buttons[i]);
add(buttons[i]);
}
if (event.getStateChange0 == ItemEvent.SELECTED) {
System.out.println(radiobutton.getText() + " selected.");
} else {
System.out.println(radiobutton.getText() + " deselected.")
598 Глава 14. Основы Swing
Компонент JTextField
Функции Swing-компонента J T e x t F i e l d почти полностью совпадают с функциями
AWT-компонента T e x t F i e I d . И тот и другой элемент позволяют задавать в конструкто
ре начальный текст, ширину элемента и тип выравнивания. В отличие от T e x t F i e I d ,
после создания J T e x t F i e l d с помощью конструктора, вызываемого без параметров, вы
можете вызывать методы s e t T e x t , s e t C o l u m n s и s e t H o r i z o n t a l A l i g n m e n t . Типы
выравнивания задаются константами J T e x t F i e l d . LEFT, J T e x t F i e l d . CENTER и
J T e x t F i e l d . R I G H T . Для получения введенного текста используется метод g e t T e x t .
При нажатии клавиши <Enter> генерируется событие A c t i o n E v e n t , а при вводе обыч
ных символов— событие D o c u m e n t E v e n t . За^метьте, что J T e x t F i e l d не применяется
для ввода пароля, для этой цели используется компонент J P a s s w o r d F i e l d .
Компонент JTextArea
Swing-компонент J T e x t A r e a похож на AWT-компонент T e x t A r e a и отличается от
него двумя особенностями. Во-первых, в J T e x t A r e a прокрутка по умолчанию не ис
пользуется. Как и для всех Swing-компонентов, прокрутка реализуется с помощью
J S c r o l l P a n e . Во-вторых, текстовые области реализуются с помощью J T e x t A r e a и
J E d i t o r P a n e и позволяют не только выводить текст, но и выполнять более сложные
действия. В частности, J E d i t o r P a n e дает возможность отображать HTML- и RTF-
документы.
Компонент JFileChooser
Управляющий элемент J F i l e C h o o s e r (рис. 14.23) позволяет пользователям вы
бирать файлы в интерактивном режиме, просматривая содержимое каталогов.
Обычно при создании экземпляра J F i l e C h o o s e r конструктору класса передается
объект S t r i n g , определяющий каталог (строка "." соответствует тек)^щему каталогу).
Вы также можете указать файл, выбираемый по умолчанию (метод s e t S e l e c t e d -
F i l e ) , и ограничить список отображаемых файлов указанными типами (для этого на
до создать объект F i l e F i l t e r и связать его с окном выбора файла). Для определения
14.13. Простые Swing-компоненты 599
[ЗЗЗНННВВННН
LOOK in \....> >
!J...J Allaire
" ^ MMi
L J BACKUP
"3
1, JBDK1.1
1 .iCDROM
, ж111..^л.1.и-СШ^И1^^И
••••i-J Рис. 14.23. Компонент J F i l e C h o o s e r
Ftlenantic; |t"-WP 2na-Edition
позволяет пользователю выбирать
Fites of type \>\\\ Fnes г "i Canc^et 1 в интерактивном режиме один или
d.
несколько файлов
14-14. Резюме
в данной главе обсуждался ряд Swing-компоненов, имеющих аналоги в пакете
AWT: J L a b e l , J B u t t o n , J S l i d e r , J P a n e l , J A p p l e t и J F r a m e . Кроме того, здесь бы
ли рассмотрены компоненты, специфические для Swing, такие как J C o l o r C h o o s e r ,
J O p t i o n P a n e и J I n t e r n a l F r a m e . Все Swing-компоненты, за исключением окон, яв
ляются легковесными и отображаются с помощью Java-кода. Панель содержимого в
J F r a m e и J A p p l e t представляет собой объект J P a n e l , реализующий по умолчанию
двойную буферизацию. И с J F r a m e и с J A p p l e t связан диспетчер компоновки
BorderLayout.
Swing-компоненты предоставляют разработчику богатые возможности. В частно
сти, при слздании интерфейса можно выбирать его стиль, создавать новое обрамле-
600 Глава 14. Основы Swing
В ЭТОЙ главе...
В
этой главе мы рассмотрим т р и компонента, которые используются для создания
сложных графических интерфейсов: J L i s t , J T r e e и J T a b l e . Списки Swing по
хожи на знакомые вам AWT-компоненты L i s t , однако, помимо вывода набора
строк, компонент J L i s t позволяет также отображать пиктограммы. Компоненты
J T r e e и J T a b l e н е имеют AWT-аналогов. J T r e e представляет данные в виде иерар
хической древовидной структуры. Примером древовидной структуры может служить
иерархия каталогов и файлов, отображаемая многими приложениями. Компонент
J T a b l e позволяет представить данные в виде двухмерной таблицы. Все т р и компо
нента соответствуют архитектуре *'модель-просмотр-контроллер", и данные для ка
ждого из них хранятся в модели данных. П р и изменении данных генерируется собы
тие, сообщающее о том, что представление данных необходимо обновить.
Все т р и компонента предоставляют модели данных со встроенными методами,
предназначенными для модификации данных и генерации событий. В соответствии с
моделями данных и н ф о р м а ц и я представляется как объекты J L a b e l . Мы покажем
вам, как создавать собственные модели данных и средства просмотра, позволяющие
представлять в составе рассматриваемых компонентов другие объекты. Определяя
собственные средства просмотра, вы можете отображать в рассматриваемых компо
нентах любые простые элементы Swing, например выводить изображения в составе
древовидной структуры либо флажки опций в ячейках таблицы.
В данной главе мы также рассмотрим два важных вопроса: вывод Swing-
компонентов на печать и обновление этих компонентов с учетом многопотоковой
обработки. Класс G r a p h i c s 2D, рассмотренный в главе 10, позволяет масштабировать
компоненты для вывода высококачественной графики на п р и н т е р . Мы покажем вам,
как открывать диалоговое окно принтера, предоставляющее пользователю возмож
ность выбора опций, и создавать методы для вывода на печать Swing-компонентов.
По сравнению с AWT процедура вывода на печать Swing-компонентов претерпела
существенные изменения. Со Swing-компонентами связываются независимые обрам
ления и UI-представители, предназначенные ддя создания и н т е р ф е й с о в выбранного
стиля. Изменение состояния Swing-компонентов всегда производится в потоке, вы
полняющем передачу событий. В данной главе мы рассмотрим порядок обращения к
604 Глава 15. Расширенные средства Swing
p r i v a t e c l a s s MyListListener
implements L i s t S e l e c t i o n L i s t e n e r {
p u b l i c void v a l u e C h a n g e d ( L i s t S e l e c t i o n E v e n t event) {
606 Глава 15. Расширенные средства Swing
}
В случае применения обработчика в теле метода, вызываемого при появлении со
бытия, следует вызвать метод g e t V a l u e l s A d j u s t i n g класса L i s t S e l e c t i o n E v e n t и
проверить, возвращает ли этот метод значение f a l s e . В данном случае два события,
сообщающих о том, что выбор предыдущего пункта был отменен, игнорируются.
Методика профессионалов
p u b l i c JList()
p u b l i c JList(Object[] data)
p u b l i c JList(Vector data)
p u b l i c JList(ListModel m o d e l )
Первый конструктор создает пустой объект J L i s t , не содержащий информации.
Второй и третий конструкторы принимают данные, о ф о р м л е н н ы е соответствен
но в виде массива и объекта V e c t o r . П р и вызове четвертого конструктора ему пе
редается объект L i s t M o d e l , который содержит методы, позволяющие определять
размер списка и получать значения пунктов.
p u b l i c L i s t M o d e l getModel()
p u b l i c void s e t M o d e l ( L i s t M o d e l m o d e l )
Метод g e t M o d e l позволяет получить модель данных, содержащую пункты списка,
предназначенные для отображения. Метод s e t M o d e l задает модель данных.
15.2. Компонент JList 607
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
public JListSimpleExample() {
super("Creating a Simple JList");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
Border valuePanelBorder =
BorderFactory.createTitledBorder("JList Selection")
valuePanel.setBorder(valuePanelBorder);
valuePanel.add(valueLabel) ;
valuePanel.add(valueField) ;
content.add(valuePanel, BorderLayout.SOUTH);
packO ;
setVisible(true);
ШШШШШШШШ
Sample JList
Entry 1 '
Entry!
Entry 4jrj
JList Selection
Листинг 1 5 . 2 . D e f a u l t L i s t M o d e l E x a m p l e . j a v a
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public DefaultListModelExample() {
super("Creating a Simple JList");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
15.2. Компонент JList 611
Sample JLIst
Entry 1 0 ^
Entry 11
[Entry 12 I
Adding Entries
Интерфейс ListModel
import java.awt.*;
import javax.swing.*;
Листинг 15.4.JavaLocationListModel.Java
import javax.swing.*;
import javax.swing.event.*;
new JavaLocation("Spain",
"near Viana de Bolo",
"flags/spain.gif"),
new JavaLocation("Suriname",
"near Paramibo",
"flags/suriname.gif"),
new JavaLocation("United States",
"near Montgomery, Alabama",
"flags/usa.gif"),
new JavaLocation("United States",
"near Needles, California",
"flags/usa.gif"),
new JavaLocation("United States",
"near Dallas, Texas",
"flags/usa.gif")
};
private JavaLocation[] locations;
private int numCountries;
Листинг 15.6.JavaLocation.Java
Интерфейс ListCellRenderer
в интерфейсе L i s t C e l l R e n d e r e r объявлен единственный метод g e t L i s t -
CellRendererComponent.
Листинг 15.7.JListCustomRenderer.Java
import j a v a . a w t . * ;
import j a v a x . s w i n g . * ;
/** Простой компонент J L i s t , иллюстрирующий применение
* средств визуализации, определенных разработчиком
* (JavaLocationRenderer).
V
p u b l i c c l a s s JListCustomRenderer extends JFrame {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new J L i s t C u s t o m R e n d e r e r 0 ;
p u b l i c JListCustomRenderer() {
s u p e r ( " J L i s t with a Custom Cell Renderer")
WindowUtilities.setNativeLookAndFeel();
15.2. Компонент JList 619
addWindowListener(new ExitListener());
Container content = getContentPane();
JavaLocationCollection collection =
new JavaLocationCollection0;
JavaLocationListModel listModel =
new JavaLocationListModel(collection);
JList sampleJList = new JList(listModel);
sampleJList.setCellRenderer(new JavaLocationRenderer())
Font displayFont = new Font("Serif", Font.BOLD, 18);
sampleJList.setFont(displayFont);
content.add(sampleJList) ;
packO ;
setVisible(true) ;
}
}
Вместо того чтобы принимать решение о том, каким должен быть цвет компонен
та при выбранном пункте, при наличии фокуса и т.д., лучше создать подкласс класса
D e f a u l t L i s t C e l l R e n d e r e r (реализующего интерфейс L i s t C e l l R e n d e r e r ) и мо
дифицировать возвращаемый объект J L a b e l , в котором цвета установлены коррект
но. Например, в листинге 15.8 показано, как к объект)^ J L a b e l , возвращаемому мето
дом s u p e r . g e t L i s t C e l l R e n d e r e r , добавляется объект I c o n . Текст, цвет переднего
плана и цвет фона J L a b e l остаются без изменений. Заметьте, что при каждом щелчке
на пункте списка вызывается метод g e t L i s t C e l l R e n d e r e r C o m p o n e n t , поэтому для
повышения производительности желательно сохранять в памяти внутренние компо
ненты, которые генерируются при построении возвращаемых компонентов. В дан
ном примере при каждом изменении пункта списка средства визуализации использу
ют для отображения в J L a b e l флага страны объект Image I c o n . Чтобы увеличить бы
стродействие программы, создается хеш-таблица, в которой объекты Image I c o n
связываются с объектами J a v a L o c a t i o n . Если объект J a v a L o c a t i o n уже отобра
жался, вместо генерации нового Image I c o n используется объект, созданный ранее.
Внешний вид модифицированного списка J L i s t , который использует средства ви
зуализации, созданные разработчиком, показан на рис. 15.4.'
Листинг 1 5 . 8 . J a v a L o c a t i o n R e n d e r e r . J a v a
import javax.swing.*;
import java.awt.*;
import java.util.*;
JLabel label =
(JLabel)super.getListCellRendererComponent(list,
value,
index,
isSelected,
hasFocus) ;
if (value instanceof JavaLocation) {
JavaLocation location = (JavaLocation)value;
Imagelcon icon = (Imagelcon)iconTable.get(value);
if (icon == null) {
icon = new Imagelcon(location.getFlagFile0);
iconTable.put: (value, icon) ;
}
label.setlcon(icon);
} else {
// Очистка старой пиктограммы; это необходимо сделать
// при работе с первыми реализациями JDK 1.2.
label.setlcon(null);
}
return(label);
}
15.3. JTree 621
шшвшшшшшшвш
• Java, Belfiiini (near Liege).
15.3. JTree
Компонент J T r e e отображает элементы данных (узлы) в виде иерархической
структуры. В данном разделе мы рассмотрим основы использования JTree, особен
ности обработки событий, связанные с выбором узлов, обсудим пример модели дре
вовидной структуры, определяемой пользователем (дерева, допускающего создание
дочерних узлов в процессе работы), и покажем, как заменить пиктограммы, пред
ставляющие узлы дерева, на изображения, определенные разработчиком.
public D e f a u l t M u t a b l e T r e e N o d e ( )
public D e f a u l t M u t a b l e T r e e N o d e ( O b j e c t data)
public D e f a u l t M u t a b l e T r e e N o d e ( O b j e c t data, b o o l e a n allowChildren)
Bee приведенные конструкторы предназначены для создания узла дерева. Первый
конструктор формирует "пустой" узел, не содержащий данных. Второй конструк
тор позволяет задавать данные. Т р е т и й конструктор дает возможность явно опре
делить, может ли данный узел содержать дочерние узлы. По умолчанию наличие
дочерних узлов допускается.
М е т о д ы класса D e f a u l t M u t a b l e T r e e N o d e
Класс D e f a u l t M u t a b l e T r e e N o d e содержит 50 методов, предназначенных для мо
дификации дочерних и родительских узлов, а также для определения относитель
ного расположения узла в иерархии. Наиболее часто используемые методы описа
ны ниже.
public E n u m e r a t i o n children()
Метод c h i l d r e n возвращает объект E n u m e r a t i o n , содержащий непосредствен
ных потомков данного узла. Если узел не имеет дочерних узлов, возвращается зна
чение n u l l .
1 5 , 3 . JTree 623
Листинг 15.9.SimpleTree.Java
p u b l i c SimpleTree0 {
s u p e r ( " C r e a t i n g a Simple J T r e e " ) ;
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new E x i t L i s t e n e r ( ) ) ;
Container c o n t e n t = g e t C o n t e n t P a n e ( ) ;
Object[] h i e r a r c h y =
{ "javax.swing",
"javax.swing.border",
"javax.swing.colorchooser",
624 Глава 15. Расширенные средства Swing
"j avax.swing.event",
"javax.swing.filechooser",
new Object[] { "javax.swing.plaf",
"javax.swing.plaf.basic",
"javax.swing.plaf.metal",
"javax.swing.plaf.multi" ) ,
"javax.swing.table",
new Object[] { "javax.swing.text",
new Object[] { "javax.swing.text.html".
• j avax.swing.text.html.parser" },
"javax.swing.text.rtf" },
"javax.swing.tree"
"javax.swing.undo" };
DefaultMutableTreeNode root » processHierarchy(hierarchy);
JTree tree = new JTree(root);
content.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize(275, 300);
setVisible(true);
}\
/** Простая процедура, оформляющая первый элемент массива
* в виде узла древовидной структуры. Остальные элементы
* массива определяются как узлы, дочерние по отношению
* к первому. Процесс повторяется рекурсивно для всех
* элементов, являющихся, в свою очередь, массивами.
V
private DefaultMutableTreeNode processHierarchy(
Object[] hierarchy) {
DefaultMutableTreeNode node =
new DefaultMutableTreeNode(hierarchy[0]);
DefaultMutableTreeNode child;
for(int i=l; i<hierarchy.length; i++) {
Object nodeSpecifier = hierarchy[i];
if (nodeSpecifier instanceof Object[]) { //Node with children
child = processHierarchy((Object[])nodeSpecifier);
} else {
child = new DefaultMutableTreeNode(nodeSpecifier); //Leaf
}
node.add(child);
}
return(node);
15.3.JTree 625
|fflflHI'l,ll.|[|IHIilMli>mtM^Msi
:1J javax. swing . J javax swing
' • javax.swing.border » javax.swing.border
• » javax svvlng.colorchooser • lavaxswing.coiorchooser
' ш javax.swing.event • javax swing.event
[ « javax.8wing.filechooser % javax.swJng.mechooser
if lJi9vax.swing.plaf - 1 javax.8wing.plaf
I • javaxswing.table » javax.swingplafbasic
s- _I;j javax.swing.text « javax.swing.plafmetal
i • javax.swlng.tree • javax.swlng.plafmulti
' • javaxswlng.undo # javaxswing.table
- ^ javax.swing.text
f javax.swing.lext.html
« javax.swlng.text.html.parser
• Javax.swing,text,rtf
Ф javax swing.tree
» Javax.8wing.undo
(a) (6)
Рис. 15.5. Компонент Jtree: a— папки закрыты; б— в результате
действий пользователя папки развернуты
Конструкторы JTree
lOiacc JTree предоставляет семь различных конструкторов. Два из них, которые
применяются наиболее часто, описаны ниже. Другие, менее популярные конструкто
ры позволяют задавать информацию в виде объектов Vector или Hash t a b l e . В клас
се JTree также определен конструктор без параметров, однако при создании он за
полняется данными, предоставляемыми Sun, и годится только для написания проб
ных примеров.
к типу узла (обычно это Def aultMutableTreeNode). Для извлечения данных, содер
жащихся в узле, надо использовать метод getUserObject. Если же вам нужен лишь
текст, соответствующий данному узлу, достаточно вызвать метод toString объекта,
возвращаемого в результате вызова tree . getLastSelectedPathComponent.
В листинге 15.10 приведен код, в котором создается древовидная структура. Каж
дый узел этой структуры имеет три дочерних узла. С компонентом JTree связан об
работчик TreeSelectionListener. Когда пользователь выбирает узел, в поле ре
дактирования, расположенном в нижней части окна, отображается значение, полу
ченное в результате вызова метода toString узла (рис. 15.6).
Листинг 15.10.SelectableTree.Java
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax. swing, event.'^;
Htfflwmw
„ J Root
\щтшшвш^шшш
„JRoot i
* . ? Child 1 - J Child 1
•^ I Child 2 « Grandchild 11
+ . I Child 3 • Grandchild 12
# Grandchild 1.3 i
- % Child 2 il
• Grandchild 2.1 il
« Grandchild 23 ::
- <5 Child 3
# Grandchild 31
• Grandchild 32
• Grandchild 3.3 |
менений, а вместо этого создают новый класс TreeNode. Проще всего сделать это,
создавая подкласс класса DefaultMutableTreeNode, обеспечивающего поддержку
родительского узла и нескольких дочерних узлов.
Ниже мы рассмотрим часто используемые методы класса D e f a u l t M u t a b l e
TreeNode и приведем пример узла, определенного пользователем, построенного как
подкласс класса DefaultMutableTreeNode.
public T r e e N o d e [ ] getPath()
Метод g e t P a t h возвращает массив узлов, представляющий путь от корневого до
данного узла.
public T r e e N o d e getRoot()
Данный метод возвращает корневой узел дерева.
public b o o l e a n isLeaf()
public b o o l e a n isRoot()
Метод i s L e a f возвращает значение t r u e , если узел является листом (т.е. не имеет
дочерних узлов); в противном случае возвращается значение f a l s e . Метод
i s R o o t возвращает значение t r u e , если данный узел является корневым узлом
дерева; в противном случае возвращается значение f a l s e .
Возможно, вы захотите, чтобы дерево строилось динамически, т.е. узлы создава
лись в ответ на действия пользователя. В этом случае узел, определяемый разработ
чиком, можно построить на базе Def a u l t M u t a b l e T r e e N o d e . Первоначально в состав
дерева включаются не все узлы, а лишь те, которые должны непосредственно ото
бражаться на экране. В этом случае необходимо разработать алгоритм для описания
дочерних узлов, которые генерировались бы только при разворачивании папки.
В листинге 15.11 показан код, при выполнении которого строится дерево, пред
ставляющее иерархическую нумерацию пунктов. Корневому узлу соответствует номер
1, дочерним узлам первого уровня — номера 1.1, 1.2, 1.3 и т.д. Дочерним узлам второго
уровня соответствуют номера 1.1.1, 1.1.2 и т.д. Число дочерних узлов для каждого узла
задается в качестве параметра командной строки при вызове программы.
При динамическом построении J T r e e перед отображением дочерних узлов вызы
вается метод g e t C h i l d C o u n t . Специальный флаг указывает, были ли узлы построены
раньше. В теле метода g e t C h i l d C o u n t , если значение флага равно f a l s e , строятся
дочерние узлы и добавляются к текущему узлу. Ч т о б ы предотвратить попытки под
счета дочерних узлов (и соответственно их построения) при определении, является
ли узел листом, в примере переопределен метод i s Leaf, который всегда возвращает
значение f a l s e . Реализация данного подхода продемонстрирована в листинге 15.12,
в котором представлен код для динамического построения узлов. Результаты выпол
нения программы показаны на рис. 15.7.
import java.awt.*;
import javax.swing.*;
p u b l i c c l a s s DynamicTree e x t e n d s JFrame {
public s t a t i c void main(String[] args) {
i n t n = 5; / / Число дочерних у з л о в для каждого у з л а .
630 Глава 15. Расширенные средства Swing
if (args.length > 0) {
try (
n = Integer.parseint(args[0]);
} catch(NumberFormatException nfe) {
System.out.println(
"Can't parse number; using default of " + n ) ;
}
}
new DynamicTree(n);
}
public DynamicTree(int n) {
super("Creating a Dynamic JTree");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
JTree tree = new JTree(new OutlineNode(1, n ) ) ;
content.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize (300, 475);
setVisible(true);
}
Листинг 15.12.OutlineNode.Java
import java.awt.^;
import javax.swing.*;
import javax.swing.tree.*;
(6)
Рис. 15.7. Объект TreeNode, определяемый разработчиком, допускает дина
мический рост древовидной структуры: а — исходное дерево; 6 — узлы,
динамически построенные при развертывании папок
632 Глава 15. Расширенные средства Swing
Листинг 15.13.Customlcons.Java
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
/** JTree без пиктограмм в узлах дерева или с
пиктограммами, определенными пользователем. */
public Customlcons() {
super("JTree Selections");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
content.setLayout(new FlowLayout());
DefaultMutableTreeNode root =
new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode child;
DefaultMutableTreeNode grandchild;
for(int childlndex=l; childlndex<4; childlndex++) {
child = new DefaultMutableTreeNode("Child " + childlndex);
root.add(child);
for(int grandChildIndex=l; grandChildIndex<4;
grandChildIndex++) {
grandchild =
15.3. JTree 633
packO ;
setVisible(true);
}
634 Глава 15. Расширенные средства Swing
iHPiffuwffiimi
standard icons No (cons ' Custom teo«s
, s Root Root ( f ) Root
- „jChildl • Child 1 + Г2) Child 1
• Grandchild i 1 - Child 2 + ^ r ) Child 2
« Grandchild 1 2 Grandchild 21 - M Child 3
« Grandchild 1 3 Grandchild 2 2 (3) Grandchild 3 1
• _ J Child 2 Grandchild 2 3 f i } Grandchild 3 2
* J Child 3 .+ Child 3 ( ? ) Grandchild 3.3
15.4. JTable
Компонент J T a b l e отображает данные в виде двухмерной таблицы, состоящей из
строк и столбцов. Данный компонент— самый сложный в Swing API. Работа J T a b l e
базируется на трех моделях: модели таблицы, модели столбца и модели выбора спи
ска. Модель таблицы обрабатывает данные в ячейках таблицы, модель столбца управ
ляет добавлением и удалением столбцов таблицы, а модель выбора списка позволяет
выбирать строки таблицы (выбор столбцов поддерживается моделью столбца).
Каждая из перечисленных моделей реализована отдельно. Все три реализации
хранятся в пакете j a v a x . s w i n g , t a b l e . В данном разделе мы рассмотрим модель
таблицы, используемую по умолчанию, и модель, определяемую разработчиком. Под
робную информацию о модели столбцов и модели выбора вы найдете в книге Кима
Топли (Kim Topley) CoreJava Foundation Classes.
Ha заметку
Чтобы заголовки JTable отображались на экране, компонент должен
быть помещен в состав объекта JScrollPane,
Ш
Конструкторы JTable
в классе J T a b l e определено семь конструкторов. Если данные для ячеек не зада
ны, ячейки таблицы заполняются значениями n u l l . П о умолчанию заголовки столб
цов создаются по соглашению, принятому в большинстве электронных таблиц (А, В,
С, АА, ВВ, СС, ...). Пять наиболее часто используемых конструкторов J T a b l e описа
ны ниже. Всеми конструкторами, кроме последнего, таблица создается с использова
нием D e f a u l t T a b l e M o d e l , D e f a u l t C o l u m n M o d e l и D e f a u l t L i s t S e l e c t i o n M o d e l .
public JTableO
Данный конструктор создает пустую таблицу с внутренними моделями Def a u l t
T a b l e M o d e l , D e f a u l t C o l u m n M o d e l и D e f a u l t L i s t S e l e c t i o n M o d e l . Для запол
нения таблицы используются методы addRow и addColumn. По умолчанию каждая
ячейка таблицы допускает редактирование содержимого.
public JTable(TableModel m o d e l )
Данный конструктор создает объект J T a b l e , в котором строки и столбцы опреде
ляются с помощью параметра T a b l e M o d e l . Чаще всего модель таблицы строится
на основе A b s t r a c t T a b l e M o d e l либо Def a u l t T a b l e M o d e l ; каждый из этих объ
ектов генерирует события T a b l e M o d e l E v e n t . Таблица также содержит D e f a u l t
ColumnModel и D e f a u l t L i s t S e l e c t i o n M o d e l .
636 Глава 15. Расширенные средства Swing
public T a b l e M o d e l getModel()
public v o i d s e t M o d e l ( T a b l e M o d e l tableModel)
Метод g e t M o d e l возвращает, a метод s e t M o d e l устанавливает объект T a b l e -
Model. Объект T a b l e M o d e l содержит данные, отображаемые в ячейках J T a b l e .
public T a b l e C o l u m n M o d e l g e t C o l u m n M o d e l ( )
public s e t C o l u m n M o d e l ( T a b l e C o l u m n M o d e l c o l u m n M o d e l )
Метод g e t ColumnModel возвращает, a метод s e t C o l u m n M o d e l устанавливает
объект T a b l e C o l u m n M o d e l для таблицы. По умолчанию модель столбцов создает
ся автоматически. Если таблица должна обеспечивать перемещение столбцов про
граммным способом, необходимо создать новую модель столбцов. T a b l e C o l u m n
Model также управляет выбором одного или нескольких столбцов. Подробно объ
ект T a b l e C o l u m n M o d e l описан в разделе документации на API, посвященном
j avax.swing.table.
public L i s t S e l e c t i o n M o d e l g e t S e l e c t i o n M o d e l ( )
public void s e t S e l e c t i o n M o d e l ( L i s t S e l e c t i o n M o d e l s e l e c t i o n M o d e l )
Метод g e t S e l e c t i o n M o d e l возвращает, a метод s e t S e l e c t i o n M o d e l устанавливает
модель выбора. Объект L i s t S e l e c t i o n M o d e l используется как J T a b l e , так и J L i s t и
поддерживает выбор одного элемента, выбор в одном и в нескольких интервалах. При
изменении выбора ячеек объект L i s t S e l e c t i o n E v e n t помещается в очередь собы
тий и в дальнейшем передается методу v a l u e C h a n g e d таблицы. Для определения вы
бранных строк используются методы g e t S e l e c t e d R o w и g e t S e l e c t e d R o w s . Модель
TableColumnModel может поддерживать L i s t S e l e c t i o n M o d e l для выбора столб
цов. Дополнительную информацию о L i s t S e l e c t i o n M o d e l вы найдете в разделе до
кументации по API, посвященном j a v a x . swing.
import j a v a . a w t . * ;
import j a v a x . s w i n g . * ;
/** Простой пример JTable, в котором заголовки таблицы и
^ данные задаются как массивы S t r i n g
Ч
public c l a s s JTableSimpleExample extends JFrame {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
new JTableSimpleExample0;
p r i v a t e f i n a l i n t COLUMNS = 4;
p r i v a t e f i n a l i n t ROWS = 15;
p r i v a t e JTcuDle sample JTable;
p u b l i c JTableSimpleExample() {
s u p e r ( " C r e a t i n g a Simple J T a b l e " ) ;
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new E x i t L i s t e n e r ( ) ) ;
Container content = g e t C o n t e n t P a n e ( ) ;
S t r i n g [ ] columnNames = buildColumnNames (COLUMNS)
638 Глава 15. Расширенные средства Swing
return(header)
}
p r i v a t e S t r i n g [ ] [ ] b u i l d T a b l e C e l l s ( i n t rows, i n t columns) {
S t r i n g [ ] [ ] c e l l s = new S t r i n g [ r o w s ] [ c o l u m n s ] ;
f o r ( i n t i=0; i<rows ; i++) {
f o r ( i n t j=0; j<columns; j++ ) {
c e l l s [i] [j] = "Row " + i + ", Col " + j ;
}
}
return(cells);
1 СоЫтп Э шш\
1 ОоШтл 0
JRowO, Col 0
1 Column 1
RowO. Col 1
1 Cs^lunw ^
RowO. Col 2 RowO, Col 3 1MI
|Row1,ColO R o w l , Col 1 Row 1. Col 2 R o w l . Col 3
IROW 2, Col 0 Row 2, Col 1 Row 2, Col 2 Row 2, Col 3
|Row3, ColO Row 3. C o l l Row3. Col 2 Row 3, Col 3 "-; 1
^Row4, Col 0 Row 4, Col 1 Row 4, Col 2 Row 4, Col 3
I R O W S , Col 0 Row 5, Col 1 Row 5, Col 2 Row 5, Col 3
iRow 6. Col 0 Row 6. Col 1 Row 6, Col 2 Row 6, Col 3
|Row7, Col 0 Row 7. Col 1 Row 7. Col 2 Row 7, Col 3
, Рис. 15.9. Простой объект JTable,
lRow8, Col 0 Row 8. C O M Row 8. Col 2 Row 8, Col 3
^ помещенный в панель с прокруткой
• p u b l i c i n t getRowCount()
• p u b l i c i n t getColumnCount()
• p u b l i c Object g e t V a l u e A t ( i n t row, i n t column)
Особенности реализации данных методов определяются структурой модели данных.
В классе A b s t r a c t T a b l e M o d e l содержится реализация метода setValueAt для
поддержки нередактируемых структур данных. Поскольку s e t V a l u e A t не модифи
цирует данные, метод i s C e l l E d i t a b l e всегда возвращает значение f a l s e .
Swing API также содержит класс DefaultTableModel, который является подклас
сом класса A b s t r a c t T a b l e M o d e l и реализует все абстрактные методы своего супер
класса. Данные в классе DefaultTableModel организованы в виде объектов Vector.
Элементами вектора строк также являются объекты Vector, содержащие данные
ячеек. Для того чтобы соответствовать структуре данных, массивы, передаваемые
конструктору DefaultTableModel, преобразуются в объекты Vector. Если таблица
имеет большие размеры, инициализация объекта DefaultTableModel происходит
достаточно долго. Метод i s C e l l E d i t a b l e класса DefaultTableModel всегда воз
вращает значение t r u e — это значит, что пользователь может выбрать любую ячейку
таблицы и модифицировать ее содержимое.
На заметку
Метод IsCellEditable класса AbstractTableModel всегда возвра
щает значение false; в классе DefaultTableModel этот метод воз
вращает значение tJTue.
Конструктор DefaultTableModel
в классе DefaultTableModel определено шесть конструкторов. Три из них, ис
пользуемые наиболее часто, описаны ниже.
собой вектор, размер которого равен числу столбцов. Первоначально вместо дан
ных таблицы используются значения n u l l .
public void a d d C o l u m n ( O b j e c t c o l u m n N a m e )
public v o i d a d d C o l u m n ( O b j e c t c o l u m n N a m e , Object[] columnData)
public void a d d C o l u m n ( O b j e c t c o l u m n N a m e , Vector columnData)
Первый из указанных методов добавляет столбец с указанным именем к модели
таблицы. Ячейки нового столбца заполняются значениями n u l l . Два других мето
да также добавляют столбец к модели таблицы, но они позволяют задавать данные
для ячеек столбца в виде массива либо вектора.
public String g e t C o l u m n N a m e ( i n t c o l u m n )
Данный метод возвращает имя указанного столбца, полученное в результате при
менения метода t o S t r i n g . Если вместо имени столбца задано значение n u l l , то
возвращаются символы, соответствующие соглашению об именовании столбцов
(А, В, С, ..., АА, ВВ, СС, ...). Если заданный номер столбца меньше нуля, а также ее-
15,4. JTable 641
Листинг 1 5 . 1 5 . D e f a u l t T a b l e E x a m p l e . J a v a
import Java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
p u b l i c c l a s s D e f a u l t T a b l e E x a m p l e e x t e n d s JTable {
642 Глава 15. Расширенные средства Swing
piiblic DefaultTableExample () {
this(new DefaultTableModelО);
JavaLocationCollection collection =
new JavaLocationCollection0;
JavaLocation[] locations = collection.getLocations();
int i;
for(i=0; i<columnNames.length; i++ ) {
model.addColumn(columnNames[i]);
}
for(i=0; i<locations.length; i++) {
model.addRow(getRowData(locations[i]));
}
}
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
WindowUtilities.setNativeLookAndFeel();
WindowUtilities.openlnJFrame(
new JScrollPane(new D e f a u l t T a b l e E x a m p l e ( ) ) , 600, 150,
"Using a DefaultTableModel");
}
table.sizeColumnsToFit(JTable.AUTO_RESIZE_OFF);
В классе TableColumn также определен метод setWidth, однако ширина столбца,
установленная с его помощью, не сохраняется после изменения размеров таблицы.
Листинг 15.16.CustomTableExample.Java
import javax.swing.*;
import javax.swing.table.*;
public CustomTableExample() {
super(new CustomTableModel());
setCellSizes();
}
private void setCellSizes () {
setRowHeight(50);
getColumn("Flag").setMaxWidth(55);
getColumn("City").setPreferredWidth(60);
getColumn("Country").setMinWidth(80);
getColumn("Comment").setMinWidth(150);
// Вызов метода для повторной установки размеров
// столбцов (коррекция ошибки).
SizeColumnsToFit(JTable.AUTO_RESIZE_OFF);
}
public static void main(String[] args) {
WindowUtilities.setNativeLookAndFeel();
WindowUtilities.openlnJFrame(
new JScrollPane(new CustomTableExample()), 525, 255,
"Using a CustomTableModel");
}
15.4.JTable 645
import javax.swing.table.*;
Usma a {JmAimTeMeiiodel
Fiag Crty Coia^ I Cemment
m
11 1 Java
1 Java
Belgium
Braz.l
inear Liege
inear Salvador
@
}
});
Выяснив, какая из ячеек стала причиной возникновения события, вы можете по
лучить содержимое ячейки, вызвав метод g e t V a l u e A t ( r o w , c o l u m n ) , либо задать
новые данные посредством метода s e t V a l u e A t ( r o w , c o l u m n ) . Метод g e t V a l u e A t
возвращает значение O b j e c t ; это значение надо привести к соответствующему типу.
Реально изменения данных проводятся в рамках модели, лежащей в основе таблицы.
Поэтому для обновления внешнего вида объекта J T a b l e надо сгенерировать событие
TableModelEvent.
Класс A b s t r a c t T a b l e M o d e l , являющийся суперклассом для T a b l e M o d e l , предос
тавляет семь методов, предназначенных для генерации событий. Чаще всего исполь
зуются два метода: f i r e T a b l e C e l l U p d a t e d ( r o w , c o l u m n ) , который обновляет
конкретную ячейку, и f i r e T a b l e D a t a C h a n g e d () , который обновляет всю таблицу.
Java 2 Platform также определяет события T a b l e C o l u m n M o d e l E v e n t для внесения
изменений в T a b l e C o l u m n M o d e l и L i s t S e l e c t i o n E v e n t — для внесения изменений
в ListSelectionModel.
В листинге 15.18 показан код, создающий таблицу, в которой пользователь указы
вает книги, которые он собирается приобрести. В программе импортируется пакет
j a v a x . s w i n g . e v e n t и обработчик событий связывается с моделью таблицы. Когда
пользователь изменяет число книг, объект T a b l e M o d e l L i s t e n e r получает событие
T a b l e M o d e l E v e n t и вычисляет общую стоимость заказа. По окончании вычислений
и записи данных в модель генерируется событие T a b l e M o d e l E v e n t , предназначен
ное для обновления представления данных на экране. Результаты выполнения про
граммы показаны на рис. 15.12.
Значительная часть кода в составе обработчика преобразовывает данные из стро
кового формата в числовой и наоборот. Если вы незнакомы с классом
D e c i m a l F o r m a t , прочитайте о нем в разделе документации по API, посвященном
j ava.text.DecimalFormat.
Листинг 1 5 . 1 8 . J T a b l e E v e n t s o a v a
import java.awt.*;
import Java.text.DecimalFormat;
import javax.swing.*;
import j avax.swing.event.*;
import javax.swing.table.*;
// Обновление строки.
tableModel.setValueAt(df.format(subTotal),
row, COL_TOTAL);
// Полное обновление.
grandTotal =0;
for(int row=0; row<data.length-1; row++) {
648 Глава 15. Расширенные средства Swing
content.add(tablePane, BorderLayout.CENTER);
setSize(460,150);
setVisible(true);
ЩUsing TdbleEvenU
Pfinter
••••EQI
Najr.e Eroperties 1
Шшззшвшшшшшт• H d „
Status Ready
Type; H P LaserJet 4000 Senes РГз
(^ Ah f' "^
f" Page 6 tiorrr p to 1 ' •
r Collate
1"" OK ^ Cancel j 1
1
Рис. 15.13. Внешний вид окна, отображаемого в результа
те вызова метода p r i n t D i a l o g
650 Глава 15. Расширенные средства Swing
return(PAGE EXISTS);
}
}
Методы g e t l m a g e a b l e X и g e t l m a g e a b l e Y возвращают координаты левого верх
него угла изображения, выводимого на печать. Оно определяется исходя из типа
принтера, размера и ориентации бумаги, заданных в диалоговом окне Printer.
На з а м е т к у
М е т о д и к а профессионалов
Листинг 1 5 . 1 9 . P r i n t U t i l i t i e s . J a v a
import java.awt.*;
import javax.swing.*;
import Java.awt.print.*;
* <PRE>
* PrintUtilities printHelper =
* new PrintUtilities(theComponent);
* </PRE>
* a затем вызывать printHelper.print(). Однако
* в большинстве случаев проще обращаться к
'*' PrintUtilities . printComponent (componentToBePrinted)
V
public class PrintUtilities imiplements Printable {
protected Component componentToBePrinted;
RepaintManager currentManager =
RepaintManager.currentManager(с);
currentManager.setDoubleBufferingEnabled(false);
}
/** Возобновление двойной буферизации необходимо
* только при работе с JDK 1.2.
V
public static void enableDoubleBuffering(Component с) {
RepaintManager currentManager =
RepaintManager.currentManager(с);
currentManager.setDoubleBufferingEnabled(true);
}
import java.awt.*;
import javax.swing.*;
import Java.awt.event.*;
import Java.awt.print.*;
buttonPanel.setBackground(Color.white)/
buttonPanel.add(printButton);
content.add(buttonPanel, BorderLayout.SOUTH);
DrawingPanel drawingPanel = new DrawingPanel();
content.add(drawingPanel, BorderLayout.CENTER);
packO ;
setVisible(true);
Листинг 15.21.DrawingPanel.Java
import java.awt.*;
import javax.swing.*;
import Java.awt.geom.*;
public DrawingPanel() {
setBackground(Color.white);
Font font = new Font("Serif", Font.PLAIN, fontSize);
setFont(font);
FontMetrics metrics = getFontMetrics(font);
messageWidth = metrics.stringWidth(message);
int width = messageWidth*5/3;
int height = fontSize*3;
setPreferredSize(new Dimension(width, height));
g2d.shear(-0.95, 0) ;
g2d.scale(1, 3 ) ;
g2d.drawstring(message, 0, 0 ) ;
g2d.setTransform(origTransform);
g2d.setPaint(Color.black);
g2d.drawstring(message, 0, 0) ;
l-^<Jllil'lilil'.H'!'»4liilll.H.llli!l>i4H
М е т о д и к а профессионалов
метода paint он вызывает метод print этого компонента. Вывод на печать с помо
щью данного класса осуществляется посредством следующего выражения:
PrintUtilities2 .printCoinponent {componentToBePrinted) ;
Параметр componentToBePrinted передает методу Swing-компонент, предназна
ченный для вывода на печать.
Листинг 15.22.PrintUtilities2.java
import java.awt.*;
import javax.swing.*;
import Java.awt.print.* ;
/** Вспомогательный класс, предназначенный для вывода
^ на печать произвольного компонента в JDK 1.3.
* Данный класс использует особенность JDK 1.3,
* состоящую в том, что в классе JComponent метод
* print переопределяется; в нем автоматически
* устанавливается флаг, который запрещает двойную
* буферизацию. Если флаг установлен, paint вызывает
* printComponent, printBorder и printChildren.
•*•
* Для того чтобы вывести компонент, его надо передать
* PrintUtilities2.printComponent(componentToBePrinted)
V
public class PrintUtilities2 extends PrintUtilities {
внешний вид компонента JLabel изменится сразу же после первого, поэтому пользова
тель не увидит сообщения "Transferring . . .". Поскольку передача файла осуществ
ляется в потоке передачи событий, взаимодействие программы с пользователем будет
блокировано до завершения метода actionPerformed. Такое поведение программы
нельзя назвать приемлемым.
Решением данной проблемы может показаться передача файла и последующее об
новление компонента JLabel в отдельном потоке. При этом поток доставки событий
освобождается и может быть использован для обработки остальных событий, в част
ности события, связанного с обновлением JLabel. Рассмотрим модифицированный
методactionPerformed.
// Модифицированный обработчик событий. Действия, требующие
// больших затрат времени, выполняются в отдельном потоке,
public void actionPerformed(ActionEvent event) {
// При изменении объекта JLabel проблемы не возникают,
// поскольку действия выполняются в потоке доставки событий.
ladDel.setText("Transferring " + filename);
} catch(InvocationTargetException ite) {
} catch(InterruptedException ie) { }
15.7. Резюме
Теперь вы знаете достаточно для того, чтобы приступить к созданию профессио
нальных пользовательских интерфейсов на базе Swing-компонентов. В данной главе
мы рассмотрели лишь некоторые средства, предоставляемые расширенными компо
нентами. Для того чтобы научиться полностью использовать возможности Swing, вам
необходимо затратить время на их изучение, однако время и усилия окупятся при
создании реальных программ.
Компоненты J L i s t , J T r e e и J T a b l e могут применять для доступа и модификации
данных (а также для генерации событий) модели по умолчанию. П р и необходимости
вы можете разработать собственные хмодели данных и средства визуализации, преду
смотрев в них особенности взаимодействия с данными и их отображения, специфи
ческие для создаваемой вами программы. В состав списков, деревьев и таблиц можно
включить практически любые Swing-компоненты, но чтобы они корректно отобража
лись, необходимо реализовать соответствующие средства визуализации.
15.6. Потоки Swing 663
В ЭТОЙ главе...
Анимационные изображения.
Использование таймеров.
J~y\ZJ^ZJ
Эффективность
Некоторые задачи быстрее выполняются программами, использующими потоки.
Рассмотрим, например, копирование пяти текстовых файлов с удаленного узла.
Предположим, что для установления сетевого соединения требуется 12 секунд, а
после того, как соединение установлено, файл может быть скопирован за 1 секун
ду. Если копировать пять файлов один за другим, вся процедура займет 5 х 13 = 65
секунд. Если же все файлы будут копироваться в различных потоках, то копирова
ние займет 12 + 5 = 17 секунд. Выигрыш в производительности при выполнении
подобных задач настолько велик, что Java автоматически копирует изображения в
отдельных потоках (подробно о копировании изображений см. в главе 9).
Удобство
Некоторые задачи удобнее решать, если рассматривать различные их части от
дельно. Предположим, что вам надо отобразить циферблат часов либо анимаци
онную последовательность. В подобных случаях целесообразно возложить ответ
ственность за обновление изображения на экране на отдельный процесс.
Н о в ы е возмолсности
Некоторые задачи попросту не могут быть реализованы без поддержки потоков.
Например, HTTP-сервер должен ожидать установления сетевого соединения. При
обращении к серверу соединение передается новому процессу, который выполня
ет обработку запроса. Если бы потоки не поддерживались, то на все время обслу-
666 Глава 16. Использование потоков
живания соединения порт был бы занят. Для выполнения реальных задач такой
сервер был бы непригоден. В главе 17 мы рассмотрим код простого многопотоко
вого HTTP-сервера, использующего при работе механизм гнезд.
Несмотря на все преимущества многопотоковых программ, принимая решение о
реализации задачи в виде многопотокового приложения, следует соблюдать осторож
ность. Тестировать и отлаживать программу, в которой одновременно выполняется не
сколько потоков, гораздо сложнее, чем программу, в которой в каждый момент времени
выполняется одно конкретное действие. Поэтому, прежде чем приступать к разработке
многопотоковых программ, взвесьте все преимущества и недостатки подобного подхо
да. Приготовьтесь к тому, что процесс написания и отладки займет больше времени по
сравнению с написанием и отладкой однопотоковой программы. Затраченное вами
время будет тем больше, чем меньше ваш опыт программирования на Java.
1 6 . 1 . Запуск потоков
Java предоставляет два механизма организации многопотоковых программ: созда
ние подкласса класса T h r e a d , содержащего код, предназначенный для выполнения, и
использование экземпляра класса T h r e a d для вызова кода исходного объекта.
Листинг 1 6 . 1 . D r i v e r C l a s s . J a v a
public class DriverClass extends SomeClass
public void startAThread() {
/ / Создание о б ъ е к т а T h r e a d .
T h r e a d C l a s s t h r e a d = new T h r e a d C l a s s ( ) ;
/ / Запуск отдельного процесса,
thread.start();
}
}
Листинг 16.2.ThreadClass.Java
Листинг 16.4.CounterТеSt.Java
Counter 0: 0
Counter 1: 0
Counter 2: 0
Counter 1: 1
Counter 2: 1
Counter 1: 2
Counter 0: 1
Counter 0: 2
Counter 1: 3
Counter 2: 2
Counter 0: 3
Counter 1: 4
Counter 0: 4
Counter 2: 3
Counter 2: 4
Листинг 16.6.ThreadedClass.Java
p u b l i c void s t a r t T h r e a d ( ) {
Thread t = new Thread(this);
t . s t a r t O ; / / Вызов метода run объекта, на который
/ / указывает параметр, передаваемый конструктору.
p u b l i c void run() {
670 Глава 16. Использование потоков
Counter 0: 0
Counter 1: 0
Counter 2: 0
Counter 1: 1
Counter 1: 2
Counter 0: 1
Counter 1: 3
Counter 2: 1
Counter 0: 2
Counter 0: 3
Counter 1: 4
Counter 2: 2
Counter 2: 3
Counter 0: 4
Counter 2: 4
Глядя на данный пример, может показаться, что описываемый здесь способ слож
нее, чем создание подкласса Thread. Однако, как вы знаете, Java не допускает множе
ственное наследование, поэтому если ваш класс уже является подклассом какого-то
класса (например, Applet), то он не может быть подклассом класса Thread. Кроме
того, в данном случае метод run имеет полный доступ к переменным и методам клас
са. При использовании подкласса Thread для обеспечения доступа к основному классу
приходится принимать специальные меры. Организуя многопотоковую обработку в
аплете, создание и запуск потоков лучше всего выполнять в методе s t a r t аплета.
16.2. Возникновение "гонок" 671
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
/** Аплет запускает несколько экземпляров своего метода run
* в разных потоках. Данный аплет работает корректно
* в большинстве случаев, но не всегда!
V
public c l a s s BuggyCounterApplet extends Applet
implements Runnable{
p r i v a t e i n t totalNum = 0;
p r i v a t e i n t loopLimit = 5;
/ / Следует различать метод s t a r t класса Thread и метод s t a r t
/ / класса Applet, который вызывается после завершения
/ / метода i n i t .
p u b l i c void s t a r t О {
Thread t ;
for(int i=0; i<3; i++) {
t = new Thread(this);
t. start 0 ;
}
}
private void pause(double seconds) {
try { Thread.sleep(Math.round(1000.O*seconds)); }
catch(InterruptedException ie) {}
}
public void run() {
int currentNum = totalNxom;
System.out.printlnCSetting currentNum to " + currentNum);
totalNum = totalNum + 1;
for(int i=0; i<loopLimit; i++) {
System, out .printlnC Counter " + currentNijm + ": " + i) ;
pause(Math.random());
}
}
672 Глава 16. Использование потоков
Такой подход был бы вполне применим, если бы виртуальная машина Java обраба
тывала выражение с помощью одной команды, однако никто не может сказать, как на
самом деле будет происходить обработка. Вероятнее всего, что, поступив таким обра
зом, вы лишь снизите вероятность возникновения ошибки вследствие "гонок". Ошиб
ка будет возникать реже, однако это нельзя рассматривать как преимущество описан
ного подхода. На самом деле такое снижение вероятности ошибки является недостат
ком. Скорее всего, ошибка останется незамеченной и проявится позже, когда ее
устранение потребует больших затрат. Чтобы исключить возникновение подобных
ситуаций, в Java предусмотрен механизм синхронизации, который позволяет указать,
что, перед тем, как управление будет передано другому потоку, определенный фраг
мент кода должен закончить свое выполнение. Подробно синхронизация рассмотре
на в следующем разделе.
16.3. Синхронизация
Механизм синхронизации позволяет управлять доступом к разделяемым ресурсам.
При синхронизации фрагмента кода с этим фрагментом связывается объект блоки
ровки. Когда поток начинает выполнение синхронизированного фрагмента кода,
этот фрагмент блокируется. До окончания выполнения синхронизированного фраг
мента либо то тех пор, пока блокировка не будет явно отменена, ни один другой по
ток не может начать выполнение аналогичного фрагмента кода. Синхронизация мо
жет распространяться более чем на один фрагмент. Можно использовать в качестве
дескриптора синхронизации объект O b j e c t и задать условия блокировки так, что при
выполнении синхронизированного фрагмента будут блокированы все остальные
фрагменты, помеченные тем же дескриптором синхронизации.
На з а м е т к у
p u b l i c v o i d someMethodO {
synchronized(this) {
/ / Тело м е т о д а .
}
}
1 6 . 3 . Синхронизация 675
p u b l i c void doSomeOperation() {
synchronized(lockObject) {
accessSomeSharedObject();
}
Применяя для синхронизации произвольный объект, вы можете выбрать для него
любое имя. Это очень удобно в тех случаях, когда в одном классе содержится несколь
ко фрагментов кода, для которых в качестве дескрипторов синхронизации необходи
мо использовать разные объекты.
16.4. Создание многопотоковых методов 677
p u b l i c void run() {
MyThread t = ( M y T h r e a d ) T h r e a d . c u r r e n t T h r e a d ( ) ;
RandomClass randomArg =
(RandomClass)t.getValueSavedEarlier();
super.foo(randomArg);
}
}
Благодаря тому, что вызов реального метода f o o ( s u p e r . f o o ) перенесен в новый
поток, переопределенный метод f o o немедленно возвращает управление, а реальная
задача продолжает выполняться в фоновом режиме.
Класс MyThread имеет следующий вид:
p u b l i c c l a s s MyThread e x t e n d s T h r e a d {
p r i v a t e Object d a t a ;
p u b l i c MyThread(Runnable r u n n a b l e , Object d a t a ) {
super(runnable);
this.data = data;
}
public Object getValueSavedEarlier() {
return data;
}
}
Параметр метода f o o , randomArg, передается конструктору MyThread и сохраня
ется в локальной копии внутри MyThread, предотвращая тем самым возникновение
"гонок". Сохранение копии r a n d o m A r g вн)'три f o o не устраняет условий возникнове
ния "гонок", так как randomArg может быть изменен в интервале времени между соз
данием потока и вызовом в том же потоке s u p e r , f o o . Синхронизация внутри f o o
также не решает проблему, поскольку выполнение программы продолжается в другом
методе. При выполнении потока данные, сохраненные ранее, извлекаются и выпол
няется метод f o o суперкласса.
При создании заготовки класса MyThread предполагается, что методу f o o каждый
раз передается "новый" экземпляр класса R a n d o m C l a s s либо R a n d o m C l a s s не допус
кает изменений внутренних переменных (как, например, классы S t r i n g , I n t e g e r ,
F l o a t , D o u b l e и др.) Поэтому MyThread сохраняет только ссылку на объект
randomArg. Если данное предположение несправедливо, в классе MyThread прихо
дится клонировать объект.
this.data = data.clone();
Метод c l o n e класса RandomClass должен выполнять "глубокое" клонирование,
т.е. копировать все внутренние объекты (простые типы копируются по умолчанию).
Пример создания фонового процесса для класса, который первоначально не под
держивал несколько потоков, показан в листингах 16.13 и 16.14. Класс RSAKey содержит
метод c o m p u t e Key, который предназначен для построения пары из общедоступного и
личного ключей, соответствующих стандарту RSA. Минимальное количество цифр об
щедоступного ключа задается с помощью параметра, передаваемого методу. Построен
ная пара RSA, а также модуль N выводится с помощью S y s t e m , o u t . Исходный код дан
ного примера можно найти по адресу h t t p : / / c o r e w e b p r o g r a m m i n g . com/.
16.4. Создание многопотоковых методов 679
import Java.math.Biglnteger;
n = p.multiply(q);
m = (p.subtract(ONE)).multiply(q.subtract(ONE));
import java.io.*;
/** Пример выполнения в фоновом режиме метода, который
* первоначально предназначался для работы в однопотоковом
* режиме. В обычных условиях выполнение потока команд
* должно быть приостановлено до завершения computeKey.
Л и с т и н г 1 6 . 1 5 . Выходные д а н н ы е ThreadedRSAKey
> j a v a ThreadedRSAKey 50 8
N => 22318033
p u b l i c => 99371593
p r i v a t e => 13439917
N => 80587 805972834 4259805164 31184 4 824160199414 998 4 603 9
p u b l i c => 8214 567 32107 9385034 667 0822324 9107 04 7 4 3113 917 4 81417
p r i v a t e => 54738576754079530157967908359197723401677283881913
Конструкторы
public ThreadO
Использование данного типа конструктора для исходного класса T h r e a d не оп
равдано, поскольку при создании потока будет вызван метод r u n , не содержащий
ни одной команды. Однако конструктор без параметров часто применяется в под
классах класса T h r e a d , где переопределен метод r u n . Выражение new T h r e a d ()
эквивалентно выражению new T h r e a d ( n u l l , n u l l , "Thread-N") , где N автома
тически выбирается системой.
public T h r e a d ( T h r e a d G r o u p g r o u p , R u n n a b l e target)
Данный метод организует поток, в котором выполняется метод r u n объекта
R u n n a b l e . Ссылка на объект передается в составе параметра t a r g e t . Поток поме
щается в указанную группу T h r e a d G r o u p (если метод c h e c k A c c e s s позволяет сде
лать это). Объект T h r e a d G r o u p определяет группу потоков и позволяет управлять
этими потоками как единым целым. Подробнее о группировке потоков рассказыва
ется ниже. Строго говоря, все потоки принадлежат объектам T h r e a d G r o u p . Если
параметр, определяющий группу, не указан, используется группа, к которой принад
лежит текущий поток. Данный конструктор эквивалентен T h r e a d ( g r o u p , t a r g e t ,
"Thread-N").
public T h r e a d ( T h r e a d G r o u p g r o u p , String n a m e )
Этот конструктор создает в указанной группе поток с заданным именем. П р и за
пуске потока вызывается метод r u n класса T h r e a d . Данный конструктор эквива
лентен T h r e a d ( g r o u p , n u l l , n a m e ) .
Константы
public final int MAX_PRIORITY
Данная константа определяет максимальный п р и о р и т е т потока.
p u b l i c final int N O R M _ P R I O R I T Y
Данный приоритет соответствует первому пользовательскому потоку. Последую
щие потоки автоматически получают п р и о р и т е т потока, из которого они были
созданы.
Как правило, в реализациях виртуальной машины Java MAX_PRIORITY равен 10,
NORM_PRIORITY- 5, а MIN_PRIORITY — 1. П р и о р и т е т ы потоков Java отображаются
на п р и о р и т е т ы конкретных операционных систем. Учитывая, что в системе Solaris
определено 2 уровней приоритетов, а в Windows N T только 7 уровней, становится
ясно, что в этих системах п р и о р и т е т ы Java будут представлены по-разному. В Windows
NT два приоритета потоков Java могут отображаться на один п р и о р и т е т операцион
ной системы. Если уровни п р и о р и т е т о в существенно влияют на выполнение про
граммы, следует тщательно тестировать продукт перед тем, как применять его для
решения конкретных задач.
Методы
p u b l i c static int activeCount()
Данный метод возвращает число активных потоков в группе T h r e a d G r o u p (и всех
подгруппах).
p u b l i c v o i d checkAccessO
Данный метод определяет, имеет ли текущий поток право модификации потока.
Метод c h e c k A c c e s s используется в аплетах и приложениях, реализующих
SecurityManager.
p u b l i c v o i d destroyO
Данный метод закрывает поток, не выполняя при этом операции по очистке ресур
сов. Если поток синхронизирован, блокировка продолжает действовать. В JDK 1.2
этот метод не реализован.
public final b o o l e a n i s D a e m o n ( )
Данный метод позволяет определить, выполняется ли поток в режиме демона. Ес
ли активны лишь потоки, выполняемые в режиме демона, Java-программа может
16.5. Методы класса Thread 685
public b o o l e a n i s l n t e r r u p t e d ( )
Данный метод проверяет, установлен ли флаг прерывания потока; при этом со
стояние флага не изменяется. Чтобы сбросить флаг, надо вызвать из метода r u n ,
принадлежащего потоку с установленным флагом, метод i n t e r r u p t e d .
Листинг 16.16-StoppableThread.Java
Конструкторы
public ThreadGroup(String groupName)
Данный конструктор создает именованный объект ThreadGroup, принадлежащий
к той же группе, что и поток, из которого вызывался конструктор.
Методы
public synchronized int activeCount()
Метод a c t i v e C o u n t возвращает число активных потоков, непосредственно либо
опосредованно принадлежащих данной группе на момент вызова метода.
public йпа1 b o o l e a n i s D a e m o n ( )
Метод i s Daemon позволяет определить, имеет ли группа статус демона. Если в та
кой группе нет ни одного потока, она автоматически удаляется.
public s y n c h r o n i z e d v o i d list()
Данный метод выводит информацию обо всех потоках и о подгруппах, содержа
щихся в группе, в S y s t e m , o u t . Метод l i s t удобен при отладке программ.
692 Глава 16. Использование потоков
public final b o o l e a n p a r e n t O f ( T h r e a d G r o u p d e s c e n d a n t )
Метод p a r e n t O f позволяет определить, является ли группа предком (не обяза
тельно непосредственной родительской группой) для указанной группы-потомка.
public final v o i d s e t D a e m o n ( b o o l e a n b e c o m e D a e m o n )
Если родительская группа имеет статус демона, он автоматически передается до
черней группе. Метод s e t Daemon позволяет изменить статус группы.
Листинг 16.17. S h i p S i m u l a t i o n o a v a
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
p u b l i c c l a s s ShipSimulation extends Applet implements Runnable {
p u b l i c void run() {
Ship s;
for(int i=0; i<ships.length; i++) {
s = ships[i];
s.move(); // Изменение расположения судов*
repaint()
}
p u b l i c void p a i n t ( G r a p h i c s g) {
Ship s;
f o r ( i n t i=0; i < s h i p s . l e n g t h ; i++) {
s = ships[i];
g . d r a w ( s ) ; / / Вывод в текущей позиции.
}
}
d
Ш1Ж- ^^Ц)^ Computet
Листинг 1 6 . 1 8 . D r a w C i r c l e s . j a v a
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import j a v a . a w t . e v e n t . * ;
import j a v a . u t i l . V e c t o r ;
/** Аплет, который после щелчка мышью отображает в окне
круг небольшого размера.*/
p u b l i c c l a s s DrawCircles extends Applet {
p r i v a t e Vector c i r c l e s ;
/** После щелчка мьшнью создается объект S i m p l e C i r c l e ,
* включается в состав объекта Vector, а система
* оповещается о том, что необходимо обновить
* содержимое окна (метод r e p a i n t вызывает метод u p d a t e ,
* который очищает экран и вызывает метод p a i n t ) .
V
p r i v a t e c l a s s CircleDrawer extends MouseAdapter {
p u b l i c void mousePressed(MouseEvent event) {
circles.addElement(
16.7. Многопотоковая графика и двойная буферизация 695
Листинг 1 6 . 1 9 . S i m p l e C i r c l e . J a v a
import java.awt.*;
/** Класс, который содержит переменные для хранения
* координат и радиуса, а также метод для рисования (draw)
Преимущества и недостатки
Данный подход реализуется очень просто и вполне применим для простых при
ложений, например для программы, отображающей круги, рассмотренной в качестве
примера. Однако, если в приложении необходимо выводить сложные графические
изображения, использовать этот подход нежелательно, так как полная перерисовка
всех графических данных занимает слишком много времени. Данный способ не под
ходит и для программ, в которых изображение на экране часто изменяется, поскольку
из-за того, что перед перерисовкой экран очищается, будет наблюдаться мерцание.
Преимущества и недостатки
Иногда реализовать данный подход оказывается проще, чем выполнять рисование
непосредственно в теле метода p a i n t , поскольку при этом перемещением управляет
непосредственно компонент. В код контейнера вносятся лишь незначительные изме
нения. Однако в данном случае возникают проблемы с перекрывающимися компо
нентами, кроме того, быстродействие оказывается низким и используются большие
объемы памяти. Создание отдельного объекта C a n v a s для каждого элемента рисунка
требует большого объема ресурсов, а перемещение компонентов не сводится к обыч
ной перерисовке.
сованный фрагмент, достаточно вывести его еще раз в той же позиции, при этом не
обходимо, чтобы различные фрагменты изображения не перекрывались. В листинге
16.20 показан код аплета, который иллюстрирует рассмотренный подход. Аплет по
зволяет создавать прямоугольники и изменять их размеры. Результат выполнения ко
да показан на рис. 16.2.
Листинг 16.20.Rubberband.Java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
Graphics g = getGraphics();
g.setXORMode(Color.lightGray) ;
drawRectangle(g, startX, startY, lastX, lastY);
}
private class RectDrawer extends MouseMotionAdapter {
/** Прямоугольник определяется по координатам точки,
'^ в которой пользователь нажал кнопку мыши, и той
* точки, куда он переместил курсор.
lastX = x;
lastY = y;
13
Click and drag to show rubberbanding
Достоинства и недостатки
Данный подход (непосредственное рисование вместо установки значений пере
менных и вывода изображений в теле метода p a i n t ) хорошо подходит для получения
результатов, используемых в течение ограниченного интервала времени. Как только
метод p a i n t очередной раз получит управление, картинка на экране будет стерта.
Таким способом невозможно создавать изображения, которые должны постоянно
присутствовать в окне программы.
1 6 . 7 . Многопотоковая графика и двойная буферизация 699
Листинг 16.21.Bounce.Java
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
import j a v a . u t i l . V e c t o r ;
/** Перемещение кругов по экрану. Двойная буферизация
* не используется, вследствие чего возникают проблемы
* с перекрывающимися кругами. Метод update переопределен,
* чтобы исключить мерцание.
V
public c l a s s Bounce extends Applet implements Runnable,
ActionListener {
p r i v a t e Vector c i r c l e s ;
700 Глава 16. Использование потоков
repaint 0 ;
}
1 A
Bouncing Circles
• •
iA
• • • • ^ *
J
^ АррЫ tidfted ' ' [3''МуСоМ{ри(в1
Преимущества и недостатки
Реализация данного подхода требует несколько бсльших усилий по сравнению с
предыдущими случаями. Кроме того, фрагменты изображения не должны перекры
ваться. Преимуществом является тот факт, что если необходимо "постоянное" рисо
вание, его можно выполнять достаточно быстро.
Внимание!
Листинг 16.23.DoubleBufferBounce.Java
mm
P e £<i Wm §0 £c(imtnic^o( ii(^
й ^' a .^ ^ iai-**аш
Bouncing Circles
!шшшit CHoodilditiss
1 1
ф %
• •
•
'
%
•
'
фф
•
4^Й»«Г
• • ;n ^jhLk^^^
1
Ш , , v<g^„„
Преимущества и недостатки
Создание внеэкранного изображения и вывод его в окно осуществляются значи
тельно быстрее, чем обычное рисование на экране. Двойная буферизация позволяет
устранить мерцание и дает хорошие результаты в тех случаях, когда необходимо уда
лять старые фрагменты изображения. Однако двойная буферизация реализуется зна
чительно сложнее, чем решения, описанные раньше, и требует большого объема па
мяти для хранения внеэкранного изображения.
708 Глава 16. Использование потоков
import Java.applet.Applet;
import java.awt.*;
Листинг 16.25.Duke.Java
import Java.applet.Applet;
import java.awt.*;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break; // Выход из цикла while.
}
712 Глава 16. Использование потоков
ьч.|'''1й4'Л1'И11|Ц'^|1шша
/ ^
1 4f} Рис. 16.5. Использование потоков для отображения
Applet started. анимационных последовательностей объектов Duke
16.9. Таймеры
Таймеры используются для решения самых разнообразных задач, например для
отображения анимационных последовательностей, запуска и остановки программ по
расписанию и организации тайм-аута при установке сетевых соединений. В предыду
щем разделе был продемонстрирован вывод анимационных изображений с помощью
отдельных потоков. В потоке периодически выполнялись определенные действия,
после чего поток на некоторое время переводился в "спящий" режим. Подобные за
дачи решаются проще при использовании класса j a v a x . s w i n g . T i m e r , который по
зволяет легко организовать цикл, осуществляющий периодическое выполнение тре
буемых действий.
Создание таймера сводится к построению экземпляра класса T i m e r . Конструктору
класса передаются значение интервала времени в миллисекундах и объект
A c t i o n E v e n t , определяющий обработчик событий. После создания таймера он дол
жен быть активизирован с помощью метода s t a r t . Например:
Timer t i m e r = new T i m e r ( p e r i o d , listener);
timer.start() ;
По умолчанию объект T i m e r создает поток, который через интервал времени
(в миллисекундах), заданный с помощью параметра p e r i o d , передает всем обработ
чикам (см. a d d A c t i o n L i s t e n e r ) событие A c t i o n E v e n t . Объект T i m e r может быть
настроен так, что через указанный промежуток времени он сгенерирует только одно
событие, а затем прекратит свою работу. Ч т о б ы перевести T i m e r в такой режим, на
до вызвать метод s e t R e p e a t s ( f a l s e ) . В отличие от обычного объекта T h r e a d , ко
торый не допускает повторного запуска потока после остановки. T i m e r позволяет
перезапустить поток с помощью метода r e s t a r t .
Событие, сгенерированное объектом T i m e r , помещается в очередь событий.
Во время работы программы может возникнуть ситуация, при которой до обработки
первого события T i m e r , содержащегося в очереди, объект сгенерирует еще несколь-
16.9. Таймеры 713
import j a v a . a w t . * ;
import j avax.swing.*;
/** Пример поддержки анимации с применением таймеров.
* Два объекта Dukes используют таймеры с различными
* периодами возникновения событий.
V
p u b l i c c l a s s TimedAnimation extends JApplet {
p r i v a t e s t a t i c f i n a l i n t NUMDUKES = 2;
p r i v a t e TimedDuke[] dukes;
p r i v a t e i n t i , index;
p u b l i c void i n i t O {
dukes = new TimedDuke[NUMDUKES];
setBackground(Color.white);
dukesEO] = new TimedDuke( 1, 100, t h i s ) ;
dukes[1] = new TimedDuke(-1, 500, t h i s ) ;
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
import j avax.swing.*;
tracker.addlmage(images[i] , 0) ;
}
try {
tracker.waitForAll();
} catch (InterruptedException ie) {}
if (!tracker.isErrorAny0) {
loaded = true;
}
}
}
timer = new Timer(msec, this);
}
// Возвращает текущее значение индекса.
public int getlndexO { return index; }
// Поддержка события таймера. Метод actionPerformed
// увеличивает значение индекса массива изображений
/ / и инициирует вывод нового изображения.
Конструктор
в классе T i m e r предусмотрен только один конструктор.
16.10. Резюме
Потоки могут использоваться для решения самых разнообразных задач и иногда
упрощают написание программ. Встречаются ситуации, в которых разбиение про
граммы на нескольких независимо выполняемых частей является более органичным
решением, чем координация различных действий в рамках одной процедуры. В дру
гих случаях использование потоков позволяет повысить эффективность работы про
граммы; примером может служить установление нескольких сетевых соединений.
Следует помнить, что при разработке многопотоковых программ приходится за
трачивать гораздо больше усилий, а отладка их происходит гораздо сложнее по срав
нению с однопотоковыми программами. Поэтому, принимая решение об использова
нии потоков, следует соблюдать осторожность.
При использовании потоков для отображения анимационных последовательно
стей либо для динамического вывода графики могут возникнуть дополнительные
трудности. Для решения подобных задач применяются различные подходы, однако
наиболее универсальным является использование двойной буферизации. При этом
графические операции выполняются над внеэкранным изображением (картой пиксе
лей), которая, в свою очередь, выводится на экран.
Параллельная обработка создает дополнительные преимущества при разработке
программ, предназначенных для поддержки сетевого взаимодействия. В следующей
главе будут рассмотрены различные вопросы сетевого обмена, включая разработку
многопотоковых серверов.
СЕТЕВОЕ
ПРОГРАММИРОВАНИЕ
В ЭТОЙ главе...
С
етевое программирование включает решение двух основных задач: создание
клиентов и создание серверов. Клиентом называется программа, которая устанав
ливает соединение с системой и передает запрос на получение определенных
услуг. Сервер— это программа, которая ожидает обращения от других программ, рабо
тающих в сети (принимает запросы через некоторый порт). Когда клиент передает
серверу запрос на установление соединения, последний обрабатывает запрос и пре
доставляет клиенту определенный набор услуг. Часто сервер работает с несколькими
клиентскими программами, обслуживая их либо по очереди, либо одновременно. Ес
ли вы еще плохо представляете себе различия между клиентом и сервером, запомни
те, что сервер всегда запускается раньше клиента и не должен знать адрес узла, с ко
торым он устанавливает соединение. Клиент запускается после сервера и при уста
новке соединения задает адрес конкретного узла.
На з а м е т к у
О р г а н и з а ц и я о б м е н а с в х о д н ы м и в ы х о д н ы м потоками
В состав класса P r i n t S t r e a m входят методы p r i n t n p r i n t l n , которые позволя
ют передавать по сети переменные простых типов, объекты S t r i n g и строковые
представления других объектов. П р и передаче объекта (ОЬ j e c t ) он преобразуется
в строку путем вызова метода t o S t r i n g соответствующего класса. Эти методы
должны быть знакомы вам, поскольку S y s t e m , o u t , часто используемый в про
граммах, по сути является экземпляром P r i n t S t r e a m . От класса O u t p u t S t r e a m
P r i n t S t r e a m наследует методы w r i t e , позволяющие передавать отдельные бай
товые значения или байтовые массивы.
Класс P r i n t W r i t e r похож на P r i n t S t r e a m ; он содержит те же методы p r i n t и
p r i n t I n . Единственное различие между этщяи методами состоит в том, что в
P r i n t W r i t e r можно организовать запись различных наборов символов Unicode.
Класс Buf f e r e d R e a d e r содержит два часто используемых метода: r e a d и r e a d L i n e .
Метод r e a d возвращает единичный символ, а r e a d L i n e читает целую строку и воз
вращает объект S t r i n g . Оба метода не возвращают управление вызывающей про
грамме до тех пор, пока данные на будут доступны. Метод r e a d L i n e ожидает появ
ления символа перевода строки или EOF (этот символ передается тогда, когда сервер
разрывает соединение), поэтому применять его надо тогда, когда вы уверены, что по
окончании передачи сервер закроет гнездо, либо тогда, когда вы знаете число строк,
которые должен передать сервер. П р и получении EOF метод r e a d L i n e возвращает
значение n u l l .
З а к р ы т и е о б ъ е к т а Socket п о о к о н ч а н и и с е т е в о г о о б м е н а
Когда обмен данными по сети закончен, надо закрыть гнездо с помощью метода c l o s e .
client.close();
Этот метод также закрывает входной и выходной потоки, связанные с гнездом.
Листинг 17.1.NetworkClient.Java
import java.net.*;
import java.io.*;
Класс SocketUtil (листинг 17.2) представляет собой лишь постой интерфейс для
вызова конструкторов Buf feredReader и PrintWriter.
Листинг 17.2.SocketUtil.Java
import java.net.*;
import java.io.*;
Соединение с FTP-сервером
Воспользуемся программой, код которой приведен в листинге 17.3, для соедине
ния с общедоступным FTP-сервером Netscape, который принимает обращения через
порт 21. В данном примере символ ">" представляет собой приглашение для ввода
строки в системе DOS или UNIX.
> Java N e t w o r k C l i e n t T e s t f t p . n e t s c a p e . c o m 21
G e n e r i c Network C l i e n t :
Made c o n n e c t i o n t o f t p . n e t s c a p e . c o m and g o t ' 2 2 0 f t p 2 6 FTP s e r v e r
(UNIX(r) System V R e l e a s e 4 . 0 ) r e a d y . * i n r e s p o n s e
Класс StringTokenizer
Объект, предназначенный ддя разбора текста, создается на базе конкретной стро
ки, после чего для получения лексем используется метод n e x t T o k e n . Набор ограни
чителей, используемый для разделения лексем, задается либо при создании объекта,
либо передается в качестве параметра методу n e x t T o k e n . Данный класс также позво
ляет узнать конкретное число оставшихся лексем ( c o u n t T o k e n s ) либо определить,
осталась ли в составе объекта хотя бы одна лексема ( h a s M o r e T o k e n s ) . Наиболее час
то используемые методы описаны ниже.
Конструкторы
p u b l i c StringTokenizer(String input)
Данный конструктор создает объект разбора указанной строки, используя в каче
стве разделителей пробелы, а также символы табуляции, новой строки и возврата
каретки. В состав возвращаемой лексемы разделители не входят.
1\/1етоды
public String nextToken()
Данный метод возвращает следующую лексему. Если в строке не осталось ни одно
го символа кроме разделителя, n e x t T o k e n генерирует исключение N o S u c h -
ElementException.
public int c o u n t T o k e n s ( )
Метод c o u n t T o k e n s возвращает число лексем, оставшихся в строке. Определение
количества лексем осуществляется исходя из текущего набора разделителей.
public b o o l e a n h a s M o r e T o k e n s ( )
Метод h a s M o r e T o k e n s позволяет определить, осталась ли в строке хотя бы одна
лексема; при этом используется текущий набор разделителей. Большинство при
ложений перед вызовом метода n e x t T o k e n определяют, осталась ли в строке хотя
бы одна лексема, либо помещают вызов n e x t T o k e n в блок t r y / c a t c h , в котором
обрабатывается исключение N o S u c h E l e m e n t E x c e p t i o n , Заметьте, что при вызо
ве h a s M o r e T o k e n s могут возникать побочные эффекты, поскольку этот метод
влияет на значение внутреннего счетчика. Так, если вы вызовете h a s M o r e T o k e n s
с одним набором разделителей, а затем n e x t T o k e n с другим набором, результаты
могут быть непредсказуемыми.
Листинг 17.4.TokTest.Java
import java.util.StringTokenizer;
microsoft
com
-gates
> Java TokTest "if (tok.hasMoreTokens()) {" " (){ . "
if
tok
hasMoreTokens
> t e l n e t a p l . j h u . e d u 25
Trying 1 2 8 . 2 2 0 . 1 0 1 . 1 0 0 . . .
Connected t o a p l c e n M P . a p l . j h u . e d u .
Escape c h a r a c t e r i s ' ' ^ j ' .
220 a p l c e n M P . a p l . j h u . e d u ESMTP S e n d m a i l 8 . 9 . 3 / 8 . 9 . 1 ; S a t , 10 Feb 2001
12:05:42
500 (EST)
expn h a l l
250 Marty Hall <hall(?aplcenMP. apl. jhu. edu>
expn root
250-Tom Vellani <vellani@aplcenMP.apl.jhu.edu>
250 Gary Gafke <gary@aplcenMP.apl.jhu.edu>
quit
221 aplcenMP.apl.jhu.edu closing connection
Connection closed by foreign host.
вращает управление до тех пор, пока на будет получен символ перевода строки. По
этому данный метод нельзя использовать при создании клиента, предназначенного
для проверки адресов. Вместо метода readLine мы должны использовать метод
read, передавая ему в качестве параметра ссылку на байтовый массив, достаточно
большой для того, чтобы вместить ответ сервера, а затем с помощью метода w r i t e
вывести содержимое массива. Код, реализующий указанные действия, приведен в
листинге 17.6, а в листинге 17.7 представлен код вспомогательного класса, предна
значенного для разбора почтового адреса. В частности, этот класс выделяет имя
пользователя и адрес узла.
import j a v a . n e t . * ;
import j a v a . i o . * ;
import j a v a . u t i l . * ;
/** Получение строки в формате "пользователь@узел" и
* разделение ее на компоненты, соответствующие
* пользователю и узлу.
*/
Unix> t e l n e t www.corewebprograimning.com 80
Trying 2 1 6 . 2 4 8 . 1 9 7 . 1 1 2 . . .
Connected t o www.corewebprograinming.com.
Es:?.pe character is ' ^ ] ' .
732 Глава 17. Сетевое программирование
GET / НТТР/1.0
НТТР/1.1 200 ОК
Date: Sat, 10 Feb 2001 18:04:17 GMT
Server: Apache/1.3.3 (Unix) PHP/3.0.11 FrontPage/4.0.4.3
Connection: close
Content-Type: text/html
</HTML>
C o n n e c t i o n c l o s e d by f o r e i g n host.
Листинг 1 7 . 9 . U r i R e t r i e v e r , J a v a
import java.net.*;
import java.io.*;
Листинг 1 7 . 1 0 . U r i R e t r i e v e r . J a v a
import java.util.*;
1 7 . 5 . К л а с с URL
Класс URL упрощает доступ к документам, расположенным на Web-серверах. Ме
тоды данного класса обеспечивают разбор строки, содержащей URL, позволяя извле
кать имя протокола (например, h t t p ) , имя узла (например, j a v a . s u n . c o m ) , номер
порта (например, 80) и имя файла (например, / r e p o r t s / e a r n i n g s . h t m l ) . Класс
URL также предоставляет простой интерфейс для чтения удаленных файлов.
Листинг 1 7 . 1 1 . U r l R e t r i e v e r 2 . J a v a
import java.net.*;
import java.io.*;
/** Получение файла с у д а л е н н о г о у з л а п о с р е д с т в о м к л а с с а URL.
736 Глава 17. Сетевое программирование
public U R L C o n n e c t i o n o p e n C o n n e c t i o n ( )
Данный метод возвращает объект U R L C o n n e c t i o n , который может использовать
ся для получения информации, передаваемой в заголовке ответа и для передачи
данных HTTP-серверу (запрос POST). Подробно запрос POST будет обсуждаться в
главе 19.
Листинг 1 7 . 1 2 . U r l T e s t . J a v a
import java.net.*;
public WebClient0 {
setLayout(new BorderLayout(5, 30));
740 Глава 17. Сетевое программирование
int fontSize = 1 4 ;
Font labelFont =
new Font("Serif", Font.BOLD, fontSize);
Font headingFont =
new Font("SansSerif", Font.BOLD, fontSize+4);
Font textFont =
new Font("Monospaced", Font.BOLD, fontSize-2);
JPanel inputPanel = new JPanelO;
inputPanel.setLayout(new BorderLayout());
JPanel labelPanel = new JPanelO;
labelPanel.setLayout(new GridLayout(4,1));
hostField = new LabeledTextField("Host:", labelFont,
30, textFont);
portField = new LabeledTextField("Port:", labelFont,
"80", 5, textFont);
// Для совместимости с большинством серверов используется
// протокол HTTP 1.0. Применяя средства HTTP 1.1,
// необходимо включить в состав запроса
// поле заголовка Host.
requestLineField =
new LabeledTextField("Request Line:", labelFont,
"GET / HTTP/1.0", 50, textFont);
labelPanel.add(hostField);
labelPanel.add(portField);
labelPanel.add(requestLineField);
JLabel requestHeadersLabel =
new JLabel("Request Headers:");
requestHeadersLabel,setFont(labelFont);
labelPanel.add(requestHeadersLabel);
inputPanel.add(labelPanel, BorderLayout.NORTH);
requestHeadersArea = new JTextArea(5, 80);
requestHeadersArea.setFont(textFont);
JScrollPane headerScrollArea =
new JScrollPane(requestHeadersArea);
inputPanel.add(headerScrollArea, BorderLayout.CENTER);
JPanel buttonPanel = new JPanelO;
submitButton = new JButton("Submit Request");
submitButton.addActionListener(this);
submitButton.setFont(labelFont);
buttonPanel.add(submitButton);
inputPanel.add(buttonPanel, BorderLayout.SOUTH);
add(inputPanel, BorderLayout.NORTH);
JPanel resultPanel = new JPanelO;
resultPanel.setLayout(new BorderLayout());
JLabel resultLabel =
new JLabel("Results", JLabel.CENTER);
resultLabel.setFont(headingFont);
resultPanel.add(resultLabel, BorderLayout.NORTH);
resultArea = new JTextArea();
resultArea.setFont(textFont);
JScrollPane resultScrollArea =
new JScrollPane(resultArea);
resultPanel.add(resultScrollArea, BorderLayout.CENTER);
JPanel interruptPanel = new JPanelO;
interruptButton = new JButton("Interrupt Download");
17.6.WebClJent... 741
interruptButton.addActionListener(this);
interruptButton.setFont(labelFont);
interruptPanel.add(interruptButton);
resultPanel.add(interruptPanel, BorderLayout.SOUTH);
add(resultPanel, BorderLayout.CENTER);
}
resultArea.setText(s);
}
private void getRequestHeaders() {
for(int i=0; i<requestHeaders.length; i++) {
requestHeaders[i] = null;
}
int headerNum = 0;
String header =
requestHeadersArea.getText();
StringTokenizer tok =
new StringTokenizer(header, "\r\n");
while (tok.hasMoreTokens()) {
requestHeaders[headerNum++] = tok.nextToken();
}
}
Листинг 17.14.HttpClient.Java
import java.net.*;
import java.io.*;
import javax.swing.*;
/•• Сетевой клиент, используемый классом WebClient. */
public class HttpClient extends NetworkClient {
private String requestLine;
private String[] requestHeaders;
private JTextArea outputArea;
private Interruptible app;
if (checkHost(host)) {
connect() ;
}
}
protected void handleConnection(Socket uriSocket)
throws lOException {
try {
PrintWriter out = SocketUtil.getWriter(uriSocket);
BufferedReader in = SocketUtil.getReader(uriSocket);
outputArea.setText("") ;
out.println(requestLine);
for(int i=0; i<requestHeaders.length; i++) {
if (requestHeaders[i] == null) {
17.6.WebClient... 743
break;
} else {
out.println(requestHeaders[i] ) ;
}
}
out.println();
String line;
while ((line = in.readLine()) != null &&
!app.islnterrupted()) {
outputArea.append(line + " \ n " ) ;
}
if (app.islnterrupted() ) {
outputArea.append(" Download Interrupted ");
}
} catch(Exception e) {
outputArea.setText("Error: " + e ) ;
}
}
private boolean checkHost(String host) {
try {
InetAddress.getByName(host);
return(true);
} catch(UnknownHostException uhe) {
outputArea.setText("Bogus host: " + host);
return(false);
}
}
}
Листинг 17.15.LabeledTextField.Java
Листинг 17.16.Interruptible.Java
ISESSCBI •а1шГх1
Hetst: jmnr. c o r e s e r v l e t s . сена
Port: (во
ReqoBsiliikeiijJGET / HTTP/I О
Ee^pest Heaiders:
J Jtf^
^
Interrupt Dowttload
С о з д а н и е о б ъ е к т а ServerSocket
Клиентское гнездо предназначено ддя установления взаимодействия с конкрет
ным сервером. В отличие о т клиентского, гнездо сервера ожидает поступления за
просов, поэтому при создании гнезда данного типа задается только порт; адрес уз
ла не указывается.
746 Глава 17. Сетевое программирование
ServerSocket listenSocket =
new S e r v e r S o c k e t (portNuinber) ;
В системе UNIX непривилегированным пользователям доступны номера портов,
превышающие 1023, а поскольку номера в диапазоне 1024-5000 уже используются,
номер порта должен быль больше 5000. Кроме того, необходимо просмотреть со
держимое файла / e t c / s e r v i c e s , чтобы убедиться, что выбранный вами номер
порта не конфликтует с номерами портов, используемых другими службами. Если
вы попытаетесь принимать запросы по порту, который уже используется, будет
сгенерировано исключение l O E x c e p t i o n .
С о з д а н и е о б ъ е к т а Socket п о с р е д с т в о м ServerSocket
Многие серверы поддерживают множественные соединения, продолжая прини
мать запросы до тех пор, пока выполняются определенные условия. Метод
a c c e p t класса S e r v e r S o c k e t ожидает установления соединения, после чего воз
вращает обычный объект S o c k e t .
while(someCondition) {
Socket server = listenSocket.accept();
doSomethingWith(server);
}
Если вы собираетесь обеспечить несколько одновременных соединений, вы долж
ны передавать гнезда, возвращаемые методом a c c e p t , отдельным потокам. В сле
дующем разделе мы рассмотрим программу, в которой поддержка каждого соеди
нения производится в отдельном потоке.
С о з д а н и е в ы х о д н о г о п о т о к а д л я п е р е д а ч и и н ф о р м а ц и и клиенту
Получив объект S o c k e t , его надо использовать приблизительно так же, как и в
клиент-программе, представленной в листинге 17.1. В приведенных ниже фраг
ментах кода входной поток создается раньше, чем выходной, поскольку большин
ство серверов сначала принимают данные от клиента, а затем передают ответ. Вы
можете изменить порядок создания потоков либо отказаться от создания одного
из них, если ваш сервер предназначен только для передачи информации.
Как было сказано при обсуждении клиент-программы, для чтения данных лучше
всего подходит поток Buf f e r e d R e a d e r .
BufferedReader in =
new B u f f e r e d R e a d e r
(new I n p u t S t r e a m R e a d e r ( s e r v e r . g e t l n p u t s t r e a m ( ) ) ) ;
Java также позволяет использовать O b j e c t l n p u t S t r e a m для получения сложных
объектов от других Java-программ. Объект O b j e c t l n p u t S t r e a m , связанный с
гнездом, работает так же, как и подобный объект, связанный с файлом: вам доста
точно вызвать метод r e a d O b j e c t и привести полученный результат к требуемому
типу. Подробно сериализация объектов была рассмотрена в главе 13. Высокоуров
невый интерфейс, использующий механизм сериализации для передачи объектов
по сети, будет обсуждаться в конце данной главы.
17.7. Реализация сервера 747
Листинг 17.17.NetworkServer.Java
import j a v a . n e t . * ;
import j a v a . i o . * ;
/** Заготовка для создания сервера. Для выполнения реальных
* задач надо переопределить метод handleConnection. Код
748 Глава 17. Сетевое программирование
System.out.println
("Generic Network Server: got connection from " +
server .getlnetAddress 0 .getHostName 0 + "\n" +
"with first line '" + in.readLine() + " ' " ) ;
out.println("Generic Network Server");
server.close();
}
/** Возвращает максимальное число соединений, которые
* может установить сервер. Значение О указывает на то,
* что сервер должен работать до тех пор, пока его
* выполнение не будет принудительно завершено.
Листинг 1 7 . 1 8 . N e t w o r k S e r v e r T e s t . J a v a
public c l a s s NetworkServerTest {
public s t a t i c void m a i n ( S t r i n g [ ] args)
i n t p o r t = 8088;
i f ( a r g s . l e n g t h > 0) {
port = Integer.parseint(args[0]);
}
750 Глава 17. Сетевое программирование
Листинг 17.19.EchoSarver.Java
import j a v a . n e t . ^ ;
import j a v a . i o . * ;
import J a v a . u t i l . S t r i n g T o k e n i z e r ;
/** Простой HTTP-сервер, который генерирует Web-страницу,
* содержащую данные, полученные от Web-клиента (обычно
* это броузер). Чтобы использовать данный сервер, его
* надо запустить в системе, задав номер порта (по умолчанию
* 8088). Предположим, что сервер запущен по адресу server.com.
* Затем надо запустить Web-броузер и обратиться с его
* помощью по адресу h t t p : / / s e r v e r . c o m : 8 0 8 8 / w h a t e v e r .
* Web-страница, сгенерированная сервером, содержит данные,
* полученные от броузера. При отладке сервлетов или
* CGI-программ надо задать значение атрибута ACTION
* дескриптора FORM h t t p : / / s e r v e r . c o m : 8 0 8 8 / w h a t e v e r .
* При обращении к серверу для передачи данных может быть
* выбран метод GET или POST.
V
p u b l i c c l a s s EchoServer extends NetworkServer {
p r o t e c t e d i n t maxRequestLines = 50;
p r o t e c t e d S t r i n g serverName = "EchoServer";
/** Номер порта передается посредством параметра командной
* строки. В противном случае используется порт 8088.
V
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
i n t p o r t = 8088;
i f ( a r g s . l e n g t h > 0) {
try {
port = Integer.parseint(args[0] ) ;
} catch(NumberFormatException nfe) {}
}
new EchoServer(port, 0);
}
p u b l i c E c h o S e r v e r ( i n t p o r t , i n t maxConnections) {
s u p e r ( p o r t , maxConnections);
752 Глава 17. Сетевое программирование
listen();
}
/•• Метод handleConnection объекта NetworkServer
* переопределяется. В переопределенном методе
* производится чтение строк символов, переданных
* клиентом. Строки символов сохраняются в массиве,
* а затем помещаются в состав элемента PRE
* HTML-страницы и передаются серверу.
V
public void handleConnection(Socket server)
throws IOException{
System.out.println
(serverName + ": got connection from " +
server.getlnetAddress().getHostName());
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
String[] inputLines = new String[maxRequestLines];
int i;
for (i=0; i<maxRequestLines; i++) {
inputLines[i] = in.readLine();
if (inputLines[i] == null) // Клиент закрыл соединение.
break;
if (inputLines[i] .length () == 0) { // Пустая строка,
if (usingPost(inputLines)) {
readPostData(inputLines, i, in);
i = i + 2;
}
break;
}
}
printHeader(out);
for (int j=0; j<i; j++) {
out.println(inputLines[j]);
}
printTrailer(out);
server.close() ;
}
// Передача HTTP-ответа и заголовка стандартной Web-страницы.
// Протокол HTTP 1.0 используется для обеспечения совместимости
/ / с о всеми клиентами.
private void printHeader(PrintWriter out) {
out.println
("HTTP/1.0 200 OK\r\n" +
"Server: " + serverName + "\r\n" +
"Content-Type: text/html\r\n" +
"\r\n" +
"<HTML>\n" +
"<!DOCTYPE HTML PUBLIC " +
"\"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" +
"<HEAD>\n" +
" <TITLE>" + serverName + " Results</TITLE>\n" +
"</HEAD>\n" +
"\n" +
17.8. Пример простого HTTP-сервера 753
"<BODY BGC0L0R=\"#FDF5E6\">\n" +
"<Н1 ALIGN=\"CENTER\">" + serverName +
" Results</Hl>\n" +
"Here is the request line and request headers\n" +
"sent by your browser:\n" +
"<PRE>");
}
// Вывод окончания Web-страницы.
private void printTrailer(PrintWriter out) {
out.println
("</PRE>\n" +
"</BODY>\n" +
"</HTML>\n");
}
// Большинство клиентов запрашивают Web-страницы методом GET,
/ / в этом случае сервер может выполнять построчное чтение
// заголовка. Однако в HTML-формах часто задается метод
// POST; в этом случае необходимо определить число байтов,
// следующих за стандартным HTTP-заголовком.
мзшм
^^^Bookmi^ Jff', fioto:jhrtp //vww cofewebpfogrammmg com-8088/top/selling/iava/book/'
m
" ^ ^ ^ " W h a f » Belated
EchoServer Results
Here is the request line and request headers sent by your browser:
Листинг 1 7 . 2 0 . T h r e a d e d E c h o S a r v e r . J a v a
import java.net.
import java.io.^
/ * * Многопотоковая в е р с и я E c h o S e r v e r . */
17.8. Пример простого HTTP-сервера 755
this.serverSocket = serverSocket;
Создание RMI-приложения
Для использования средств RMI в приложении вам надо создать четыре класса и
скомпилировать пять компонентов программы. Необходимые классы и действия по
компиляции кратко описаны ниже.
Необходимые классы
Для использования RMI необходимо создать четыре основных класса.
1. И н т е р ф е й с к удаленнолсу объекту. Данный интерфейс используется как кли
ентом, так и сервером.
2. RMI-клиент. Данный клиент выполняет поиск объекта на удаленном сервере,
приводит объект к типу, определяемому интерфейсом, созданным на предыду
щем шаге, а затем обращается к объекту как к локальному. Заметьте, что сете
вое соединение должно поддерживаться все время, пока существует ссылка на
удаленный объект. Когда ссылка на удаленный объект обрабатывается проце-
д)^рой "сборки мусора", соединение автоматически разрывается.
3. Реализация удаленного объекта. Удаленный объект, используемый сервером,
должен реализовывать интерфейс, созданный на первом шаге.
4. RMI-сервер. Данг1ый класс создает экземпляр объекта, построенного на пре
дыдущем шаге, и регистрирует объект, используя конкретный URL.
бует, чтобы на стороне сервера выполнялся каркас. Если и клиент, и сервер ра
ботают на платформе Java 2, задается опция - v l . 2 компилятора r m i c .
3. Запуск RMI-peecTpa. Данное действие выполняется единожды, независимо от
количества удаленных объектов. Текущая версия RMI требует, чтобы реестр
выполнялся в той же системе, что и сервер.
4. Запуск сервера. Сервер запускается на той же машине, что и реестр.
5. Запуск клиента. Клиент может быть запущен на любой машине.
Листинг 17.21.Rem.java
i m p o r t J a v a . r m i . •^;
/•• RMI-клиент непосредственно использует этот интерфейс.
* RMI-сервер создает реальный удаленный объект, который
* реализует этот интерфейс, а затем регистрирует экземпляр
* объекта.
V
public interface Rem extends Remote {
public String getMessageO throws RemoteException;
}
2. RMI-клиент.
Данный класс должен выполнять поиск объекта на удаленном узле, используя
N a m i n g . l o o k u p , приводить объект к требуемому типу и обращаться к нему как
к локальному объекту. В отличие от CORBA, RMI-клиент должен знать адрес уз
ла, на котором расположены распределенные службы. URL задается в формате
rmi ://узел/путь или rmi: //узел:порт/путь. Если номер порта не указан, ис
пользуется порт 1099. Данный процесс может генерировать три исключения:
R e m o t e E x c e p t i o n , N o t B o u n d E x c e p t i o n и M a l f o r m e d U R L E x c e p t i o n . Их об
работку необходимо предусмотреть в блоке t r y / c a t c h . Для обработки
M a l f o r m e d U R L E x c e p t i o n надо импортировать пакет j a v a . n e t . * . Кроме то
го, многие клиенты передают удаленному объекту объекты S e r i a l i z a b l e , по
этому желательно всегда импортировать пакет j a v a . i o . *, даже если в данном
конкретном случае он не используется. П р и м е р RMI-клиента приведен в лис
тинге 17.22.
17.9. RMI: Remote Method Invocation 759
import Java.rmi.*;
import Java.rmi.server.UnicastRemoteObject;
RMI-сервер.
Задача сервера состоит в создании объекта и регистрации его по определенно
му URL. Для регистрации объекта используется метод Naming, r e b i n d (он от
меняет выполненное ранее связывание) или метод N a m i n g . b i n d (если объект
был связан ранее, генерируется исключение A l r e a d y B o u n d E x c e p t i o n ) . Тер
мин "связывание" имеет разные значения в RMI и CORBA. В данном случае
"связывание" означает регистрацию и выполняется не клиентом, а сервером.
В блоке t r y / c a t c h , в котором выполняется связывание, необходимо преду
смотреть обработку исключений R e m o t e E x c e p t i o n и MalformedURL-
E x c e p t i o n . Пример RMI-сервера приведен в листинге 17.24.
Листинг 1 7 . 2 4 . Remlmpl. j a v a
import java.rmi.*;
import java.net.*;
/ * * Сервер с о з д а е т объект Remlmpl (реализующий интерфейс Rem),
* з а т е м р е г и с т р и р у е т е г о под URL Rem.
V
p u b l i c c l a s s RemServer {
public s t a t i c void main(String[] args) {
try {
Remlmpl l o c a l O b j e c t = new R e m l m p l ( ) ;
Naming.rebind("rmi:///Rem", l o c a l O b j e c t ) ;
} catch(RemoteException re) {
System.out.println("RemoteException: " + re);
} c a t c h ( M a l f o r m e d U R L E x c e p t i o n mfe) {
System.out.println("MalformedURLException: " + mfe);
3. Запуск RMI-peecTpa.
Для запуска RMI-реестра используется следующая команда:
Prompt> rmiregistry
В системе UNIX в конце строки можно добавить символ "&", чтобы поддержка
реестра выполнялась как фоновый процесс. В Windows данная команда прини
мает вид s t a r t r m i r e g i s t r y . Вы также можете указать порт, в противном
случае по умолчанию будет принят номер порта 1099.
4. Запуск сервера.
Сервер запускается по следующей команде:
S e r v e г > Java RemServer
Как и при запуске RMI-реестра, в конце строки можно добавить символ "&",
чтобы сервер выполнялся как фоновый процесс. В Windows данная команда
принимает вид s t a r t J a v a R e m S e r v e r .
762 Глава 17. Сетевое программирование
5. Запуск клиента.
Для этого надо задать приведенную ниже команду.
Proinpt> Java RemClient
Here i s a remote message.
У fix)
Определение f (х) предоставляет объект Eva l u a t a b l e (листинг 17.26). Второй
метод, i n t e g r a t e , использует метод прямоугольников для аппроксимации следую
щего интеграла:
stop
J f(x)dx
y^evalObj .evaluate(x) -
stepSiize
x= start x=stop
Evaluatable evalObj) {
double sum = 0.0, current = starts-
while (current <= stop) {
sum += evalObj.evaluate(current);
current += stepSize;
}
return(sum);
}
1. И н т е р ф е й с Remotelntegral.
В листинге 17.27 показан интерфейс, используемый как клиентом, так и сервером.
Листинг 1 7 . 2 7 . R e m o t e l n t e g r a l . J a v a
import java.rmi.*;
2. Клиент Remotelntegral.
В листинге 17.28 показан код RMI-клиента. Он получает объект R e m o t e l n t e g r a l
с указанного узла, а затем использует его для приближенного вычисления инте
грала. Заметьте, что экземпляры E v a l u a t a b l e ( S i n , Cos, Q u a d r a t i c ) помимо
интерфейса E v a l u a t a b l e реализуют интерфейс S e r i a l i z a b l e и, следователь
но, могут передаваться по сети. Классы S i n , Cos и Q u a d r a t i c показаны соответ
ственно в листингах 17.29-17.31. Метод t o S t r i n g каждого из трех классов будет
использован в дальнейшем при создании примера RMI-аплета.
Листинг 1 7 , 2 8 . R e m o t e l n t e g r a l C l i e n t . J a v a
import java.rmi.*;
import java.net.*;
import java.io.*;
/ * * Данный к л а с с выводит р е з у л ь т а т ы ч и с л е н н о г о и н т е г р и р о в а н и я
* с р а з л и ч н о й т о ч н о с т ь ю . Реальные вычисления выполняются
* на удаленной машине, а д р е с которой з а д а е т с я в командной
* строке.
V
Листинг 17.29.Sin.Java
import Java.io.Serializable;
import Java.io.Serializable;
import Java.io.Serializable;
3. Реализация Remotelntegral.
В листинге 17.32 показана реализация интерфейса Remotelntegral. В ней ис
пользуются методы класса Integral.
import j ava.rmi.*;
import Java.rmi.server.UnicastRemoteObject;
4. Сервер Remotelntegral.
В листинге 17.33 показан код сервера, который создает объект Remotelnte
grallmpl и регистрирует его в локальной системе под U R L Remotelntegral.
import java.rmi.*;
import java.net.*;
/** Создает объект Remotelntegrallmpl и регистрирует его под
* именем 'Remotelntegral', так что удаленные клиенты могут
* связываться с ним для получения результатов численного
* интегрирования. Сервер размещается на рабочей станции,
* способной выполнять операции с плавающей точкой с высокой
* скоростью.
V
public class RemotelntegralServer {
public static void main(String[] args) {
try {
Remotelntegrallmpl integral = new Remotelntegrallmpl();
Naming.rebind("rmi:///Remotelntegral", integral);
} catch(RemoteException re) {
System.out.println("RemoteException: " + re) ;
} catch(MalformedURLException mfe) {
System.out.println("MalformedURLException: " + mfe);
}
}
768 Глава 1 7 . Сетевое п р о г р а м м и р о в а н и е
Prompt> Java R e m o t e l n t e g r a l S e r v e r
5. Запуск клиента.
После ввода указанной ниже команды вы получите следующий результат:
Prompt> Java RemotelntegralClient
Approximated with 10 steps:
Integral from 0 to pi of sin(x)=2.0082484079079745
Integral from pi/2 to pi of cos (x)=-1.0010288241427086
Integral from 0 to 5 of x"2=41.5625
Approximated with 100 steps:
Integral from 0 to pi of sin(x)=2.0000822490709877
Integral from pi/2 to pi of cos(x)=-1.000010280911902
17.9. RMI: Remote Method Invocation 769
На з а м е т к у
Листинг 17.34.RemoteIntegralClient2.Java
import java.rmi.*;
import java.net.*;
import java.io.*;
catch(NotBoundException nbe) {
System.out.println("NotBoundException: " + nbe);
catch(MalformedURLException mfe) {
System.out.println("MalformedURLException: " + mfe)
grant {
// rmihost - RMI-реестр и сервер
// webhost - HTTP-сервер для классов заглушки
permission Java.net.SocketPermission
"r^iihost: 1024-65535", "connect";
permission java.net.SocketPermission
"webhost:8 0", "connect";
Prompt> j a v a c RemoteIntegralClient2.Java
Prompt> j a v a c RemotelntegralServer.Java
2. Генерация заглуп1ки клиента и каркаса сервера.
В командной строке надо задать следующее выражение:
Prompt> rmic - v l . 2 Remotelntegrallmpl
3. Размещение файлов на соответствующих узлах.
В табл. 17.1 описано расположение файлов классов. На стороне клиента долж
ны находиться R e m o t e I n t e g r a l C l i e n t 2 , а также классы R e m o t e l n t e g r a l ,
S i n , Cos и Q u a d r a t i c . Поскольку последние три класса являются подклассами
E v a l u a t a b l e , а этот класс не копируется с сервера, E v a l u a t a b l e также дол
жен находиться на клиент-машине. Кроме того, клиенту необходим файл поли
тики r m i p o l i c y . c l i e n t .
На стороне сервера, где создается и регистрируется экземпляр удаленного объ
екта, необходимы классы R e m o t e l n t e g r a l S e r v e r , Remotelntegrallmpl,
R e m o t e l n t e g r a l (дочерний класс) и E v a l u a t a b l e (последние три класса не ко
пируются с HTTP-сервера). Класс I n t e g r a l необходим на сервере, поскольку
статические методы I n t e g e r , sum и I n t e g e r . e v a l u a t e вызываются в
R e m o t e l n t e g r a l l m p l . При регистрации удаленного объекта серверу также тре
буется класс Remote I n t e g r a l Imp 1_S t u b . И наконец, на сервере необходимы
S i n , Cos и Q u a d r a t i c . В этих классах определяют метод e v a u l a t e , объявлен
ный в интерфейсе E v a l u a t a b l e ; они требуются при динамическом связывании
объекта I n t e g r a l . Определение этих классов не передается с клиент-машины.
На HTTP-сервере должен находиться файл заглушки Remote I n t e g r a l -
Imp I S t u b , предназначенный для копирования на клиент-машину. Кроме то
го, на HTTP-сервер следует поместить связанные с I n t e g r a l I m p l классы
R e m o t e l n t e g r a l и E v a l u a t a b l e . Они используются при регистрации удален
ного объекта, так как r m i r e g i s t r y не получает эти файлы от сервера, соз
дающего объект.
1 7 . 9 . R M I : R e m o t e M e t h o d Invocation 773
Quadratic
4. Запуск HTTP-сервера.
Ha НТТР-сервере следует разместить Remote I n t e g r a l S t u b . c l a s s , R e m o t e -
I n t e g e r a l . c l a s s и E v a l u a t a b l e . c l a s s и проверить, что эти файлы дос
тупны с помощью броузера.
5. Запуск RMI-peecxpa.
Запуск RMI-реестра выполняется по следующей команде:
Server> /somedirectory/rmiregistry
Перед запуском r m i r e g i s t r y убедитесь в том, что файлы классов отсутствуют
в каталоге, из которого вы запускаете реестр, а также в том, что на них не ука
зывает переменная окружения CLASS PATH.
Внимание!
6. Запуск сервера.
Для запуска сервера надо задать следующую команду:
Server> J a v a -Djava.rmi.server.codebase=http://webhost/rmi/
RemoteIntegralServer
При этом предполагается, что файл заглушки находится на НТТР-сервере
w e b h o s t в каталоге r m i . Заметьте, что сервер должен запускаться на том же уз
ле, что и r m i r e g l s t r y , но из другого каталога. Если при запуске сервера гене-
774 Глава 1 7 . С е т е в о е п р о г р а м м и р о в а н и е
На з а м е т к у
7. Запуск клиента.
Для того чтобы получить выходные данные, приведенные ниже, надо задать в
командной строке следующее выражение (здесь rmihost— это узел, на кото
ром выполняются rmiregistry и сервер):
Client> Java -DJava.security.policy=rmiclient.policy
RemGteIntegralClient2 rmihost
Approximated with 10 steps:
Integral from 0 to pi of sin(x)=2.0082484079079745
Integral from pi/2 to pi of cos(x)=-1.0010288241427086
Integral from 0 to 5 of x^2=41.5625
Approximated with 100 steps:
Integral from 0 to pi of sin(x)=2.0000822490709877
Integral from pi/2 to pi of cos(x)=-1.000010280911902
Integral from 0 to 5 of x"2=41.665624999999906
Approximated with 1000 steps:
Integral from 0 to pi of sin(x)=2.0000008224672983
Integral from pi/2 to pi of cos (x)=-1.000000102808351
Integral from 0 to 5 of x^2-41.666656249998724
Approximated with 10000 steps:
Integral from 0 to pi of sin(x)=2.00000000822436
Integral from pi/2 to pi of cos(x)=-1.0000000010278831
Integral from 0 to 5 of x"2=41.666666562504055
'Correct' answer using Math library:
Integral from 0 to pi of sin(x)=2.0
Integral from pi/2 to pi of cos(x)=-0.9999999999999999
Integral from 0 to 5 of x"2=41.666666666666664
Пример RMI-annera
Создание аплета, использующего RMI-взаимодействие, намного проще по сравне
нию с созданием аналогичного приложения, поскольку с аплетом всегда связан дис
петчер защиты, управляющий загрузкой удаленных файлов, поэтому RMI-аплету не
нужен RMISecurityManager. С другой стороны, на работу аплета накладывается ряд
ограничений. Так, аплет может устанавливать сетевое соединение только с сервером,
с которого он был загружен, поэтому RMI-реестр, сервер, регистрирующий удален
ные объекты, и HTTP-сервер, с которого аплет копирует файл заглушки, должны рас
полагаться на одном узле.
Раз.мещая аплет на HTTP-сервере, убедитесь, что файлы клиента расположены в
том же каталоге, что и файл класса аплета. Вы также можете расположить JAR-файл в
каталоге аплета и указать его посредством атрибута ARCHIVE дескриптора APPLET.
Подробно о создании JAR-файлов рассказывалось в разделе 7.10.
17.9. RMI: Remote Method Invocation 775
import java.awt.*;
import Java.awt.event.*;
import java.rmi.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
/** Данный класс представляет собой версию RemotelntegralClient,
* выполненную в виде аплета. Аплет обращается к удаленной
* машине для выполнения численного интегрирования.
* Поскольку аплет работает с собственным диспетчером
* компоновки, для загрузки классов заглушки необходимость
* в RMISecurityManager отпадает.
V
public class RemotelntegralApplet extends JApplet
implements ActionListener {
private Evaluatable[] shapes;
private Remotelntegral remotelntegral;
private JLabel result;
private JTextField startlnput, stoplnput, steplnput;
private JComboBox combo;
public void initO {
String host = getCodeBase().getHost();
try {
remotelntegral =
(Remotelntegral)Naming.lookup("rmi://" + host +
"/Remotelntegral");
} catch(RemoteException re) {
reportError("RemoteException: " + re);
} catch(NotBoundException nbe) {
reportError ("NotBoundException: " -i- nbe);
} catch(MalformedURLException mfe) {
reportError("MalformedURLException: " + mfe);
}
Container context = getContentPane();
// Создание раскрывающегося списка.
shapes = new Evaluatable[]{ new Sin(),
new Cos(),
new Quadratic!) };
combo = new JComboBox(shapes);
context.add(combo, BorderLayout.NORTH);
// Ввод входных данных,
startlnput = new JTextField();
stoplnput = new JTextField0;
776 Глава 17. Сетевое программирование
шшалз:^ .:^тщ
J Ffle Edit Vievv Search Go i
Quadratic
i t ^ i,
^ 1
0 0
i^b^i 5 0
iU'-u 1000
b > , ^ < ' 11 f ^?'<<^ъ ^.,.,>,..
Suhmtt Рис. 17.4. Так выглядит аплет, взаимодействующий
с удаленным объектом посредством RMI, в окне броузера
r r r : : i . '::| Netscape 6
17.9. RMI: Remote Method Invocation 777
Броузер Netscape (кроме версии 6) и все версии Internet Explorer без установки
продукта Java Plug-In (см. раздел 9.9) не поддерживают Java 2 и протокол RMI 1.2. Бо
лее того, Internet Explorer без установки дополнительного модуля не поддерживает
даже протокол RMI 1.1. Дополнительный модуль для работы с RMI доступен по адресу
f t p : / / f t p / m i c r o s o f t . c o m / d e v e l o p r / m s d n / u n s u p - e d / . Протокол RMI 1.1 под
держивается в Netscape 4.06 и более поздних версиях.
17.10. Резюме
Механизм гнезд, реализованный в Java, позволяет создавать сетевые клиенты и
серверы, взаимодействующие с сетевыми программами, написанными на любом язы
ке программирования. Процесс создания клиента включает следующие действия: соз
дание гнезда, связывание с гнездом входного и выходного потоков, использование
этих потоков при сетевом взаимодействии и закрытие гнезда. Сервер действует ана
логично, но перед созданием гнезда он ожидает установления соединения. П р и соз
дании как клиента, так и сервера приходится решать задачу разбора строк символов.
В этом существенную помощью может оказать класс S t r i n g T o k e n i z e r . Для под
держки распределенной обработки удобно использовать технологию RMI.
Следующая часть данной книги посвящена созданию программ, выполняющихся
на стороне сервера. В первую очередь мы рассмотрим HTML-формы, с помощью ко
торых создается и н т е р ф е й с для взаимодействия с программами на стороне сервера,
такими как сервлеты и CGI-сценарии. С помощью ф о р м осуществляется взаимодей
ствие с пользователем и передача полученных от него данных на сервер. После этого
мы обсудим Java-сервлеты, которые выполняются на Web-сервере и играют роль по
средников межд)' Web-броузерами или другими HTTP-клиентами и базами данных ли
бо приложениями, также находящимися на стороне сервера. После этого речь пойдет
о технологии JavaSei-\'er Pages (JSP), которая позволяет включать в статические
HTML-страницы динамические фрагменты. Мы также расскажем вам о написании
аплетов, предназначенных для передачи данных HTTP-серверам, расположенным за
брандмауэрами. Кроме того, мы рассмотрим JDBC API, с помощью которого вы може
те передавать SQL-запросы базам данных. И, наконец, вы узнаете о средствах Java
API, предназначенных для обработки XML-файлов.
-Jzj^-j^±
ПРОГРАММЫ,
ВЫПОЛНЯЮЩИЕСЯ
НА СТОРОНЕ
СЕРВЕРА
В ЭТОЙ части...
В ЭТОЙ главе...
элементы, использованные для создания этой формы, будут рассмотрены ниже в этой
главе. Сейчас нас интересуют лишь некоторые особенности данной Web-страницы. Во-
первых, заметьте, что одному из полей редактирования присвоено имя f i r s t N a m e , а
второму— l a s t N a m e . Во-вторых, обратите Внимание! на то, что интерфейсные элемен
ты являются элементами текстового уровня и чтобы добиться требуемого расположе
ния полей редактирования относительно текста, надо включать в состав Web-страницы
дескрипторы, предназначенные для форматирования. И, наконец, примите к сведе
нию, что с формой связан URL h t t p : / / l o c a l h o s t : 8 0 8 8 / S o m e P r o g r a m , по которому
будут передаваться данные, введенные пользователем.
Листинг 1 8 . 1 . GetForm.html
<BODY BGC0L0R="#FDF5E6">
<H2 ALIGN="CENTER">A Sample Form U s i n g GET</H2>
</BODY>
</HTML>
Перед тем как информация, введенная посредством формы, будет впервые передана
на сервер, надо запустить на стороне сервера (в данном случае на локальном компьюте
ре) программу E c h o S e r v e r , которую мы рассмотрели ранее в разделе 17.8. Эта про
грамма представляет собой "мини-сервер" и может оказать существенную помощь при
отладке. Независимо от того, какой каталог и файл указаны в составе URL, E c h o S e r v e r
возвращает клиенту принятую информацию, оформленною в виде Web-страницы. Как
видно из рис. 18.2, когда пользователь введет в первом поле редактирования J o e , а во
втором поле— H a c k e r и щелкнет на кнопке Submit Query, броузер обратится к URL
h t t p : / / l o c a l h o s t : 8 0 8 8 / S o m e P r o g r a m ? f i r s t N a m e = J o e & l a s t N a m e = H a c k e r . В лис
тинге 18.2 представлен код модифицированного документа, в котором вместо метода
GET используется метод POST; внешний вид документа показан на рис. 18.3. Как видно из
рис. 18.4, значения J o e и H a c k e r по-прежнему представляются в формате f i r s t N a m e =
J o e & l a s t N a m e = H a c k e r , но в данном случае эта строка параметров располагается после
пустой строки, разделяющий заголовок и тело Н1ТР-запроса.
18.1. Передача данных с помощью HTML-форм 783
k 4' ^- г ^А ^^ М-^-л аа Ш
•'• 'ч^^у''Вос*1тв<к$ ^ 1осгй«т |h«p//localhosl/'GetFofm html
d
А Sample Form Using GET
1 First name: p o e
1 Last name: JHacker
1 SiAmtt Query |
шшшшшЕяшшшшшшшт
Fie £ ( * V'tew feo CowifMiic^or йф
Si
4 ~i ё __^<
<>loc«*on-|hHp
^. i l //ЬсдХпой
,, | i " Bookmafks -J> ^£ ^
8088/'Somerruyci
"3
EchoSei4'er Results
Here is the request line and request headers sent by your browser:
',^;.»Ф- ОосшигЛОоп*
^^ ::э -2^
Рис. 18.2. HTML-запрос, переданный документом GetForm.html,
отображаемым в броузере Netscape 4.7
784 Глава 18. HTML-формы
<BODY BGC0L0R="#FDF5E6">
<H2 ALIGN="CENTER">A Sample Form Using P0ST</H2>
<FORM ACTION="http://localhost:8088/SomeProgram"
METHOD="POST">
<CENTER>
First name:
<INPUT TYPE="TEXT" NAME="firstName" VALUE="Joe"><BR>
Last name:
<INPUT TYPE="TEXT" NAME="lastName" VALUE="Hacker"><P>
<INPUT TYPE="SUBMIT">
</CENTER>
</FORM>
</BODY>
</HTML>
UsmaPOST -Netscdoe
g o j;jc4T»mu'm-^^fof tieto сжз
ll :P ^^ i -I- ''Ж J IS:
f BiXik-i>afks ^ LcscalJon:jhftp/'/locaihos:t,''PostFofmhtni
Subtnit Query
Оосигпдат* Done
^;^
Рис. 18.3. Внешний вид документа PostForm.html
18.2. Элемент FORM 785
MfirVffiliffflMiEBaMHHHHHHHHHIIIillllllllliiilillllllillli I il [
file £<* ^ie«/v g o £ommurac^tor Лф
EchoSei^ er Results
Here is the request line and request headers sent by your browser:
firstName-Joes lastName-Hacker
^^^
Рис. 18.4. HTML-запрос, переданный документом PostForm.html,
отображаемым в броузере Netscape 4.7
ACTION
Атрибут ACTION определяет URL сервлета или CGI-сценария, предназначенного для
обработки данных, передаваемых формой (например, h t t p : / / c g i . w h i t e h o u s e .
g o v / b i n / s c h e d u l e - f u n d - r a i s e r ) , либо почтового адреса, по которому должна
быть передана эта информация (например, m a i l t o : a u d i t @ i r s . gov). Некоторые
провайдеры не позволяют пользователям размещать на сервере сервлеты и CGI-
программы. В этом случае единственным способом доставки данных, введенных по
средством формы (например, заказы на приобретение продукции), остается переда
ча их по электронной почте. Задавая URL, начинающийся с m a i l t o , необходимо
указывать метод POST (см. описание атрибута METHOD).
METHOD
Атрибут METHOD задает способ передачи данных HTTP-серверу. При использовании
метода GET данные присоединяются через знак вопроса ("?") к URL, связанному с
формой. Пример использования этого метода приведен в разделе 18.1. По умолча
нию броузеры, запрашивая у сервера HTML-страницы, также применяют метод GET.
При использовании метода POST данные передаются в отдельной строке.
Метод GET имеет как преимущества, так и недостатки. Этот метод очень прост, и ес
ли программа, выполняющаяся на стороне сервера, использует метод GET, для ее от
ладки и тестирования не обязательно применять форму, достаточно задать URL,
присоединив к нему требуемые данные. С другой стороны, из-за ограничений, на
кладываемых броузером на размер URL, ограничивается также и объем данных, ко
торые могут быть присоединены к нему. Метод POST свободен от этого недостатка.
Кроме того, большинство броузеров вместе с URL документа отображают также и
присоединенные данные. Это не позволяет использовать метод GET для работы с
конфиденциальными данными там, где экран дисплея виден посторонним.
ENCTYPE
Атрибут ENCTYPE определяет способ кодировки данных, предназначенных для
передачи. По умолчанию используется кодировка a p p l i c a t i o n / x - w w w - f o r m -
u r l e n c o d e d , согласно которой клиент преобразует каждый пробел в символ "-ь", а
любой символ, не являющийся латинской буквой или ц и ф р о й , в трехсимвольную
последовательность, состоящую из знака "%'' и двузначного шестнадцатеричного
числа, представляющего код символа. Знак равенства между именем и значением и
знак "&", которым разделяются пары имя-значение, не кодируются.
Например, на рис. 18.5 показан документ G e t F o r m . h t m l (листинг 18.1), в котором
в первом поле редактирования введеЕ1а строка " M a r t y ( J a v a H a c k e r ? ) " . Как
видно из рис. 18.6, на сервер будет передана последовательность символов
"Marty+%28Java+Hacker%3F%2 9". Пробелы заменены символами "+", 28— это
шестнадцатеричный код левой скобки, 3F— код знака вопроса, а 29 — код правой
скобки.
18.2. Элемент FORM 787
1 I Q Subnj¥5uefy^ J 1
1 ^ Local ««r^net vj
Л1 ШетеА Expfotet
' file Е<Й Vbv f^voftes lods йф
J
EchoSei^er Results
Here is the request Hne and request headers sent by your browser:
ШОопе * ^ l o c ^ rtifdnet
J
Рис. 18.6. HTTP-запрос, переданный Internet Explorer 5.0 при акти
визации формы, показанной на рис. 18.5
<FORM ACTION="http://localhost:8088/SomeProgram"
ENCTyPE="multipart/form-data">
Результаты показаны на рис. 18.7 и 18.8.
Листинг 1 8 . 3 . M u l t i p a r t F o r m . h t m l
a
Using ENCTYPE=^'miiltipiirt/form-data'^
First name: j Joe
Last name: JHacker
Submit Query
30247933410805
Content-Disposition: form-data; name="firstName"
Joe
30247933410805
Content-Disposition: form-data; пагое*"lastName"
Hacker
302 47933 410805 —
Ш",Ч>' ^Ш::.т::.Шл:.:Я:^±
TARGET
Атрибут TARGET используется броузерами, поддерживающими ф р е й м ы . Данный
атрибут позволяет определить, в каком из ф р е й м о в должны отображаться резуль
таты выполнения сервлета или другой программы, обрабатывающей переданные
данные. П о умолчанию результаты выводятся в тот фрейм, где находилась форма,
которая передала запрос.
ONSUBMIT и ONRESET
Данные атрибуты задают JavaScnpt-код, используемый для проверки содержимого
ф о р м ы перед передачей данных серверу или сбросом содержимого интерфейсных
элементов. Если выражение, на которое указывает атрибут ONSUBMIT, возвращает
значение f a l s e , содержимое ф о р м ы не передается на сервер. Это позволяет про
верить с помощью JavaScript-сценариев формат и значение данных, предназна
ченных для передачи на сервер, и оповестить пользователя об ошибке.
ACCEPT и ACCEPT-CHARSET
Данные атрибуты появились только в HTML 4.0. С их помощью определяются
MIME-ТИПЫ (ACCEPT) и кодировка символов (ACCEPT-CHARSET), которые должны
поддерживаться сервлетом или другой программой, обрабатывающей информа
цию. MIME-ТИПЫ, перечисленные в атрибуте ACCEPT, могут также быть использо
ваны клиентом для ограничения типов файлов, доступных пользователю при ко
пировании.
790 Глава 1 8 . H T M L - ф о р м ы
Поля редактирования
Элемент: <INPUT TYPE="TEXT" NAME="..." ...> (закрывающий
дескриптор отсутствует)
Атрибуты: NAME (обязательный), VALUE, SIZE, MAXLENGTH, DISABLED, RE^ШONLY,
ONCHANGE, ONSELECT, ONFOCUS, ONBLUR, ONKEYDOWN, ONKEYPRESS, ONKEYUP
Данный элемент создает поле, предназначенное для редактирования одной стро
ки текста. П р и м е р ы полей редактирования были приведены в листингах 18.1-18.3.
Для работы с фрагментом текста, содержащим несколько строк, используется эле
мент TEXTAREA. Если атрибут TYPE в элементе INPUT не указан, по умолчанию при
нимается тип TEXT, однако при создании HTML-документов рекомендуется явно за
давать тип интерфейсного элемента. След}^ет помнить, что элементы в составе фор
мы размещаются в окне в соответствии с правилами форматирования, поэтому при
создании ф о р м ы следите за тем, чтобы броузер не разместил и н т е р ф е й с н ы й элемент
отдельно от поясняющего текста.
М е т о д и к а профессионалов
NAME
Атрибут NAME идентифицирует поле редактирования. Поскольку данные всегда пе
редаются на сервер в формате гшя= значение, то для поля редактирования, при опре
делении которого не был указан атрибут NAME, пара имя-значение не передается.
VALUE
Значение атрибута VALUE определяет начальное содержимое поля редактирова
ния. П р и активизации ф о р м ы серверу передается текущее содержимое поля, ко
торое формируется в результате действий пользователя. Если на момент передачи
содержимого ф о р м ы поле редактирования пусто, строка параметров имеет сле
дующий вид: прочие_данные8сtext f ieldname^Sinpo4ue_daHHue.
SIZE
Атрибут SIZE задает ширину текстового поля, которая вычисляется исходя из
средней ширины символа, отображаемого определенным шрифтом. Если количе
ство символов превышает ширину элемента, его содержимое сдвигается влево так,
чтобы последний символ строки был виден на экране. Это также может произой
ти, если в состав введенной строки входит много символов, ширина которых пре
вышает среднее значение (например, прописная буква W). Очевидно, что сказан
ное справедливо только для пропорциональных шрифтов, которые по умолчанию
использует для отображения содержимого полей редактирования броузер
Netscape. Internet Explorer использует для этой цели моноширинный шрифт, и та
кое поведение броузера нельзя изменить, даже если поместить элемент INPUT в
состав элемента FONT или CODE.
MAXLENGTH
Атрибут MAXLENGTH задает максимально допустимое число символов в поле редак
тирования. Это значение отличается от числа видимых символов, которое задает
ся с помощью атрибута SIZE.
DISABLED, R E A D O N L Y
Атрибут DISABLED полностью запрещает доступ к полю редактирования, а атри
бут READONLY переводит его в режим "только для чтения". Поле редактирования,
доступ к которому запрещен, не получает фокус ввода ни после щелчка мышью, ни
после нажатия клавиши <ТаЬ>, поэтому его содержимое не может быть изменено.
Кроме того, информация, содержащаяся в запрещенном поле редактирования, не
передается на сервер. Текст, содержащийся в поле, которое находится в режиме
"только для чтения", не может быть изменен, однако такие поля могут получать
фокус ввода и сведения о них включаются в строку параметров, передаваемую на
сервер. Несмотря на то что атрибуты DISABLED и READONLY предусмотрены спе
цификацией HTML 4.0, броузер Netscape 4.x не поддерживает их.
792 Глава 1 8 . H T M L - ф о р м ы
O N C H A N G E , ONSELECT, O N F O C U S , O N B L U R , O N K E Y D O W N ,
ONKEYPRESS и O N K E Y U P
Указанные атрибуты используются только при работе с броузерами, поддерживающи
ми JavaScript. Фрагменты кода, на которые указывают значения данных атрибутов, об
рабатывают события, соответствующие изменению содержимого поля редактирова
ния с переходом на другой элемент, выбору пользователем содержимого текстового
поля, получению и потере фокуса ввода, а также нажатию клавиш на клавиатуре.
Текстовые области
Элемент:<TEXTAREANAME='..." ROWS=xxxCOLS=yyy>... </TEXTAREA>
Атрибуты: NAME (обязательный), ROWS (обязательный), COLS (обязательный), WRAP
(нестандартный), DISABLED, READONLY, ONCHANGE, ONSELECT, ONFOCUS, ONBLUR,
ONKEYDOWN, ONKEYPI^SS, ONKEYUP
Элемент TEXTAREA создает область, позволяющую работать с фрагментом текста,
состоящим из нескольких строк. Внешний вид текстовой области показан на рис. 18.10.
18.3. Управляющие элементы для обработки текста 793
NAME
Данный атрибут определяет имя элемента.
ROWS
Атрибут ROWS задает число строк текста, которые должны отображаться в составе
элемента. Если реальное число строк превысит значение атрибута ROWS, к элемен
ту автоматически добавляется полоса прокрутки.
COLS
Атрибут COLS задает ширину текстовой области. Ш и р и н а элемента вычисляется
исходя из средней ш и р и н ы символа в шрифте, используемой для представления
текста. Если число символов в строке превышает значение атрибута COLS, различ
ные броузеры поступают по-разному. В Netscape отображается горизонтальная по
лоса прокрутки (однако, с помощью атрибута WRAP вы можете изменить поведение
элемента, предусмотренное по умолчанию). В Internet Explorer слова, выходящие
за пределы области, переносятся на новую строку.
WRAP
Атрибут WRAP, специфический для броузера Netscape, определяет действия, кото
рые должны предприниматься, если строка оказывается длиннее, чем ширина об
ласти, указанная с помощью атрибута COLS. Значение OFF, предполагаемое по
умолчанию, запрещает перенос слов. В этом случае, чтобы перейти на новую стро
ку, пользователь должен явно задать символ перевода строки. Значение HARD зада
ет "жесткий" перенос слов; при передаче данных на сервер в соответствующих по
зициях указываются символы перевода строк. Наконец, значение SOFT также раз
решает перенос слов, но при передаче данных на сервер символы перевода строк
находятся только в тех позициях, где их ввел пользователь.
DISABLED, R E A D O N L Y
Атрибут DISABLED полностью запрещает дост)^п к текстовой области, а атрибут
READONLY переводит ее в режим только для чтения. Текстовая область, доступ к
которой запрещен, не получает фокус ввода ни после щелчка мышью, ни после
нажатия клавиши <ТаЬ>, соответственно ее содержимое не может быть изменено.
794 Глава 18. HTML-формы
18.4. Кнопки
Как правило, кнопки в составе форм используются для активизации формы, т.е.
для запуска процедуры передачи данных на сервер и для сброса содержимого элемен
тов формы в состояние, заданное в HTML-документе. Броузеры, поддерживающие
JavaScript, могут также применять кнопки для запуска фрагментов JavaScript-кода.
Чаще всего кнопки создаются с помощью элемента INPUT; при этом атрибут TYPE
может принимать значения SUBMIT, RESET или BUTTON. Кроме того, в HTML 4.0 был
определен элемент BUTTON, но в настоящее время он поддерживается только Internet
Explorer. Этот новый элемент позволяет создавать кнопки с надписями, состоящими
из нескольких строк, выводить на кнопках изображения, выбирать шрифт, а также
1 8 . 4 . Кнопки 795
Внимание!
Кнопка Submit
Элемент: <INPUT TYPE="SUBMIT" ...> (закрывающий дескриптор
отсутствует)
А т р и б у т ы : NAME, VALUE, DISABLED, ONCLICK, ONDBLCLICK, ONFOCUS, ONBLUR
После щелчка на кнопке S u b m i t содержимое ф о р м ы передается сервлету или дру
гой программе на стороне сервера, URL которой задан посредством атрибута ACTION
элемента FORM. Несмотря на то что процедура передачи данных может быть запущена
и другими способами, например с помощью карты изображений, большинство форм
содержат в своем составе хотя бы одну кнопку S u b m i t . Подобно другим интерфейс
ным элементам, внешний вид кнопки S u b m i t зависит от операционной системы, по
этому на различных платформах она выглядит по-разному. На рис. 18.11 показана
кнопка S u b m i t , созданная посредством выражения <INPUT TYPE="SUBMIT"> и ото
бражаемая в системе Windows 98.
Submit Query
Рис. 18.11. Кнопка Submit с надписью, выбираемой по умолчанию
NAME и VALUE
С большинством и н т е р ф е й с н ы х элементов связываются имя и значение, которые
передаются на сервер. Поскольк}^ кнопка S u b m i t предназначена исключительно
для запуска процедуры передачи данных, атрибут NAME может отсутствовать; в
этом случае пара и м я - з н а ч е н и е не будет передаваться обрабатывающей програм
ме. Если имя задано, на сервер передается только имя и значение активизирован
ной кнопки. Надпись на кнопке определяется значением данного элемента.
Задавая значение посредством атрибута VALUE, вы можете изменить надпись на
кнопке. Приведенный ниже фрагмент кода создает поле редактирования и две
кнопки S u b m i t . Внешний вид ф о р м ы показан на рис. 18.12. Если пользователь
щелкнет на первой кнопке, строка параметров, передаваемая на сервер, будет
иметь вид Item=256MB+SIMM&Add=Add+Item+to+Cart.
<CENTER>
Item:
<INPUT TYPE="TEXT" NAME="Item" VALUE="256MB SIMM"><BR>
<INPUT TYPE="SUBMIT" NAME="Add"
VALUE="Add Item to Cart">
<INPUT TyPE="SUBMIT" NAME="Delete"
VALUE="Delete Item from Cart">
</CENTER>
796 Глава 18. HTML-формы
DISABLED
Атрибут DISABLED запрещает доступ к кнопке. Такая кнопка не может пол)^чать
фокус ввода, и ее имя и значение не передаются на сервер. JavaScript-сценарий,
содержащийся на Web-странице, может динамически изменять данный атрибут.
Несмотря на т о что DISABLED предусмотрен спецификацией HTML 4.0, броузер
Netscape 4.x не поддерживает данный атрибут.
ONCLICK, ONDBLCLICK, O N F O C U S и O N B L U R
Указанные атрибуты используются только при работе с броузерами, которые под
держивают JavaScript. Фрагменты кода, на которые указывают атрибуты ONCLICK и
ONDBLCLICK, выполняются при активизации кнопки. Код, соответств)тощиР1 атрибу
ту ONFOCUS, выполняется при получении кнопкой фокуса ввода, а код, определяе
мый значением атрибута ONBLUR, — при потере фокуса. Если фрагмент кода, связан
ный с кнопкой, возвращает значение f a l s e , передача данных не происходит. Имена
HTML-атрибутов не зависят от регистра символов, поэтому в реальных док)'ментах
они обычно обозначаются как o n C l i c k , o n D b l C l i c k , o n F o c u s и o n B l u r .
Листинг 1 8 . 4 . B u t t o n E l e m e n t . h t m l
<BUTTON TYPE="SUBMIT">Multi-line<BR>label</BUTTON>
<P>
<BUTTON TYPE="SUBMIT">
<B>Label</B> w i t h < I > f o n t < / I > c h a n g e s .
</BUTTON>
<P>
<BUTTON TYPE="SUBMIT">
<IMG S R C = " i m a g e s / J a v a - L o g o . g i f " WIDTH=110 HEIGHT=101
ALIGN="LEFT" ALT="Java Cup Logo">
LabeKBIO^with image
</BUTTON>
</CENTER>
</FORM>
</BODY>
</HTML>
fcl^я.llu^l^ьg;Яi^JЩ|^^P^ДJfw.'!';fЯ^ BMK.rnlxfl
' EHe m Ytew Favorites iool* ЙФ B l
J
The BUTTON Element
1 MuttHme
[| Smgte-line Label | label j
1 i ^УЛМ
J
Щ'&опб ifJMyCoft
Кнопка Reset
Элемент: <INPUT TYPE="RESET" ...> (закрывающий дескриптор
отсутствует)
Атрибуты: VALUE, NAME, DISABLED, ONCLICK, ONDBLCLICK, ONFOCUS, ONBLUR
Кнопка R e s e t предназначена для сброса содержимого ф о р м ы в состояние, опре
деляемое атрибутами VALUE элементов. Значение кнопки R e s e t никогда не передает
ся на сервер.
798 Глава 18. HTML-формы
VALUE
Атрибут VALUE определяет надпись на кнопке. По умолчанию отображается стро
ка "Reset".
NAME
Поскольку содержимое кнопки Reset не передается на сервер, атрибут NAME, как
правило, не указывается. Однако в документах, содержащих JavaScript-коды, атри
бут NAME позволяет JavaScript-сценарию ссылаться на данную кнопку.
DISABLED
Данный атрибут позволяет запретить доступ к кнопке. Запрещенная кнопка не по
лучает фокус ввода. JavaScript-сценарий, содержащийся на Web-странице, может
динамически изменять данный атрибут. Несмотря на то что атрибут DISABLED
определен спецификацией HTML 4.0, броузер Netscape 4.x не поддерживает его.
Кнопки JavaScript
Элемент: <INPUT TYPE="BUTTON" ...> (закрывающий дескриптор
отсутствует)
А т р и б у т ы : NAME, VALUE, DISABLED, ONCLICK, ONDBLCLICK, ONFOCUS, ONBLUR
Элемент INPUT типа BUTTON распознается только броузерами, поддерживающими
JavaScript. Данный элемент создает кнопку, которая выглядит подобно кнопкам Submit
и Reset и позволяет связывать фрагменты кода с атрибутами ONCLICK, ONDBLCLICK,
ONFOCUS и ONBLUR. Имя и значение, связанные с такой кнопкой, входят в состав дан
ных, передаваемых на сервер. С кнопкой может быть связан любой фрагмент JavaScript-
18.5. Флажки и переключатели опций 799
кода, но обычно этот код используется для проверки формата данных, содержащихся в
составе интерфейсных элементов. В приведенном ниже примере создается кнопка, при
активизации которой вызывается JavaScript-функция v a l i d a t e Form.
<INPUT TYPE="BUTTON" VALUE="Check Values"
onClick="validateForm{)">
Флажки опций
Элемент: <INPUT TYPE="CHECKBOX" NAME="..." ...>
(закрывающий дескриптор отсутствует)
Атрибуты: NAME (обязательный), VALUE, CHECKED, DISABLED, READONLY, ONCLICK,
ONFOCUS, ONBLUR
Значение, связанное с флажком опции, созданным с помощью элемента INPUT
данного типа, передается на сервер только в том случае, если флажок установлен.
Следующий фрагмент кода создает флажок опции, показанный на рис. 18.14.
<Р>
<INPUT TYPE="CHECKBOX" NAME="noEmail" CHECKED>
Check here if you do <I>not</I> want to
get our email newsletter
М е т о д и к а профессионалов
NAME
Данный атрибут задает имя, которое при активизации ф о р м ы передается на сер
вер. Имена стандартных флажков опций должны обязательно присутствовать, но
если элемент предназначен только для взаимодействия с JavaScript-сценарием, ат
рибут NAME может отсутствовать.
VALUE
Данный атрибу'т указывать не обязательно. П о умолчанию принимается значение
VALUE, равное on. Как было сказано выше, имя и значение передаются на сервер
только в том случае, если флажок установлен. В предыдущем примере ф о р м а пере
дает пару n o E m a i l = o n , но если пользователь перед активизацией ф о р м ы сбросит
флажок опции, эти данные не будут отображаться в строке параметров. Поэтому
сервлеты или CGI-программы, анализирующие информацию, переданную клиен
том, должны лишь проверять факт наличия имени элемента указанного типа; зна
чение можно не рассматривать.
CHECKED
Если указан атрибут CHECKED, то при загрузке Web-страницы устанавливается соот
ветствующий флажок опции. В противном случае он отображается сброшенным.
DISABLED, READONLY
Атриб)^^ DISABLED запрещает доступ к элементу, а атрибут READONLY переводит
его в режим только для чтения. Несмотря на то что атрибуты DISABLED и
READONLY определены в спецификации HTML 4.0, броузер Netscape 4.x не под
держивает их.
ONCLICK, O N F O C U S и O N B L U R
Данные атрибуты определяют фрагменты JavaScript-кода, обрабатывающие щел
чок мышью на элементе, получение и потерю фокуса ввода.
Переключатели опций
Элемент: <INPUT TYPE="RADIO" NAME="..." VALUE="..." ...>
(закрывающий дескриптор отсутствует)
Атрибуты: NAME (обязательный), VALUE (обязательный), CHECKED, DISABLED,
READONLY, ONCLICK, ONFOCUS, ONBLUR
Переключатели опций отличаются от флажков тем, что в каждый момент времени
в группе может быть выбран только один элемент. К группе относятся все элементы
1 8 . 5 . Ф л а ж к и и переключатели опций 801
NAME
В отличие от большинства других элементов, одно и то же имя присваивается не
скольким переключателям опций. Элементы с одним именем объединяются в логи-
ческ)то группу. Заметьте, что значения атрибутов зависят от регистра символов, по
этому два переключателя, описанные ниже, будут принадлежать к разным группам.
<INPUT TYPE="RADIO" NAME="Foo" VALUE="Valuel">
<INPUT TYPE="RADIO" NAME="FOO" VALUE="Value2">
Внимание!
VALUE
Значение атрибута VALUE вместе со значением NAME передается на сервер в соста
ве строки параметров. Атрибут VALUE не влияет на внешний вид переключателя.
802 Глава 18. HTML-формы
CHECKED
Переключатель, для которого задан атрибут CHECKED, при загрузке Web-страницы
отображается как выбранный. Остальные переключатели в группе считаются не
выбранными.
DISABLED, R E A D O N L Y
Атрибут DISABLED запрещает доступ к элементу, а атрибут READONLY переводит
его в режим "только для чтения". Несмотря на то что DISABLED и READONLY опре
делены в спецификации HTML 4.0, броузер Netscape 4.x не поддерживает их.
ONCLICK, O N F O C U S и O N B L U R
Данные атрибуты определяют фрагменты JavaScript-кода, обрабатывающие щел
чок мышью на элементе, получение и потерю фокуса ввода.
NAME
Атрибут NAME задает имя элемента, передаваемое сервлету или CGI-программе.
18.6. Раскрывающиеся списки и окна списков 803
SIZE
Атрибут SIZE указывает число видимых строк. Если данный атрибут задан, ото
бражается окно списка. Если не указаны ни SIZE, ни MULTIPLE, элемент SELECT
представляется в виде раскрывающегося списка.
MULTIPLE
Атрибут MULTIPLE указывает на то, что пользователь может выбирать сразу не
сколько пунктов списка. Если данный атрибут отсутствует, разрешается выбирать
только один пункт.
DISABLED
Атрибут DISABLED запрещает доступ к списку. Несмотря на то что атрибут
DISABLED определен в спецификации HTML 4.0, броузер Netscape 4.x не поддер
живает его.
ONCLICK, O N F O C U S , O N B L U R и O N C H A N G E
Эти нестандартные атрибуты используются при работе с броузерами, поддержи
вающими JavaScript. О н и определяют фрагменты JavaScript-кода, которые выпол
няются после щелчка мышью на пункте списка, при получении и потере фокуса
ввода, а также при изменении выбора с последующей потерей фокуса.
SELECTED
Если в составе дескриптора <OPTION> есть атрибут SELECTED, это означает, что
данный элемент должен автоматически выбираться при загрузке Web-страницы.
VALUE
Атрибут VALUE определяет значение, передаваемое серверу вместе с именем эле
мента SELECT. Это значение не совпадает с текстом пункта. Текст пункта задается
отдельно после дескриптора <OPTION>.
DISABLED
Данный атрибут позволяет запретить доступ к пункту списка. Несмотря на то что
данный атрибут определен в спецификации HTML 4.0, броузер Netscape 4.x не
поддерживает его.
В приведенном ниже примере создается элемент SELECT, пунктами которого яв
ляются названия языков программирования. Поскольку в дескрипторе <SELECT> от
сутствуют атриб)ты SIZE и MULTIPLE, данный элемент отображается как раскры
вающийся список. На рис. 18.16 и 18.17 показан внешний вид элемента сразу после за
грузки Web-страницы и после щелчка мышью на кнопке, расположенной в правой
804 Глава 18. HTML-формы
Совет
NAME
Атрибут NAME идентифицирует поле редактирования, содержащееся в составе
элемента.
VALUE
Из соображений безопасности этот атрибут игнорируется. Имя файла может вве
сти только пользователь.
SIZE и M A X L E N G T H
Атрибуты SIZE и MAXLENGTH используются точно так же, как и одноименные ат
рибуты поля редактирования. Атрибут SIZE определяет число видимых символов,
а атрибут MAXLENGTH — максимальную длину строки.
ACCEPT
Значением атрибута ACCEPT является список MIME-типов. С помощью данного
атриб)а^а можно ограничить список дост)^пных имен файлов, однако его поддер
живают не все броузеры.
806 Глава 18. HTML-формы
DISABLED, READONLY
Эти атриб)а'ы позволяют запретить доступ к элементу или перевести его в режим
только для чтения. Несмотря на то что атрибуты DISABLED и READONLY включены
в состав спецификации HTML 4.0, броузер Netscape 4.x не поддерживает их.
Enter datafilebelow:
Browse... Рис. 18.19. Внешний вид элемента
копирования файлов
Lookr*:] _jWINDOVv/S
й bmdlog.Ul .'j^CDPLuYEREXE
£] Bubbles bmp
SiCALCEXE 5? C\^ne\ Screen Sav(
^ cap_pi.ini *VCHARMAPEXE
^ Carved Stone.bmp JC] Circles.bmp
^£pcd32exe ^CLEANMGREXE
Li J 11
I File name: jcdpiaver in, UP&n
Рис. 18.20. Окно выбора файла, которое
I F3es 0} type jAP "^ilei r ' l •ц
отображается при активизации кнопки Browse
NAME
Атрибут NAME идентифицирует элемент в составе формы, и его значение переда
ется на сервер.
SRC
Атрибут SRC определяет URL изображения.
ALIGN
Атрибут ALIGN может принимать те же значения (ТОР, MIDDLE, BOTTOM, LEFT,
RIGHT; по умолчанию— BOTTOM) и используется так же, как и атрибут ALIGN эле
мента IMG.
DISABLED
Данный атрибут позволяет запретить доступ к карте изображения. Несмотря на то
что атрибут DISABLED предусмотрен спецификацией HTML 4.x, броузер Netscape
4.x не поддерживает его.
В листинге 18.5 представлен код простого примера, демонстрирующего использо
вание карты изображений. В качестве значения атрибута ACTION формы указан URL
программы EchoServer, рассмотренной в разделе 17.8. На рис. 18.21 показано ис
ходное состояние док}^мента, а на рис. 18.22 — содержимое окна броузера после щелч
ка мышью на изображении.
808 Глава 18. HTML-формы
Листинг 1 8 . 5 . ImageMap.html
<BODY>
<H1 ALIGN="CENTER">The IMAGE Input Control</Hl>
Which island is Java? Click and see if you are correct.
<FORM ACTION="http://localhost:8088/GeographyTester">
<INPUT TYPE="IMAGE" NAME="map" SRC="images/indonesia.gif">
</FORM>
</BODY>
</HTML>
!^1fri-frailffMiT^I'IVIIIill>'ii'J4'.!''!l-MHHHHHHHHHHHHH^ I
EchoServ'er Results
Here IS the request line and request headers sent by your browser;
^
g j Done * ^ locd ЫитЫ
Рис. 18.22. После щелчка мышью в точке (305, 280) содержимое формы передается на сервер.
В состав строки параметров включается последовательность символов map.x=305&map.y=280
Листинг 1 8 . 6 . I s M a p . h t m l
</HEAD>
<BODY>
</BODY>
</HTML>
Mi.!iHi'i!ii.fjiiM",MamMi
fie £,* View go СотгшпкяШ» МФ
4: ->' -л A^W^^'t%'m'
The ISMAP Attribute
Select a pin:
GET / C h i p T e s t e r ? 2 7 1 , 1 8 4 HTTP/1.0
Connect-ion: Keep-Alive
User-Agent: M o z i l l a / 4 . 7 [en] (¥in98; U)
Host: localhost:8088
Accept: iinage/gif, image/x-xbitinap, image/jpeg, image/pjpeg, imat
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
1^ШВШШШВБШЕ |»ипй|||шша
вааг^гяш
- j
Grouping Controls in Internet Explorer
• Group One ' ' ' ; ~- - -
•Field lA. h e l d A
iField IB: JField В
iFieldlCIFieldC
'' Ог01ф Two ;
Field 2A: Held A
Field 2B: jField В
Field 2C [Field С
J Рис. 18.25. FIELDSET позволяет объединять
J:^ Щ СощиЛе!
интерфейсные элементы в группы
ALIGN
Атрибут ALIGN управляет расположением текстовой метки. Значениями данного
атрибута могут быть ТОР (по умолчанию), BOTTOM, LEFT и RIGHT. На рис. 18.25 по
казаны две группы и н т е р ф е й с н ы х элементов. В одной из них принимается распо
ложение метки по умолчанию, в другой задан атрибут ALIGN="RIGHT". В настоя
щее время для управления выравниванием рекомендуется использовать листы
стилей. П р и этом внесенные изменения могут распространяться на различные
части документа.
Внимание!
18.12. Резюме
HTML-формы создаются на базе элемента FORM, в состав которого включаются
элементы INPUT, предназначенные для получения данных. Атрибут ACTION дескрип
тора <FORM> задает URL программы на стороне сервера, предназначенной для обра
ботки данных. С каждым из элементов INPUT связывает имя и значение. Имя указыва
ется в составе HTML-документа, а значение либо задается с помощью HTML-кода, ли
бо формируется в результате действий пользователя. Пары имя-значение передаются
серверу. При этом они либо присоединяются к URL (в случае запроса GET), либо по
мещаются в отдельную строку (в случае запроса POST).
В этой главе мы рассмотрели вопросы сбора данных. Однако основную работу по
решению задачи, поставленной перед системой, выполняет программа обработки.
Обсуждению обрабатывающих программ на стороне сервера посвящены две следую
щие главы.
JAVA НА СТОРОНЕ
СЕРВЕРА: СЕРВЛЕТЫ
В ЭТОЙ главе...
Поддержка сеанса.
J~y\ZJ^3J
Эффективность
в традиционных CGI-программах для обработки каждого запроса запускается новый
процесс. Если объем вычислений, выполняемый программой, невелик, то время, необ
ходимое для выполнения вспомогательных операций, связанных с запуском и поддерж
кой нового процесса, мог)^' превышать время работы самой программы. При использо
вании сервлетов виртуальная машина Java запускает каждый сервлет в виде "легковес
ного" потока. Для традиционных CGI-программ при одновременном получении N за
просов в память загр)окается N копий программы. Для сервлетов в этом сл)^ае органи-
1 9 . 1 . Преимущества сервлетов... 819
зуется N потоков, но все они используют одну копию класса сервлета. По окончании об
работки запроса CGI-программой процесс завершается. Это затрудняет выполнение
вычислений, связанных с несколькими последовательными запросами к базе данных, и
других действий, предполагающих наличия постоянно доступного набора данных. По
сле окончания обработки запроса сервлет остается в памяти, поэтому может хранить
любые данные в промежутках времени между запросами клиента.
Простота использования
Сервлеты предоставляют мощные средства, позволяющие выполнять автоматиче
ский разбор и декодирование данных, передаваемых HTML-формами, обрабатывать
cookie, поддерживать состояние сеанса и выполнять другие действия, связанные с об
служиванием запросов. Кроме того, если разработчик знает Java, зачем ему изучать
также язык Perl? Если вы согласны, что Java-технология позволяет создавать более на
дежный код, допускающий повторное использование, стоит ли возвращаться к C++
для написания программ на стороне сервера?
Богатые возможности
Сервлеты предоставляют ряд возможностей, которые трудно, а иногда и невоз
можно реализовать в обычных CGI-программах. Так, например, сервлеты могут непо
средственно взаимодействовать с Web-сервером. Для CGI-программ это возможно
только при условии использования API сервера. Взаимодействие с Web-сервером уп
рощает преобразование относительных URL в абсолютные и выполнение других за
дач, связанных с обработкой заголовка запроса. Различные сервлеты могут использо
вать общий набор данных, что позволяет организовать пул соединений с базой. Серв
леты могут хранить данные между запросами, что упрощает поддержку сеанса и дает
возможность обеспечить кэширование результатов предыдущих вычислений.
Переносимость
Сервлеты реализуются на языке Java и используют стандартные наборы APL По
этому сервлет, написанный, например, для работы с iPlanet Enterprise Sei^ver, может
практически без изменений использоваться совместно с Apache, Microsoft Internet In
formation Server (IIS), IBM WebSphere, StarNine WebStar и другими серверами. Реаль
но сервлеты могут работать практически с каждым из современных Web-серверов (в
некоторых продуктах для этой цели необходимо использовать дополнительные моду
ли). Набор средств для работы с сервлетами включен в состав Java 2 Platform, Enter
prise Edition (J2EE; см. h t t p : / / j a v a . s u n . c o m / j 2 e e / ) , благодаря чему задача под
держки сервлетов в корпоративных средах существенно упрощается.
Защита
Один из основных недостатков, снижающих безопасность традиционных CGI-
программ, связан с тем, что эти программы выполняются непосредственно в оболоч
ках операционных систем. Поэтому разработчик, использующий CGI, должен осо-
820 Глава 19. Java на стороне сервера: сервлеты
Низкая стоимость
в настоящее время существует множество недорогих и даже бесплатных Web-серверов,
обеспечивающих работу небольших Web-узлов. При наличии Web-сервера можно обеспе
чить выполнение сервлетов, не затрачивая при этом больших усилий. В отличие от серв-
летов, для работы CGI-программ часто требуются дорогостоящие пакеты.
• Apache Tomcat
Пакет Tomcat реализует спецификацию Java Sei-vlet 2.2 и может либо использо
ваться как независимый сервер для тестирования сервлетов, либо быть интег
рирован в состав сервера Apache. В настоящее время существуют версии данно
го продукта практически для любой операционной системы, поддерживающей
платформу Java 2. Подробную информацию об Apache Tomcat вы найдете по
адресу h t t p : / / J a k a r t a . a p a c h e . o r g / t o m c a t / .
• Allaire JRun
J R u n представляет собой продукт с поддержкой Java Sei-vlet 2.2 и JSP 1.1,
встраиваемый в состав серверов Netscape Enterprise или FastTrack, IIS, Micro
soft Personal Web Server, Apache, O'Reilly WebSite и StarNine WebStar. Он хоро
шо подходит для разработки программ, но не годится для их доставки. Под
робную и н ф о р м а ц и ю об Allaire J R u n вы найдете по адресу h t t p : / / w w w .
a l l a i r e . com/products/j run/.
• ServletExec
ServletExec поддерживает спецификации Java SeiMet 2.2 и JSP 1.1 и может
встраиваться в популярные Web-серверы, предназначенные для работы в сис
темах Solaris, Windows, MacOS, HP-UX и Linux. Д а н н ы й продукт можно скопи
ровать и использовать бесплатно, однако для работы некоторыми дополни
тельными средствами и утилитами администрирования необходимо приобре
сти лицензию. Подробная информация находится по адресу h t t p : / / w w w .
servletexec.com/.
• LiteWebServer
Продукт LiteWebSei~ver (LWS) представляет собой свободно распространяемый
Web-сервер, разработанный Gefion Software на базе Tomcat. Он поддерживает
Java Sei~vlet 2.2 и JSP 1.1. Gefion Software также предлагает дополнительный
модуль под названием WAICooIRunner, который реализует возможности Servlet
2.2 и JSP 1.1 на серверах Netscape FastTrack и Enterprise. Дополнительная ин
формация находится по адресу h t t p : //www. g e f i o n s o f t w a r e . com/.
• Caucho Resin
Resin представляет собой средство поддержки сервлетов и JSP, соответствую
щее спецификации Java SeiMet 2.2 и JSP 1.1. Этот продукт также обеспечивает
уравновешивание нагрузки. Caucho Resin можно бесплатно использовать для
разработки и некоммерческой доставки программ. И н ф о р м а ц и я о данном про
дукте находится по адресу h t t p : //www. c a u c h o . c o m / p r o d u c t s / r e s i n / .
822 Глава 19. Java на стороне сервера: сервлеты
• http://java.sun.com/products/jsp/download.htinl
По данному адресу можно найти и скопировать на локальный компьютер доку
ментацию на 2.1/1.0 API или 2 . 2 / 1 . 1 API. П р и этом необходимо скопировать
весь пакет, а затем извлечь из него требуемые документы.
• http://java.sun.eom/products/servlet/2.2/javadoc/
На этом узле вы можете просматривать в интерактивном режиме документа
цию на Java Servlet 2.2 и JSP 1.1.
• http://www.java.sun.com/j2ee/j2sdkee/techdocs/api/
По данному адресу находится полный набор документов, 1!чи._;мвс-::"Лц;1А /J. i Java 2
Platform, Enterprise Edition (J2EE), включающий пакеты Servlet 2.2 и JSP 1.1.
Настройка сервера
Перед запуском сервера надо установить ряд его характеристик, например задать
порт, по которому он должен ожидать обращения, указать каталоги для поиска
HTML-файлов и т.д. Процедура настройки различается для разных серверов и должна
быть подробно описана в документации.
Tomcar 3
• instalLdir/webapps/ROOT/WEB-INF/classes
Стандартное расположение классов сервлетов. Все серверы, поддерживающие
Servlet 2.2 и JSP 1.1, содержат инсталляционный каталог, путь к которому выгля
дит приблизительно так: . . . / W E B - I N F / c l a s s e s . Например, для Allaire JRun он
имеет вид i n s t a l l _ d i r / s e r v e r s / d e f a u l t / d e f a u l t - a p p / W E B - I N F / c l a s s e s .
• install_dir/lib
Расположение JAR-файлOB с кодами классов.
• instalLdir/webapps/ROOT
Расположение HTML-файлов, изображений и JSP. Каталог подобного назначения
также существует во всех серверах с поддержкой Sei-vlet 2.2 и JSP 1.1. Например,
Allaire J R u n использует для этой цели каталог i n s t a l l d i г / s e r v e r s /
default/default-app/.
JSWDK 1.0.1
• install_dir/webpages/WEB-INF/servlets
Стандартное расположение классов сервлетов.
824 Глава 19. Java на стороне сервера: сервлеты
• install_dir/lib
Расположение JAR-файлов с кодами классов,
• install_dir/webpages
Расположение HTML-файлов, изображений и JSP.
Обращения к сервлетам
Большинство серверов позволяет регистрировать имена сервлетов, поэтому обра
щаться к ним можно в форме h t t p : //узел/путь/имя. Конкретные особенности вызова
сервлетов подробно описаны в документации на сервер. Сутцествует универсальный
способ обращения к сервлетам, при котором URL сервлета задается в виде
\\Х,Х,^\ //узел/s^TV^Q'L/имя_сервлвта. Обратите внимание, что в данном URL применя
ется имя s e r v l e t (без буквы " s " в конце), несмотря на то, что реальный каталог обыч
но называется s e r v l e t s и даже может иметь другое имя, например c l a s s e s или l i b .
В настоящее время по умолчанию используются два варианта URL. В первом из
них в состав URL входит имя пакета, в котором находится сервлет. Сервлеты поме
щаются в пакеты для того, чтобы избежать возникновения конфликтов имен. В этом
случае URL имеет вид htt'p: //узел/servlet/имя_пакета.имя_сервлета. Многие со
временные Web-серверы позволяют определять Web-приложения — наборы сервле
тов и JSP (а также изображений, HTML-документов и т.д.). В этом случае URL, ис
пользуемый для обращения к сервлету, выглядит так: htt'p: //узел/пуmb_K_Web-
приложению/servlet/имя_пакета.имя_сервлета. Кроме того, большинство Web-
серверов позволяет определять произвольные отображения URL в сервлеты, незави
симо от того, используются ли пакеты и Web-приложения.
Листинг 1 9 . 1 . S e r v l e t T e m p l a t e . J a v a
import java.io.*;
import javax.servlet.^;
import javax.servlet.http.*;
public class ServletTemplate extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
19.3. Базовая структура сервлета 825
P r i n t W r i t e r out = r e s p o n s e . g e t W r i t e r ( ) ;
/ / Объект o u t и с п о л ь з у е т с я для п е р е д а ч и данных б р о у з е р у .
Листинг 19.2.HelloWorld.Java
import j a v a . i o . * ;
import j a v a x . s e r v l e t . * ;
import j a v a x . s e r v l e t . h t t p . * ;
p u b l i c c l a s s HelloWorld extends H t t p S e r v l e t {
p u b l i c void doGet(HttpServletRequest r e q u e s t ,
HttpServletResponse response)
throws S e r v l e t E x c e p t i o n , lOException {
P r i n t W r i t e r out = r e s p o n s e . g e t W r i t e r ( ) ;
o u t . p r i n t l n C ' H e l l o World");
}
Fie £ Л ytew go
Помимо HTML, сервлеты могут передавать клиенту и другие типы данных. Так,
например, нередко в результате выполнения сервлета генерируется изображение в
формате GIF ( i m a g e / g i f ) или таблица Excel ( a p p l i c a t i o n / v n d . m s - e x c e l ) .
Подробно структура HTTP-ответа будет рассмотрена в разделе 19.10. Заметьте, что
заголовки ответа необходимо устанавливать перед тем, как записывать содержимое
ответа, используя для этого объект P r i n t W r i t e r . Дело в том, что HTTP-ответ состо
ит из строки состояния, одного или нескольких полей заголовков, после которых
следует пустая строка и документ, передаваемый броузеру. Порядок включения полей
заголовков не имеет значения; более того, строка состояния может быть сформиро
вана после всех полей. С документом дело обстоит по-другому. Содержимое документа
не всегда сохраняется в буфере, поскольку пользователю удобнее работать, если он
может просматривать начало Web-страницы в то время, как остальная часть докумен
та продолжает загружаться. В версии 2.1 спецификации сервлетов буферизация вы
вода посредством объекта P r i n t W r i t e r не была предусмотрена, и когда начиналась
запись документа в поток, менять состав заголовка было уже поздно. В версии 2.2 бы
ла введена частичная буферизация вывода, однако размеры буфера не были оговоре
ны. Для определения размера буфера используется метод getBuf f e r S i z e объекта
H t t p S e r v l e t R e s p o n s e , а установить размеры буфера можно, вызвав метод
setBuf f e r S i z e . В версии 2.2 есть возможность изменить поля заголовка после нача
ла вывода документа, однако сделать это можно только в том случае, если буфер еще
не заполнился и реальная передача данных клиенту еще не началась. Если вы не уве
рены, началась ли передача данных, выяснить это можно с помощью метода
isCoiranitted.
Методика профессионалов
package cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWWW extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
828 Глава 19. Java на стороне сервера: сервлеты
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String docType =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
"Transitional//EN\">\n";
out.println(docType +
"<HTML>\n" +
"<HEAD><TITLE>Hello WWW</TITLE></HEAD>\n" +
"<BODY>\n" +
"<Hl>Hello WWW</Hl>\n" +
"</BODY></HTML>");
J
Hello WWW
d Рис. 19.2. Результаты выполнения сервлета,
ёЗ Done |^tocd»i*«ne( •y:^: представленного в листинге 19.3 (HelloWWW. j ava)
<!DOCTYPE ...>
<HTML>
<HEAD><TITLE>...</TITLE>...</HEAD>
<BODY ...>...</BODY>
</HTML>
М е т о д и к а профессионалов
Листинг 1 9 , 4 . S e i r v l e t U t i l i t i e s . J a v a
p a c k a g e cwp;
/*^ Простые средства для создания HTML-кода.
* Подобные методы обычно объявляются как static.
V
public class ServletUtilities {
public static final String DOCTYPE =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
"Transitional//EN\">";
public static String headWithTitle(String title) {
return(DOCTYPE + "\n" +
"<HTML>\n" +
"<HEAD><TITLE>" + title + "</TITLE></HEAD>\n");
}
// Остальная часть класса ServletUtilities не приводится.
830 Глава 19. Java на стороне сервера: сервлеты
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
Метод init
Метод i n i t вызывается только при создании сервлета. Каждое последующее об
ращение клиента не приводит к вызову данного метода. Таким образом, процесс ини
циализации сервлета можно сравнить с инициализацией аплета. В зависимости от
19.4. Жизненный цикл сервлета 831
способа регистрации, сервлет создается либо при первом обращении клиента по со
ответствующему URL, либо при запуске сервера. Если сервлет не зарегистрирован, а
лишь помещен в специальный каталог, он создается по обращению пользователя.
Подробно каталоги, предназначенные для размещения сервлетов, были рассмотрены
в разделе 19.2.
Определение метода i n i t сервлета выглядит приблизительно так:
p u b l i c void i n i t O throws S e r v l e t E x c e p t i o n {
/ / Действия по инициализации . . .
}
Метод service
Каждый раз, когда сервер принимает запрос, предназначенный для сервлета, он по
рождает новый поток, в котором вызывается метод s e r v i c e . Метод s e r v i c e проверя
ет тип HTTP-запроса (GET, POST, PUT, DELETE, и т.д.) и вызывает соответствующий ме
тод (например, doGet, d o P o s t , doPut, d o D e l e t e ) . Если ваш сервлет должен одинаково
реагировать на запрос POST и на запрос GET, то вы, возможно, захотите вместо реали
зации методов doGet и do P o s t непосредственно переопределить метод s e r v i c e . Од
нако мы не рекомендуем поступать так. Лучше организовать вызов метода doGet в теле
метода d o P o s t (или наоборот). Пример подобного подхода показан ниже.
p u b l i c void doGet(HttpServletRequest r e q u e s t ,
HttpServletResponse response)
throws S e r v l e t E x c e p t i o n , lOException {
/ / Код сервлета . . .
832 Глава 19. Java на стороне сервера: сервлеты
Совет
Если ваш сервлет должен выполнять одинаковую обработку запро
сов GET И POST, не следует переопределять метод service. Лучше
организовать вызов метода doPost из doGet или вызов метода doGet
ИЗ doPost.
Интерфейс SingteThreadModel
Обычно система создает один экземпляр сервлета, а затем по получении запросов
формирует потоки. Во время обработки одного запроса может быть создано несколь
ко новых потоков. Это означает, что в теле методов d o G e t и d o P o s t необходимо
предусмотреть средства синхронизации доступа к совместно используемым данным.
Если вы хотите запретить одновременное выполнение нескольких потоков, надо соз
дать класс сервлета так, чтобы он реализовывал интерфейс S i n g l e T h r e a d M o d e l .
public class YourServlet extends HttpServlet
implements SingleThreadModel {
}
19.5. Пример использования инициализированных параметров 833
В этом случае вы получаете гарантию того, что в системе для одного экземпляра
сервлета не будет выполняться более одного потока. Запросы к сервлету помещаются
в очередь и обрабатываются последовательно один за другим. Можно также органи
зовать пул экземпляров сервлетов и использовать его для обслуживания запросов. В
этом случае исчезает необходимость заботиться о доступе к переменным экземпляра.
Тем не менее вы должны обеспечить корректную обработку переменных класса
(объявленных как s t a t i c ) , а также данных, расположенных за пределами сервлета.
Однопотоковая организация существенно снижает производительность сервлета,
в особенности, если обращения от клиентов поступают достаточно часто. Поэтому
стоит хорошо подумать, прежде чем принимать решение о реализации интерфейса
SingleThreadModel.
Метод destroy
В процессе работы сервер может принять решение о завершении экземпляра серв
лета. Это может произойти в результате действий администратора либо в случае, если
сервер обнаружит, что сервлет бездействует в течение достаточно длительного време
ни. Перед тем как завершить работу сервлета, сервер вызывает метод d e s t r o y . Этот
метод дает возможность сервлету закрыть соединения с базой данных, закрыть потоки,
записать данные cookie на диск и выполнить необходимые действия по освобождению
ресурсов. Однако не забывайте о том, что при прекращении работы сервлета не всегда
вызывается метод d e s t r o y . Сервер может выйти из строя, и все данные, не сохранен
ные на диске, будут утеряны. Поэтому необходимо предусмотреть периодическую за
пись на диск данных (например, записей cookie) в процессе работы сервера.
М е т о д и к а профессионалов
Листинг 1 9 . 6 . S h o w M e s s a g e . J a v a
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
out.println("</BODY></HTML>");
Щ T h e ShowpMessage S e i v l e l - N e t s c a p e
Л и с т и н г 1 9 . 7 . w e b . x m l (для T o m c a t 3 )
<web-app>
<servlet>
<servlet-name>ShowMsg</servlet-name>
<servlet-class>cwp.ShowMessage</servlet-class>
<init-param>
<param-name>message</param-name>
<param-value>Shibboleth</param-value>
</init-param>
<init-param>
<param-name>repeats</param-name>
<param-value>5</param-value>
</init-param>
</servlet>
</web-app>
ShowMsg.initparams=message=Shibboleth,repeats=5
# Стандартная установка
j sp.code=com.sun.j sp.runtime.JspServlet
зависит от того, были ли данные переданы методом GET или методом POST. Сервлет
выясняет использованный метод и автоматически выполняет разбор строки пара
метров. Д а н н ы й метод возвращает объект S t r i n g , содержащий значение, которое
соответствует первому вхождению указанного имени в строку параметров. Если пара
метр существует, но с ним не связано никакое значение, возвращается пустая строка.
Если при вызове метода указано имя несуществующего параметра, метод возвращает
значение n u l l . Как вы уже знаете, в составе строки параметров могут присутствовать
несколько пар и м я - з н а ч е н и е с совпадающими именами. Для обработки таких данных
желательно использовать вместо g e t P a r a m e t e r метод g e t P a r a m e t e r V a l u e s , воз
вращающий массив строк. Если указанный параметр отсутствует, метод g e t
P a r a m e t e r V a l u e s возвращает значение n u l l , а если имя встречается в строке пара
метров один раз, метод возвращает массив, состоящий из одного элемента.
Имена параметров зависят от регистра символов, поэтому вызовы методов
request.getParameter("Paraml") и request.getParameter("paraml") не
идентичны.
Внимание!
Параметры, передаваемые методам getParameter и getParameter
Values, зависят от регистра символов.
Листинг 19.9. T h r e e P a r a m s . j a v a
package cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ThreeParams extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Reading Three Request Parameters";
out.printIn(ServletUtilities.headWithTitie(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</Hl>\n"
"<UL>\n" +
" <LI><B>paraml</B>: "
+ request.getParameter("paraml") + "\n" +
" <LI><B>param2</B>: "
+ request.getParameter("param2") + "\n" +
<LI><B>param3</B>: "
+ request.getParameter("рагатЗ") + "\n" +
"</UL>\n" +
"</BODY></HTML>");
}
}
[t^iffiifflffiimiFmffi«nmnff,migffii^ii^^i—i 1Я
; Ftle £drt View Г^уоЛег Tools Нф
" 3 r^Go I
ь\тт\т;т\1Щ
Frfe £dtt View F§vontes loots H d p
""1^
Reading Three Request Parameters
• paimnl: ~hall
• paiaml: -brown
• paiamS: -mcnamee
jj
^Oone ~щ Local итйате»
Листинг 1 9 . 1 1 . S e r v l e t U t i l i t i e s . J a v a
p a c k a g e cwp;
import javax.servlet.*;
import javax.servlet.http.*;
public class ServletUtilities {
// Другие части ServletUtilities здесь не показаны.
/** Данный метод заменяет все вхождения символа "<" на
* "<", все вхождения ">" на ">" и (для значений
* атрибутов) все вхождения двойных кавычек на
* """, а все вхождения символа "&" на "&атр;".
* Без подобной фильтрации символы, встречающиеся в строке,
* могут повлиять на внешний вид Web-страницы.
• getContentLength
Метод g e t C o n t e n t L e n g t h возвращает значение заголовка C o n t e n t - L e n g t h в
целочисленном виде ( i n t ) .
• getContentType
Метод g e t C o n t e n t T y p e возвращает значение заголовка C o n t e n t - T y p e (в виде
объекта S t r i n g ) .
• getDateHeader и getlntHeader
Методы g e t D a t e H e a d e r и g e t l n t H e a d e r читают указанные поля и преобра
зуют их значения соответственно в типы D a t e и i n t .
• getHeaderNames
Вместо обращения к конкретному полю заголовка по его имени вы можете ис
пользовать метод g e t H e a d e r N a m e s для получения объекта E n u m e r a t i o n , со
держащего все поля, имеющиеся в составе текущего запроса. Эту возможность
иллюстрирует код, приведенный в листинге 19.12.
• getHeaders
В большинстве случаев имя поля появляется в заголовке запроса лишь один раз.
Однако имена некоторых полей могут повторяться в составе запроса с различ
ными значениями. Примером такого поля может служить A c c e p t - L a n g u a g e .
Если сервер поддерживает спецификацию Java 5е1Л'1е1 2.2, вы можете вызывать
метод g e t H e a d e r s , который возвращает объект E n u m e r a t i o n , содержащий
все значения полей с указанным именем.
Помимо чтения значений полей заголовка, вы можете получить информацию о
самом запросе. Для этого также используются методы объекта H t t p S e r v l e t R e q u e s t .
Т р и основных метода, предназначенных для этой цели, описаны ниже.
• getMethod
Метод g e t M e t h o d возвращает метод запроса (обычно это GET или POST, но мо
гут также встречаться методы HEAD, PUT и DELETE).
• getRequestURI
Метод g e t R e q u e s t U R I возвращает часть URL, расположенную после адреса
узла и номера порта перед данными формы. Н а п р и м е р , для URL h t t p : / /
r a n d o m h o s t . c o m / s e r v l e t / s e a r c h . B o o k S e a r c h метод g e t R e q u e s t U R I вер
нет з н а ч е н и е / s e r v l e t / s e a r c h . B o o k S e a r c h .
• getProtocol
Метод g e t P r o t o c o l возвращает сведения о протоколе, содержащиеся в первой
строке HTTP-запроса. Обычно в результате выполнения данного метода возвра
щается строка H T T P / 1 . 0 или H T T P / 1 . 1 . Перед тем как включать в состав ответа
поля, специфические для протокола HTTP 1.1, надо вызвать g e t P r o t o c o l и убе
диться, что броузер поддерживает версию 1.1 данного протокола.
19.7. Запрос клиента: заголовок HTTP-запроса 843
Листинг 1 9 . 1 2 . S h o w R e q u e s t H e a d e r s . J a v a
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/•• Отображение полей заголовка, переданных в составе запроса.
public class ShowRequestHeaders extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
response.setContentType{"text/html");
PrintWriter out = response.getWriter();
String title = "Servlet Example: Showing Request Headers";
out.printIn(ServletUtilities.headWithTitle(title) +
"<BODY BGC0L0R=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</Hl>\n" +
"<B>Request Method: </B>" +
request. getMethodO + "<BR>\n" +
"<B>Request URI: </B>" +
request.getRequestURI0 + "<BR>\n" +
"<B>Request Protocol: </B>" +
request.getProtocolO + "<BR><BR>\n" +
"<TABLE B0RDER=1 ALIGN=\"CENTER\">\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Header Name<TH>Header Value");
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
out.println("<TR><TD>" + headerName);
out.println(" <TD>" + request.getHeader(headerName));
}
out.println("</TABLE>\n</BODY></HTML>");
}
/** Сервлет поддерживает как метод GET, так и метод POST. */
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
844 Глава 19. Java на стороне сервера: сервлеты
doGet(request, response);
Header Name
Accept Language f;.
Connection Keep-Alive
User-Agent MozillaM 7 [en] (Wm98. U)
Accept-Charset iso-8859-l,*,utf-8
iHost localhost
jAccept-Encoding ;gzip
:Accept ^age/gif; unagc/x-xbitamp, miagc/jpcg, miagc/pjpeg. cnage/png, */*
t^tflnfiifmi^mffiif^i!H«iw^inmiinimif'
'• Ffe £{Й View F^vofites ТоЫе Нф
3,
Sei^let Example: Showing Request Headers
Request Metliod; GET
Request URI: /servlet/cwp.ShowRequestHeaders
Request Rotocol; HTTP/1 1
:|||Ш1Ш||Ши'р
Accept-
:- :en-us
iLanguage
iConnection -Keep-AHvc
;User-Agent ;Моа11а/4.0 (compatible. MSIE 5.0, Windows 9S, DigExt)
iHost ilocalhost
^Accept-
jgap, deflate
;Encoding
'image/gif, image/x-xbitmap, image/jpeg. image/pjpeg, application/msword,
jAccept
appbcaton/vndms-excel, appHcabon/^/nd ms-poweфOlnt, *'*•
Рис. 19.7. Поля заголовка в окне броузера Internet Explorer 5.0, выпол
няющегося в системе Windows 98
19.7. Запрос клиента: заголовок HTTP-запроса 845
Accept
В данном поле содержатся MIME-типы данных, поддерживаемых броузером или
другим HTTP-клиентом, отправившим запрос. Сервлет, в котором предусмотрена
возможность передачи данных в различных форматах, проверяет содержимое
A c c e p t и решает, какой из форматов целесообразно выбрать при ф о р м и р о в а н и и
ответа. Н а п р и м е р , изображения в формате PNG занимают меньше места по срав
нению с теми же изображениями в формате GIF, однако броузеры, поддерживаю
щие формат PNG, встречаются достаточно редко. Если сервлет имеет, доступ к
PNG-файлам, он должен вызвать метод r e q u e s t . g e t H e a d e r ( " A c c e p t " ) , прове
рить, содержится ли в списке МШЕ-типов i m a g e / p n g , и если такой тип обнару
жен, то передать файл xxx.png. В противном случае сервлет должен отправить
клиенту файл ххх. g i f . Н е к о т о р ы е MIME-типы приведены в табл. 19.1.
Accept-Charset
Данное поле определяет наборы символов (например, ISO-8859-1), поддерживае
мые броузером.
Accept-Encoding
Данное поле заголовка указывает типы кодировки, поддерживаемые броузером.
Если сервер пол)'чает поле A c c e p t - E n c o d i n g в составе заголовка, он может зако
дировать содержимое документа, представив его в любом из указанных форматов.
П р и этом в заголовок ответа включается поле C o n t e n t - E n c o d i n g . Обычно коди
рование производится для уменьшения времени передачи документа по сети. Тип
кодировки существенно отличается от MIME-типа документа (который указывает
ся в поле заголовка ответа C o n t e n t - Т у р е ) , так как броузер предпринимает кон
кретные действия по воспроизведению документа уже после декодирования. Если
броузер не поддерживает конкретный тип кодировки, он не сможет отобразить
Web-страницу. Стандартными типами кодировок являются g z i p и c o m p r e s s .
Сжатие содержимого документа перед отправкой его по сети вполне оправдано,
поскольку время, которое экономится при передаче, значительно превышает вре
мя, необходимое для декодирования документа. Далее в этом разделе будет приве
ден пример того, как при кодировании время передачи документа сокращается
приблизительно в 10 раз.
846 Глава 19. Java на стороне сервера: сервлеты
Accept-Language
Если сервлет имеет возможность генерировать ответы на различных языках, то,
проверив содержимое этого поля, он может выбрать язык, подходящий для кли
ента. Значениями данного поля являются двухбуквенные сокращения, например
en, e n - U S , d a и т.д. Подробно этот вопрос описан в документе RFC 1766.
Authorization
Данное поле идентифицирует клиента при обращении к Web-страницам, защи
щенным паролем.
Connection
Содержимое данного поля определяет, может ли клиент поддерживать постоян
ные HTTP-соединения. Посредством одного постоянного соединения броузер
может получить несколько файлов (например, HTML-документ и связанные с ним
изображения). П р и этом исключаются накладные расходы, связанные с открыти
ем новых соединений. В запросах H T T P 1.1 постоянные соединения предполага
ются по умолчанию, и для того, чтобы организовать HTTP-обмен в соответствии с
использовавшимся ранее стандартом, надо задать в поле C o n n e c t i o n значение
c l o s e . В H T T P 1.0 значение K e e p - A l i v e указывает на то, что постоянное соеди
нение должно поддерживаться.
Каждый HTTP-запрос приводит к очередному вызову сервлета, независимо то то
го, передаются ли запросы в рамках одного соединения или через отдельные со
единения. Сервер вызывает сервлет только после чтения HTTP-запроса. Это озна
чает, что для поддержки постоянных соединений сервлет должен пользоваться
средствами сервера. Задача же сервлета— предоставить серверу данные, необхо
димые для того, чтобы такая поддержка стала возможной. В частности, в составе
ответа, передаваемого через постоянное соединение, обязательно должно присут
ствовать поле C o n t e n t - L e n g t h .
Content-Length
Данное поле используется только в запросах POST. Содержимое поля указывает чис
ло байт в строке. Вместо того чтобы вызывать r e q u e s t . g e t l n t H e a d e r ( " C o n t e n t -
L e n g t h " ) , вы можете обратиться в методу r e q u e s t . g e t C o n t e n t L e n g t h ( ) . По
скольку сервлеты автоматически выполняют разбор данных, обращение к данному
полю выполняется очень редко.
Cookie
В поле C o o k i e броузер возвращает серверу данные cookie, которые ранее были
переданы ему. Подробно этот вопрос рассматривается в разделе 19.11. Поддержка
cookie не предусмотрена в протоколе H T T P 1.1. Cookie представляет собой рас
ширение Netscape, которое в настоящее время поддерживается как Netscape, так и
Internet Explorer.
19.7. Запрос клиента: заголовок HTTP-запроса 847
Host
Броузеры и другие HTTP-клиенты обязаны включать данное поле в заголовок за
проса. Содержимое поля Host определяет узел и порт, соответствующие исходно
му URL. Так как компьютеры могут иметь несколько имен и поскольку запросы в
некоторых случаях перенаправляются, может возникнуть ситуация, при которой
поле Host станет единственным источником информации об узле. Данное поле
использовалось и раньше, однако в HTTP 1.0 оно было необязательным.
If-Modified-Since
Данное поле заголовка указывает на то, что документ должен передаваться клиен
ту только в том случае, если он был модифицирован позже указанной даты. Если
новые результаты не получены, сервер передает в заголовке код 302 (Not
Modified). Наличие поля If-Modif i e d - S i n c e позволяет броузеру сохранять до
кументы в кэше, передавая их по сети только в том случае, если с момента послед
него просмотра они были изменены. Сервлет не должен непосредственно выпол
нять какие-либо действия с этим заголовком. Чтобы система могла автоматически
принимать решение о передаче документа, достаточно реализовать в сервлете ме
тод g e t L a s t M o d i f i e d .
If-Unmodified-Since
Данное поле вызывает результат, обратный If-Modif i e d - S i n c e . Оно указывает
на то, что обработка запроса должна быть продолжена только в том случае, если
документ был создан или модифицирован раньше указанной даты. Если поле If-
Modif i e d - S i n c e применяется в запросах GET (передать документ только в том
случае, если он модифицирован позже, чем документ, содержащийся в кэше), то
поле If-Unmodif i e d - S i n c e включается в состав запросов PUT (обновить доку
мент только в том случае, если он имеет более раннюю дату последней модифика
ции, чем предлагаемый документ).
Referer
Данное поле содержит URL Web-страницы, на которой находится ссылка, исполь
зованная при формировании запроса. Так, например, если на странице А содер
жится ссылка на страницу Б, то в составе запроса на получение страницы Б будет
содержаться поле R e f e r e r , в котором указан URL страницы А. Эта возможность
позволяет выявить документы, авторы которых согласились включить в них рек
ламу других узлов, а также дает возможность прослеживать трафик. Значение
R e f e r e r обычно отражается в файле протокоа. Несмотря на то что R e f e r e r —
очень полезное поле, не стоит излишне полагаться на него, поскольку его значе
ние легко фальсифицировать. Заметьте также, что поле называется R e f e r e r (а не
R e f e r r e r , как можно было бы ожидать); один из авторов HTTP допустил грамма
тическую ошибку.
User-Agent
Данный заголовок идентифицирует броузер, сгенерировавший запрос, и может
быть использован для того, чтобы менять содержимое документа в зависимости от
типа применяемого клиента. Создавая версии документов или коды сервлетов,
848 Глава 1 9 . Java на стороне с е р в е р а : сервлеты
Листинг 1 9 . 1 3 . E n c o d e d P a g e . J a v a
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.zip.*;
out.printIn(ServletUtilitles.headWithTitie(title) +
"<BODY BGC0L0R=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</Hl>\n"
String line = "Blah, blah, blah, blah, blah. " +
"Yadda, yadda, yadda, yadda.";
for(int 1=0; i<10000; i++) {
out.println(line);
}
out.println("</BODY></HTML>");
out.close 0 ;
850 Глава 19. Java на стороне сервера: сервлеты
- ^ y^ J : . i ^ j i i ^ . i ^ r f ' a a
Page Encoded with GZip
Blah, blah, blah, blah, blah Yadda, yadda, yadda, yadda Blah, blah, blah, blah, blah
Yadda, yadda, yadda, yadda Blah, blah, blah, blah, blah Yadda, yadda. yadda, yadda
Blali. blah, blah, blah, blah Yadda, yadda, yadda. yadda Blah, blah, blah, blah, blah j ^
AUTH_TYPE
Если в заголовке присутствует поле A u t h o r i z a t i o n , данная переменная окруже
ния сообщает об используемой схеме ( b a s i c или d i g e s t ) . Аналогичные данные
можно получить с помощью метода r e q u e s t . g e t A u t h T y p e ( ) .
CONTENT_LENGTH
Значение данной переменной устанавливается только п р и получении запроса
POST. В переменной CONTENTLENGTH указывается количество байтов данных, со
держащееся в теле запроса, т.е. CONTENTLENGTH предоставляет ту же информа
цию, что и поле заголовка C o n t e n t - L e n g t h . Для того чтобы получить информа
цию, аналогичную значению переменной окружения CONTENTLENGTH, надо вы
звать S t r i n g . v a l u e O f ( r e q u e s t . g e t C o n t e n t L e n g t h О ) или r e q u e s t . g e t -
H e a d e r ( " C o n t e n t - L e n g t h " ) . Однако на практике многие предпочитают исполь
зовать метод r e q u e s t . g e t C o n t e n t L e n g t h ( ) , который возвращает значение i n t .
19.8. Аналоги стандартных CGI-переменных 851
CONTENT.TYPE
Переменная окружения CONTENT_TYPE определяет М1МЕ-тип данных, содержа
щихся в составе запроса. Часто используемые МШЕ-типы перечислены в
табл. 19.1. Информацию, аналогичную CONTENT_TYPE, можно получить, вызвав
метод r e q u e s t . g e t C o n t e n t T y p e ( ) .
DOCUMENT_ROOT
Переменная DOCUMENT_ROOT определяет каталог, соответствующий URL
h t t p : / / h o s t / , где h o s t означает конкретное имя узла. Для получения соответст
вующего значения используется метод g e t S e r v l e t C o n t e x t () . g e t R e a l -
Path ( " / " ) . Более старые спецификации сервлетов предполагали возможность
вызова r e q u e s t . g e t R e a l P a t h ( " / " ) , однако такой подход уже не поддерживает
ся. Для отображения произвольного URI (части URL, следующей за адресом узла и
номером порта) в реальный путь на локальной машине можно также воспользо
ваться методом g e t S e r v l e t C o n t e x t ( ) . g e t R e a l P a t h .
HTTP^XXX.YYY
Переменные окружения с именами в представленном формате позволяют полу
чать необходимые значения полей HTTP-заголовка. Например, содержимое поля
Cookie доступно посредством переменной НТТР_С00К1Е, полю User-Agent со
ответствует переменная HTTP__USER__AGENT, значение HTTP_REFERER определяет
ся содержимым поля R e f e r e r и т.д. Сервлеты могут использовать для этой цели
метод r e q u e s t . g e t H e a d e r либо один и специальных методов, описанных в раз
деле 19.7.
PATHJNFO
Переменная PATHINFO предоставляет информацию, заданную в URL после адре
са сервлета и перед данными запроса. Например, для выражения h t t p : / / h o s t /
s e r v l e t / c w p . S o m e S e r v l e t / f oo/bar?baz=quux в состав PATH_INFO будет вклю
чена последовательность символов / f с о / b a r . Поскольку сервлет, в отличие от
CGI-программ, может непосредственно взаимодействовать с сервером, данные,
содержащиеся в PATH_INFO, для его работы не требуются, однако получить соот
ветствующее значение можно вызовом метода r e q u e s t . g e t P a t h I n f о.
PATH^TRANSLATED
Переменная окружения PAT Н Т RAN SLATED предоставляет информацию о пути,
отображенную в реальный путь на сервере. Для сервлетов эти данные не нужны,
поскольку для преобразования пути можно вызвать метод g e t S e r v l e t
Context () . g e t R e a l P a t h . Подобные преобразования нельзя выполнить в тради
ционных CGI-программах, поскольку они выполняются независимо от сервера.
Для получения значения данной переменной используется метод r e q u e s t . G e t -
PathTranslated.
852 Глава 19. Java на стороне сервера: сервлеты
QUERY_STRING
В случае запроса GET данная переменная предоставляет строку параметров, при
соединенную к URL. В сервлетах необходимость в этих данных практически нико
гда не возникает, так как разработчик может для получения конкретных парамет
ров воспользоваться методом r e q u e s t . g e t P a r a m e t e r (см. раздел 19.7). Если по
каким-то причинам вам нужны необработанные данные, получить их можно по
средством метода r e q u e s t . g e t Q u e r y S t r i n g .
REMOTE__ADDR
Данная переменная определяет IP-адрес клиента, от которого поступил запрос.
Адрес представляется в строковом виде (например, "198.137.241.30"). Эти сведе
ния могут быть также получены посредством метода r e q u e s t . g e t Remote Addr ( ) .
REMOTE_HOST
Переменная REMOTE_HOST содержит полное доменное имя клиента (например,
m y c l i e n t . g o v ) . Если доменное имя не может быть определено, возвращается
IP-адрес. Аналогичные данные можно получить с помощью метода r e q u e s t .
getRemoteHost().
REMOTE^USER
Если в составе запроса был заголовок A u t h o r i z a t i o n , обработанный сервером,
переменная окружения REMOTEUSER содержит данные о пользователе, которые
можно использовать для отслеживания сеансов на защищенных узлах. Данную ин
формацию можно получить с помощью метода r e q u e s t . g e t R e m o t e U s e r ( ) .
REQUEST^METHOD
Данная переменная определяет тип HTTP-запроса (обычно это GET или POST, но
иногда также встречаются значения HEAD, PUT, DELETE, OPTIONS и TRACE).
В сервлетах информация о типе запроса обрабатывается автоматически и в зави
симости от используемого типа вызывается метод d o G e t , do P o s t и т.д. Исключе
нием является запрос HEAD, который автоматически обрабатывается методом
s e r v i c e . Данные, соответствующие значению переменной REQUESTMETHOD,
можно получить с помощью метода r e q u e s t . g e t M e t h o d ( ) .
SCRIPT__NAME
Данная переменная указывает путь к сервлету относительно корневого каталога
сервлетов. Получить эти сведения можно, вызвав метод r e q u e s t . g e t S e r v l e t P a t h .
SERVER_NAME
Переменная окружения SERVER_NAME содержит имя узла, на котором выполняется
сервер. Для получения этих данных используется метод r e q u e s t . g e t S e r v e r N a m e .
SERVER_PORT
В данной переменной содержится номер порта, по которому сервер ожидает об
ращения. Для того чтобы получить аналогичные данные, надо использовать вызов
19.9. Ответ сервера: коды состояния 853
SERVER_PROTOCOL
Переменная SERVER_PROTOCOL сообщает название и версию протокола, указан
ного в запросе (например, H T T P / 1 . 0 или H T T P / 1 . 1 ) . Эти данные можно получить
также с помощью метода r e q u e s t . g e t P r o t o c o l .
SERVER_SOFTWARE
Данная переменная окружения содержит и н ф о р м а ц и ю о программном обеспече
нии Web-сервера. В сервлетах получить подобные сведения можно вызовом мето
да g e t S e r v l e t C o n t e x t ( ) . g e t S e r v e r I n f о .
ра, все, что может сделать разработчик сервлета, — предусмотреть установку кода со
стояния. Для этого используется метод s e t S t a t u s класса H t t p S e r v l e t R e s p o n s e .
Компоненты HTTP-ответа расположены в строго определенном порядке. Поэтому,
если ваш ответ содержит специальный код состояния, а документ входит в состав от
вета, убедитесь в том, что метод s e t S t a t u s вызывается перед передачей содержимо
го документа посредством P r i n t W r i t e r . Как было сказано в разделе 19.3, сервер не
обязательно сохраняет документ в буфере (спецификация Servlet 2.1 вовсе не преду
сматривает буферизацию). В связи с этим вы должны либо установить код состояния
до обращения к P r i n t W r i t e r , либо сделать это до того, как содержимое буфера будет
передано броузеру.
М е т о д и к а профессионалов
• 100-199
Коды, в который первая из трех ц и ф р равна 1, указывают на то, что, получив
ответ, клиент должен выполнить некоторые действия.
• 200 - 299
Коды, начинающиеся с ц и ф р ы 2, сообщают о том, что запрос был обработан
успешно.
• 300-399
Коды в данном диапазоне означают, что файл, указанный в запросе, был пере
мещен. О б ы ч н о при этом в состав ответа включается поле L o c a t i o n , содер
жащее новый адрес ресурса.
• 400-499
Коды, начинающиеся с цифры 4, соответствуют ошибкам, допущенным клиентом.
• 500 - 599
Коды в данном диапазоне указывают на ошибку сервера.
100 (Continue)
Если сервер получает в составе запроса поле E x p e c t , содержащее 1 0 0 - c o n t i n u e ,
это означает, что клиент запрашивает разрешение передать в составе следующего
запроса код документа. Если сервер отправит ответ с кодом состояния 100
(SCCONTINUE), то клиент может продолжать передачу данных. Код 417
( E x p e c t a t i o n F a i l e d ) сообщает о том, что броузер не может принять'документ.
Код состояния 100 был введен в HTTP 1.1.
856 Глава 19. Java на стороне сервера: сервлеты
200 ( О К )
Код 200 (SCOK) говорит о том, что обработка запроса окончилась успешно. В со
ставе ответа передается документ, указанный в запросе. Данный код устанавлива
ется для сервлетов по умолчанию. Если вы не вызовете метод s e t S t a t u s , сервер
установит код 200.
201 (Created)
Код состояния 201 (SC_CREATED) означает, что сервер в ответ на запрос создал
новый документ. URL этого документа помещается в поле заголовка L o c a t i o n .
202 (Accepted)
Код 202 (SCACCEPTED) информирует клиента о том, что запрос был принят, но
. обработка его еще не закончилась.
204 ( N o Content)
Код состояния 204 (SC_NO_CONTENT) сообщает броузеру, что тот должен отобра
жать предыдущий документ, поскольку новый документ недоступен. Этот код по
лезен в том случае, когда пользователь периодически перезагружает Web-страницу
с помощью кнопки Reload и на каком-то этапе сервлет обнаруживает, что очеред
ной вариант документа полностью повторяет предыдущий.
302 (Found)
Данное значение аналогично коду 301 за исключением того, что URL, указанный в
поле L o c a t i o n , должен интерпретироваться как временный адрес ресурса. На
практике большинство броузеров обрабатывает коды 301 и 302 одинаково. За
метьте, что в HTTP 1.0 данному коду соответствовало сообщение Moved Tempo
r a r i l y , а в H T T P 1.1 — сообщение Found. Вопреки ожиданиям, константа, объяв
ленная в классе H t t p S e r v l e t R e s p o n s e , называется не SC_FOUND, а
SC_MOVED_TEMPORARILY.
На заметку
Код состояния 302 полезен, поскольку броузеры автоматически следуют ссылке, ука
занной в поле L o c a t i o n . Кроме того, для поддержки данного кода предусмотрен
специальный метод sendRedirect. Использование response. sendRedi-
rect(url) предпочтительнее, чем обращение к методу r e s p o n s e . s e t -
S t a t u s ( r e s p o n s e . SC_MOVED_TEMPORARILY) с последующим вызовом r e s p o n s e .
s e t H e a d e r ( " L o c a t i o n " , u r l ) . Во-первых, код сервлета упрощается, во-вторых,
]1ЛЯ броузеров, не поддерживающих перенаправление, сервлет с помощью
s e n d R e d i r e c t автоматически создает страницу, содержащую ссылку на ресурс. И,
наконец, при работе с версией 2.2 (используемой в J2EE) метод s e n d R e d i r e c t под
держивает относительные URL и автоматически преобразовывает их в абсолютные.
Предполагается, что броузеры автоматически следуют по указанному адресу только в
случае запроса GET. Дополнительная информация приведена в описании кода 307.
400 (Bad R e q u e s t )
Код состояния 400 (SC_BAD_REQUEST) сообщает о том, что запрос клиента был со
ставлен некорректно и содержал синтаксические ошибки.
858 Глава 19. Java на стороне сервера: сервлеты
401 ( U n a u t h o r i z e d )
Значение 401 (SC_UNAUTHORIZED) указывает на то, что клиент старается получить
доступ к документу, защищенному паролем, не указав требуемые идентификаци
онные данные в поле заголовка A u t h o r i z a t i o n . Ответ должен содержать поле
WWW-Authenticate.
403 ( F o r b i d d e n )
Код состояния 403 (SC_FORBIDDEN) сообщает, что, независимо от идентификаци
онных данных, сервер отказывается предоставить ресурс. Часто такой ответ гене
рируется в тех случаях, когда права доступа к файлу или каталогу на сервере уста
новлены неправильно.
404 ( N o t F o u n d )
Код 404 (SCNOTFOUND) информирует клиента о том, что ресурс, URL которого
был указан в составе запроса, отсутствует. Данный код встречается настолько час
то, что для его поддержки в классе H t t p S e r v l e t R e s p o n s e был предусмотрен
специальный метод s e n d E r r o r . В качестве параметра этому методу передается
текстовое сообщение. Преимущество метода s e n d E r r o r перед методом
s e t S t a t u s состоит в том, что при выполнении s e n d E r r o r сервер автоматически
генерирует страницу с сообщением об ошибке. По умолчанию Internet Explorer 5
игнорирует сообщение об ошибке и отображает свою страницу, хотя это и проти
воречит спецификации HTTP. Для того чтобы отменить эту установку, надо вы
брать пункт меню Tools (Сервис), перейти в меню Internet Options (Свойства обо
зревателя), выбрать вкладку Advanced (Дополнительно) и сбросить флажок опции
Show friendly HTTP error m e s s a g e s (Выводить подробные сообщения об ошибках
HTTP). К сожалению, большинство пользователей ничего не знают об этой уста
новке Internet Explorer 5, поэтому сообщения об ошибках, генерируемые на сто
роне сервера, для них недоступны. Другие популярные броузеры и Internet
Explorer 4 нормально отображают подобные сообщения.
Внимание!
По умолчанию internet Explorer игнорирует сообщения об ошибках,
генерируемые сервером.
405 ( M e t h o d N o t Allowed)
Код 405 (SC_METHOD_NOT_ALLOWED) указывает на то, что конкретный метод (GET,
POST, HEAD, PUT, DELETE и т.д.) недопустим для данного ресурса. Этот код был
введен в H T T P 1.1.
410 ( G o n e )
Код состояния 410 (SCGONE) сообщает клиенту о том, что запрашиваемый доку
мент удален и адрес для перенаправления запроса неизвестен. Код 410 отличается
от кода 404 тем, что он явно указывает, что документ был удален, а код 404 сооб
щает, что ресурс не найден и п р и ч и н ы этого неизвестны. Данный код состояния
был введен в H T T P 1.1.
19.9. Ответ сервера: коды состояния 859
411 (Length R e q u i r e d )
Код 411 (SC_LENGTH_REQUIRED) указывает на то, что сервер не может обработать
запрос (обычно это запрос POST с присоединенным документом), поскольку кли
ент не включил в него поле C o n t e n t - L e n g t h , сообщающее об объеме данных, пе
редаваемых на сервер. Д а н н ы й код был введен в H T T P 1.1.
414 (Request U R I T o o L o n g )
Код состояния 414 ( S C R E Q U E S T U R I T O O L O N G ) сообщает, что длина URI в со
ставе запроса слишком велика. URI — это часть URL, находящаяся после адреса уз
ла и номера порта. Н а п р и м е р , в URL h t t p : / / w w w . y 2 k - d i s a s t e r . c o m : 8 0 8 0 /
w e / l o o k / s i l l y / n o w / последовательность символов / w e / l o o k / s i l l y / n o w / со
ставляет URI. Данный код был введен в H T T P 1.1.
415 ( U n s u p p o r t e d M e d i a Type)
Значение 415 (SC_UNSUPPORTED_MEDIA_TYPE) указывает на то, что тип докумен
та, переданного в составе запроса, неизвестен серверу и сервер не знает, как обра
ботать его. Данный код был введен в H T T P 1.1.
501 ( N o t I m p l e m e n t e d )
Код 501 (SC_NOT_IMPLEMENTED) оповещает клиента о том, что функции, необходи
мые для обслуживания запроса, на сервере не реализованы. Такой ответ клиент мо
жет получить в ответ на запрос PUT, если сервер не поддерживает данный метод.
860 Глава 19. Java на стороне сервера: сервлеты
505 ( H T T P V e r s i o n N o t S u p p o r t e d )
Код 505 (SC_HTTP_VERSION_NOT_SUPPORTED) означает, что сервер не поддержи
вает версию H T T P , указанную в запросе. Данный код был введен в l i T T P 1.1.
Листинг 1 9 . 1 4 . S e a r c h E n g i n e s . J a v a
р а с к а д е cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
/** Сервлету передаются ключевые слова для поиска, число
* результатов на странице и имя поискового сервера.
* Данный сервлет иллюстрирует использование заголовка
* ответа. Если сервлету известен поисковый сервер, он
* генерирует ответ 302 (посредством sendRedirect).
* В противном случае клиенту передается ответ 4 04
* (посредством sendError).
*/
public class SearchEngines extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
19.9. Ответ сервера: коды состояния 861
Листинг 1 9 . 1 5 . S e a r c h S p e c . J a v a
p a c k a g e cwp;
j;^»A!ijj!i;ii|jf|MJi|.H.iiu/^i.!iifira!ff^^
'.r-T^jTa^a й-м^Л'^-j'
AiJdiess \fi] h(tp //localhost/cwp/Seafd-£ngines html ^J ^ ^^^
3
Searching the Web
Search String: |serviets J S P book
Results to Show Per Page fTF~
<? Google I <" bifoseek | r L/COS | r HotBot
Se«rch I
J
^ Done 1 ^ local rtidfiet
:?'«о.Н' • / ; I' 1П0М 1'/. •: 2,580* vservlets JSP book .-^'Г' i L-^-0.68 ^.7.'.- ^
"^-i'"'';'"^ Computers > Programming > Languages > Java > Runtime Environments > Sen/lets
zl
iigj Ф intefnet
Листинг 19.16,SearchEngines.html
<BODY BGC0L0R="#FDF5E6">
<H1 ALIGN="CENTER">Searching the Web</Hl>
<FORM ACTION="/servlet/cwp.SearchEngines">
<CENTER>
Search String:
<INPUT TYPE="TEXT" NAME="searchString"><BR>
Results to Show Per Page:
<INPUT TYPE="TEXT" NAME="numResults"
VALUE=10 SIZE=3><BR>
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="google">
Google I
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="infoseek">
Infoseek |
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="lycos">
Lycos I
<INPUT TYPE="RADIO" NAME="searchEngine"
VALUE="hotbot">
HotBot
<BR>
<INPUT TYPE="SUBMIT" VALUE="Search">
</CENTER>
</FORM>
</BODY>
</HTML>
• setContentType
Данный метод устанавливает поле заголовка C o n t e n t - T y p e и используется
большинством сервлетов.
• setContentLength
Данный метод устанавливает поле заголовка C o n t e n t - L e n g t h и используется в том
случае, если броузер поддерживает постоянное (keep-alive) HTTP-соединение.
866 Глава 19. Java на стороне сервера: сервлеты
• addCookie
Метод addCookie включает в состав заголовка поле S e t - C o o k i e , содержащее
запись cookie. Метод s e t Cookie отсутствует, поскольку наличие в одном заго
ловке нескольких полей cookie— вполне нормальное явление. Механизм
cookie будет рассматриваться в разделе 19.11.
• sendRedirect
Как было сказано в предыдущем разделе, метод s e n d R e d i r e c t , помимо уста
новки кода состояния 302, включает также в состав заголовка поле L o c a t i o n .
Пример использования данного метода приведен в листинге 19.14.
Allow
Данное поле заголовка указывает методы запроса, поддерживаемые сервером. Это
поле обязательно должно входить в состав ответа 405 (Method Not Allowed). По
умолчанию метод s e r v i c e автоматически генерирует поле Allow для запросов
OPTION.
Cache-Control
Поле C a c h e - C o n t r o l сообщает броузеру или другой клиент-программе условия,
при которых документ, переданный в составе ответа, может быть помещен в кэш.
В этом поле могут содержаться следующие значения.
• p u b l i c . Документ может быть помещен в кэш, даже если общепринятые пра
вила запрещают делать это (например, если документ защищен паролем).
• p r i v a t e . Документ предназначен для одного пользователя и может содер
жаться только в личном (неразделяемом) кэше.
• п о - c a c h e . Документ не должен помещаться в кэш. Сервер также может за
дать выражение n o - c a c h e = " h e a d e r l , h e a d e r 2 , . . . ,headerN", в котором
19.10. Ответ сервлета: поля заголовка 867
Connection
Если в поле C o n n e c t i o n указано значение c l o s e , броузер не должен использовать
постоянное соединение. По умолчанию клиенты, поддерживающие протокол
HTTP 1.1, используют постоянное соединение. Чтобы постоянное соединение со
хранялось, для клиентов HTTP 1.0 должно быть указано поле C o n n e c t i o n :
k e e p - a l i v e , а для клиентов HTTP 1.1 — не указано C o n n e c t i o n : c l o s e . При на
личии постоянного соединения в составе заголовка ответа обязательно должно
присутствовать поле C o n t e n t - L e n g t h .
/
Content-Encoding
Данное поле сообщает о том, каким преобразованиям подвергалось содержимое
документа перед передачей. После получения документа броузер должен выпол
нить обратное преобразование. Если документ был сжат посредством g z i p , при
передаче такого документа экономится много времени. Пример передачи сжатого
документа приведен в разделе 19.7.
868 Глава 19. Java на стороне сервера: сервлеты
Content-Language
Поле C o n t e n t - L a n g u a g e определяет язык документа. Значением этого поля
должно быть стандартное двухбуквенное сокращение, например e n , e n - u s , da и
т.д. Дополнительную информацию вы найдете в RFC 1766.
Content-Length
Данное поле заголовка указывает число байт в документе, содержащемся в составе
ответа. Это поле необходимо только в том случае, если броузер поддерживает по
стоянное HTTP-соединение. Чтобы определить, может ли броузер использовать по
стоянное соединение, надо проверить значение поля заголовка C o n n e c t i o n . Если
вы хотите воспользоваться преимуществами постоянного соединения, вам надо за
писать документ в B y t e A r r a y O u t p u t S t r e a m , определить размер документа, устано
вить соответствующее значение поля C o n t e n t - L e n g t h , вызвав для этого метод
r e s p o n s e . s e t C o n t e n t L e n g t h , а затем передать содержимое документа посредст
вом в ы з о в а b y t e A r r a y S t r e a m . w r i t e T o ( r e s p o n s e . g e t O u t p u t S t r e a m ( ) ).
Content-Type
Поле C o n t e n t - T y p e содержит MIME-тип документа, передаваемого в составе от
вета. Данное поле приходится устанавливать настолько часто, что в классе
H t t p S e r v l e t R e s p o n s e для этого предусмотрен специальный метод s e t C o n -
t e n t T y p e . Зарегистрированные MIME-типы задаются в формате шип/подтип, а
незарегистрированные— в формате тип/х-подтип. По умолчанию для сервлетов
принимается MIME-тип t e x t / p l a i n , однако сервлет может явно задать тип
t e x t / h t m l либо другой требуемый тип.
Часто используемые MIME-типы перечислены в табл. 19.1.
Подробно MIME-типы описаны в документах RFC 1521 и RFC 1522 (ссылки на
электронные версии вы найдете по адресу h t t p : / / w w w . r f c - e d i t o r . o r g / ) . По
скольку новые MIME-типы постоянно регистрируются, существуют динамически
обновляемые списки типов. О ф и ц и а л ь н о зарегистрированные MIME-типы пере
числены в документе h t t p : / / w w w . i s i . e d u / i n - n o t e s / i a n a / a s s i g n m e n t s / -
m e d i a ^ t y p e s / m e d i a - t y p e s . И н ф о р м а ц и ю об используемых незарегистрирован
ных типах можно найти по адресу h t t p : / / w w w . l t s w . s e / k n b a s e / i n t e r n e t / -
mime.htp.
Expires
Данное поле задает время, по истечении которого документ считается устаревшим
и его версия, содержащаяся в кэше, не должна использоваться. Сервлет может
применять это поле при передаче броузеру документов, содержимое которых под
вергается частым изменениям. Например, следующий фрагмент кода включает в
состав заголовка поле, сообщающее о том, что документ, полученный броузером,
остается действительным в течение 10 минут.
long currentTime = System.currentTimeMillis ( ) ;
l o n g t e n M i n u t e s = 1 0 * 6 0 * 1 0 0 0 ; / / Значение в миллисекундах
response.setDateHeader("Expires",
currentTime + tenMinutes);
Аналогичные действия выполняет значение m a x - a g e поля C a c h e - C o n t r o l .
870 Глава 19. Java на стороне сервера: сервлеты
Last-Modified
В поле L a s t - M o d i f i e d указывается дата последней модификации документа. Если
броузер включает в состав запроса поле заголовка I f - M o d i f i e d - S i n c e , он фор
мирует тем самым условный запрос. Документ передается в ответ на этот запрос,
только если дата, указанная в Last-Modif i e d , оказывается более поздней по
сравнению со значением If-Modif i e d - S i n c e . В противном случае сервер фор
мирует ответ с кодом состояния 304 (Not Modified) и клиент использует копию
документа, содержащуюся в кэше. Если вы собираетесь явно устанавливать данное
поле, используйте для этого метод s e t D a t e H e a d e r . Однако в большинстве случаев
устанавливать значение данного поля не требуется. Вместо этого следует реализо
вать метод getLastModif i e d и предоставить стандартному методу s e r v i c e об
рабатывать условные запросы.
Location
Данное поле заголовка включается в состав всех ответов, для которых код состоя
ния начинается с цифры 3, и сообщает броузеру адрес документа. Броузер автома
тически устанавливает соединение с указанным узлом и получает документ. Часто
значение данного поля устанавливается с помощью метода s e n d R e d i r e c t класса
H t t p S e r v l e t R e s p o n s e , который также устанавливает код состояния, равный 302.
Пример использования этого метода был приведен в предыдущем разделе.
Pragma
Если в состав заголовка ответа включено поле Pragma, содержащее значение п о -
cache, клиент, поддерживающий протокол HTTP 1.0, не должен сохранять полу
ченный документ в кэше. В HTTP 1.1 аналогичные действия выполняет поле
Cache-Control: no-cache.
Refresh
Данный заголовок указывает время (в секундах), через которое броузер должен
обратиться за обновленным вариантом Web-страницы. Например, чтобы броузер
запрашивал новую копию документа каждые 30 секунд, вы должны установить зна
чение 30 следующим образом:
response.setlntHeader("Refresh", 30)
Заметьте, что поле R e f r e s h не задает постоянное обновление документа. Оно
лишь указывает, через какое время должно произойти следующее обращение кли
ента. Продолжая передавать поле Refresh, вы можете сформировать ответ с ко
дом 204 (No Content), чтобы предотвратить копирование документа. Пример ис
пользования поля R e f r e s h будет приведен ниже в этом разделе.
Вместо повторной загрузки текущего документа вы можете указать новую Web-
страницу. Для этого после значения, определяющего время обновления, задайте
точку с запятой и URL страницы. Например, чтобы броузер загружал через пять
секунд документ, расположенный по адресу h t t p : / / h o s t / p a t h , надо вызвать ме
тод s e t Header следующим образом:
response.setHeader("Refresh", "5; URL=http://host/path/")
19.10. Ответ сервлета: поля заголовка 871
Retry-After
Данное поле заголовка используется с кодом состояния 503 ( S e r v i c e
U n a v a i l a b l e ) и сообщает броузеру, как скоро он должен повторить запрос.
Set-Cookie
Поле S e t - C o o k i e содержит запись cookie, связанную с Web-страницей. Для каж
дой записи cookie требуется отдельное поле S e t - C o o k i e . В сервлетах нельзя ис
пользовать вызов r e s p o n s e . s e t H e a d e r ( " S e t - C o o k i e " , . . . ), вместо этого на
до применять метод addCookie класса H t t p S e r v l e t R e s p o n s e . Подробно записи
cookie рассматриваются в разделе 19.11. Поле S e t - C o o k i e не является частью
протокола HTTP 1.1. Средства cookie были предложены Netscape, а в настоящее
время их поддерживают и Netscape, и Internet Explorer.
www-Authenticate
Данное поле всегда включается в состав заголовка ответа с кодом состояния 401
(Unauthorized). Оно сообщает броузеру, какая информация должна содержаться
в поле A u t h o r i z a t i o n . Чаще всего сервлеты не выполняют непосредственных
действий с этим полем, а позволяют специализированным средствам Web-сервера
обрабатывать документы, защищенные паролем.
Листинг 1 9 . 1 7 . P r i m e N u m b e r s . J a v a
package cwp;
import java.io.*;
import javax.servlet.*;
import javax. servlet.http. "^;
import java.util.*;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Some " + numDigits + "-Digit Prime Numbers";
out.printIn(ServletUtilities.headWithTitie(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H2 ALIGN=CENTER>" + title + "</H2>\n" +
"<H3>Primes found with " + numDigits +
" or more digits: " + numCurrentPrimes +
".</H3>");
if (isLastResult)
out.println("<B>Done searching.</B>");
else
out.println("<B>Still looking for " + numPrimesRemaining +
" more<BLINK>...</BLINK></B>");
out.println("<0L>") ;
for(int i=0; i<numCurrentPrimes; i++) {
out.println(" <LI>" + currentPrimes.elementAt(i));
}
out.println("</0L>");
out.println("</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
doGet(request, response);
}
// Выяснить, имеются ли результаты или ведутся ли вычисления
// такого же количества простых чисел с таким же количеством
// цифр. Если подходящие результаты существуют, они
// возвращаются броузеру, а новый поток не создается.
// Размеры списка результатов невелики, и его поддержка
/ / н е требует большого объема памяти. Доступ к списку
// синхронизируется.
<BODY BGC0L0R="#FDF5E6">
<H2 ALIGN="CENTER">Finding Large Prime Numbers</H2>
<BR><BR>
<CENTER>
<FORM A C T I O N = " / s e r v l e t / c w p . PrimeN\ambers">
<B>Number of primes to calculate:</B>
<INPUT TYPE="TEXT" NAME="numPrimes" VALUE=25 SIZE=4><BR>
<B>Number of digits:</B>
<INPUT TYPE="TEXT" NAME="numDigits" VALUE=150 SIZE=3><BR>
<INPUT TYPE="SUBMIT" VALUE="Start Calculating">
</FORM>'
</CENTER>
</BODY>
</HTML>
ШШ
-^^ ^ 3 .Й ^^- Si s ui 3 Jl
Finding Large Prime Numbers
i-inixf
^тБшшшяшшшшшшшт
^- -У 3 '^ ^ ^ ^s ^ 3 Ш
Some 125-Digit Prime Numbers
Primes fomid with 125 or mote digits: S.
1. 25955811439632246588281060898749698746124929689978474726713518542454
2. 25955811439632246588281060898749698746124929689978474726713518542454
3. 25955811439632246588281060898749698746124929689978474726713518542454
4. 25955811439632246588281060898749698746124929689978474726713518542454
5. 25955811439632246588281060898749698746124929689978474726713518542454
6. 25955811439632246588281060898749698746124929689978474726713518542454
7. 25955811439632246588281060898749698746124929689978474726713518542454
8 25955811439632246588281060898749698746124929689978474726713518542454
±1
:У«;==й>-: ,GI
Рис. 19.12. Промежуточные результаты обработки запроса
сервлетом PrimeNumbers. Эти данные могут отображаться
после очередной автоматической перезагрузки страницы либо в
том случае, если сервлет воспользовался результатами обра
ботки одного из предыдущих запросов. В любом случае для
получения обновленных данных броузер должен повторно обра
титься к сервлету
Done searching;
1. 2595581 14396322465882810608987496987461249296899784747267135185424
2. 2595581 14396322465882810608987496987461249296899784747267135185424
3. 2595581 14396322465882810608987496987461249296899784747267135185424
4. 2595581 14396322465882810608987496987461249296899784747267135185424
5. 2595581 14396322465882810608987496987461249296899784747267135185424
6. 2595581 14396322465882810608987496987461249296899784747267135185424
7. 2595581 14396322465882810608987496987461249296899784747267135185424
8. 259558 14396322465882810608987496987461249296899784747267135185424
9. 2595581 14396322465882810608987496987461249296899784747267135185424
in osQ*;*;??!
Li 14'?0Л^О0Л^'^ЙЙГ)01ПЛПЙОЯ74аЛ<5Я7ЛЛ174000ЛЯ007О47^7')>;71?^1Я';4':>АЗ]
f^'^ii^'.
Document Done ':^.2к-._::^.Ж^.:.Ш...,.^г^ ' /
Листинг 1 9 . 1 9 . P r i m e L i s t . J a v a
p a c k a g e cwp;
Листинг 19.20.Primes.Java
package cwp;
import Java.math.Biglnteger;
package cwp;
import javax.servlet.*;
import javax.servlet.http.*;
V
public static int getlntParameter(HttpServletRequest request.
String paramName,
int defaultValue) {
String paramString = request.getParameter(paramName);
int paramValue;
try {
paramValue = Integer.parseint(paramString);
} catch(NumberFormatException nfe) { // null или
// некорректный формат
paramValue = defaultValue;
}
return(paramValue);
}
1 9 . 1 1 . Cookie
Запись cookie представляет собой небольшой фрагмент текста, который Web-
сервер передает броузеру и который броузер должен вернуть при последующем визи
те на тот же сервер или в тот же домен. Возможность сервера получать информацию,
переданную ранее клиенту, позволяет представить док}^меит в том виде, в котором
пользователь в прошлый визит завершил с ним работу, автоматически идентифици
ровать пользователя и выполнять другие важные задачи. Большинство броузеров не
сохраняет в кэше документы, с которыми связаны записи cookie.
В данном разделе рассматриваются вопросы установки и чтения записей cookie в серв-
летах, а следующий раздел посвящен поддержке сеанса взаимодействия с сервлетом.
Настройка узла
Многие узлы, реализованные как "порталы", предоставляют возможность изменять
внешний вид главной страницы в соответствии со вк)тами пользователя. Они позволя
ют разместить на страгп^це прогноз погоды, данные о котировке акций, результаты
спортивных соревнований и прочие данные. Поскольку' настраивать главную страницу
при каждом визите на узел неудобно, для запоминания установок, выполненных ранее,
применяются средства cookie. Если настройка Web-страницы не предполагает сложных
действий, требуемый набор параметров может непосредственно сохраняться в записи
cookie. Если же для запоминания состояния док)^1ента необходимо хранить большой
объем данных, то клиенту передается лишь идентификатор, по которому сервер нахо
дит в базе данных необходимые значения характеристик.
Создание cookie
Для создания cookie надо вызвать конструктор Cookie, передав ему два строковых
параметра: имя и значение cookie. Н и имя, ни значение не должны содержать сле
дующие символы:
[ ] ( ) = , « / ? @ : ;
Атрибуты cookie
Перед тем как включать запись cookie в заголовок ответа, необходимо задать не
которые характеристики cookie, используя для этого методы s e t X x x (где Ххх опреде
ляет имя атрибута). Каждому методу s e t X x x соответствует метод getXxx, позволяю
щий прочитать значение атрибута. В отличие от имени и значения, атрибуты cookie
применимы только к записям cookie, которые сервер передает клиенту; в составе
cookie, возвращаемых клиентом серверу, атрибуты отсутствуют.
public String g e t C o m m e n t O
public void s e t C o m m e n t ( S t r i n g c o m m e n t )
Метод s e t C o m m e n t устанавливает, a метод getComment возвращает строку ком
ментариев, связанную с cookie. Согласно версии О протокола Cookie (см. описание
методов g e t V e r s i o n и s e t V e r s i o n ) , комментарии используются исключительно
на стороне сервера и клиенту не передаются.
гда, однако в некоторых случаях имя используется как логический флаг и значение
игнорируется (т.е. само наличие cookie с определенным именем предоставляет
достаточную информацию).
Листинг 19.22.SetCookies.Java
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/•• Устанавливаются шесть значений cookie. Три из них
* действительны только в течение сеанса (независимо от
* того, сколько времени он длится). Три других
* действительны в течение часа (даже если броузер
* перезагружается).
V
public class SetCookies extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
for(int i=0; i<3; i++) {
/ / П о умолчанию значение maxAge равно -1, т.е.
// запись cookie действительна только в течение
// текущего сеанса.
Cookie cookie = new Cookie("Session-Cookie-" + i,
"Cookie-Value-S" + i ) ;
response.addCookie(cookie);
1 9 . 1 1 . Cookie 887
1^И1И'тШ|1
£te £(й ^mi FavoKes loefe Нф
~3
Setting Cookies
There are six cookies associated with this page. To see them, visit
the showCooicieg setvlst.
Three of the cookies are associated only with the current session,
v^ue three are persistent. Quit the browser, restart, and return to the
ShowCooJcies servlet to verify that the three long-lived ones persist
across sessions.
Листинг 1 9 . 2 3 . S h o w C o o k i e s . J a v a
package cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Создание таблицы cookie, связанных с текущей
888 Глава 19. Java на стороне сервера: сервлеты
страницей.
Ч
Ji
Active Cooldes Active Cookies
Cooki? Katm« Cookie Vn]u«
Session-Cookie-0 Cookie-Value-SO Persistent-Coobe-O Cookie-Value-PO
Persistent-Cookie-0 Coobe-Value-PO P ersistent- С о okic -1 С о okie - Value -P1
Session-Coobe-1 Coobe-Value-Sl Persistent-Cookie-2 Cookie-Value-P2
Persistent-Cookie-1 Coobe-Value-Pl
Session-Cookie-2 Cooloe-Value-S2
Persistent-Co окне-2 Cookie-Value-P2
J
•;^Done Igi Loccil ir*ari8t ^Oone |sjLoe^»*afiet • - '
Листинг 1 9 , 2 4 . S e r v l e t U t i l i t i e s . Java
p a c k a g e cwp;
import javax.servlet.*;
import javax.servlet.http.*;
package cwp;
import javax.servlet.http.*;
Использование cookie
Записи cookie можно использовать для храненияя и н ф о р м а ц и и о сеансе. Напри
мер, сервлет может выполнять следующие действия:
String sessionID = makeUniqueString();
H a s h t a b l e s e s s i o n l n f o = new H a s h t a b l e O ;
Hashtable globalTable = f i n d T a b l e S t o r i n g S e s s i o n s ( ) ;
globalTable.put(sessionID, sessionlnfo);
Cookie s e s s i o n C o o k i e = new C o o k i e ( " J S E S S I O N I D " , s e s s i o n I D ) ;
sessionCookie.setPathC'/") ;
response.addCookie(sessionCookie);
При очередном запросе сервер может использовать таблицу g l o b a l T a b l e , чтобы
посредством идентификатора сеанса, полученного в составе записи cookie, найти
таблицу данных, соответствующих конкретному сеансу. Такой подход часто использу
ется, однако, следует заметить, что при создании сервлета можно пользоваться высо
коуровневыми средствами API, которые выполняют следующие задачи.
• Извлечение из набора cookie конкретной записи, содержащей идентификатор
сеанса.
• Установка времени жизни cookie.
• Связывание с каждым запросом хэш-таблицы.
• Создание уникальных идентификаторов сеанса.
Модификация URL
П р и использовании данного подхода к каждому URL, передаваемому на сервер,
присоединяются дополнительные данные, идентифицирующие текущий сеанс. Полу
чив запрос, сервер по идентификатору находит информацию, соответствующую се
ансу. Например, в URL h t t p : / / h o s t / p a t h / f i l e . h t m l ; j s e s s i o n i d = 1 2 3 4 присут-
892 Глава 19. Java на стороне сервера: сервлеты
Скрытые поля
в составе HTML-формы могут быть элементы наподобие приведенного ниже.
<INPUT TYPE="HIDDEN" NAME="session" VALUE=",..">
При активизации ф о р м ы имя и значение этого элемента будут переданы методом
GET или POST на сервер в составе строки параметров. Скрытые поля могут приме
няться для хранения и н ф о р м а ц и и о сеансе. Недостаток их состоит в том, что они мо
гут использоваться только в динамически генерируемых документах.
создан. Для того чтобы объект сеанса создавался автоматически, надо при вызове ме
тода g e t S e s s i o n передать ему параметр t r u e . Вызов метода выглядит следующим
образом:
HttpSession s e s s i o n = r e q u e s t . g e t S e s s i o n ( t r u e ) ;
Если вас интересует, существовал ли объект сеанса ранее или был создан при по
следнем вызове метода g e t S e s s i o n , вы можете использовать для проверки метод
isNew.
ShoppingCart cart =
(ShoppingCart)session.getAttribute("previousltems");
if (cart == null) { // "Корзина" не создана
cart = new ShoppingCart();
session.setAttribute("previousltems", cart);
}
String itemID = request.getParameter("itemID");
if (itemID != null) {
cart.addItem(Catalog.getItem(itemID));
}
Завершение сеанса
Как только время между запросами клиента превысит значение, заданное посред
ством s e t M a x I n a c t i v e I n t e r v a l , сеанс автоматически завершается. П р и этом раз
рывается связь объектов с ключевыми значениями. Для объектов, реализующих ин
т е р ф е й с H t t p S e s s i o n B i n d i n g L i s t e n e r , также вызывается метод v a l u e U n b o u n d .
Вместо того чтобы дожидаться окончания времени жизни сеанса, его можно за
вершить принудительно, вызвав метод i n v a l i d a t e .
М е т о д и к а профессионалов
p a c k a g e cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
import java.util.*;
/** Простой пример поддержки сеанса. */
public class ShowSession extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, lOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Session Tracking Example";
HttpSession session = request.getSession(true);
String heading;
Integer accessCount =
(Integer)session.getAttribute("accessCount");
if (accessCount == null) {
accessCount = new Integer(0);
heading = "Welcome, Newcomer";
} else {
heading = "Welcome Back";
accessCount = new Integer(accessCount.intValue() + 1)
}
// Вместо putValue используется setAttribute.
898 Глава 19. Java на стороне сервера: сервлеты
session.setAttribute("accessCount", accessCount);
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGC0L0R=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + heading + "</Hl>\n" +
"<H2>Information on Your Session:</H2>\n" +
"<TABLE B0RDER=1 ALIGN=\"CENTER\">\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
" <TH>Info Type<TH>Value\n" +
"<TR>\n" +
" <TD>ID\n" +
" <TD>" + session. getldO + "\n" +
"<TR>\n" +
" <TD>Creation Time\n" +
ft <TD>" +
new Date(session.getCreationTime()) + "\n" +
"<TR>\n" +
" <TD>Time of Last AccessXn" +
" <TD>" +
new Date(session.getLastAccessedTime() ) + "\n" 4
"<TR>\n" +
" <TD>Nuinber of Previous Accesses\n" +
" <TD>" + accessCount + "\n" +
"</TABLE>\n" +
"</BODY></HTML>");
1сА-ит*д!иш1ди,1.]1Л1ДЛУШЛ1.и
Ftie Edit ytew Q,o jQomrmKBcetor йе^
^ •>" 3 Й ^^ i^a c# rf Q Ш fil
Welcome Back
Information on Your Session:
Ш Tol010mC6608409833952431At
Creation Time Mon Apr 16 10:41:25 EDT 2001
Time of Last Access Mon Apr 16 10:44:54 EDT 2001
Number of Previous Accesses 10
19.13. Резюме
Сервлеты представляют собой эффективное, мощное и недорогое средство, высту
пающее в качестве альтернативы CGI-программам и другим технологиям создания про
грамм, выполняющихся на стороне сервера. Помимо преимуществ, сервлеты имеют
важный недостаток: они должны генерировать HTML-документы. Использовать метод
p r i n t In для создания больших разделов Web-страниц неудобно, а сопровождение
сервлета, выполняющего такие действия, сопряжено со значительными трудностями.
Кроме того, код, генерирующий данные, объединен с кодом, представляющим их, что
затрудняет создание сервлета двумя отдельными группами разработчиков. Эти пробле
мы решает технология JSP, которая будет рассмотрена в следующей главе.
JAVASERVER PAGES
В ЭТОЙ главе...
• Преимущества JSP.
• Использование JavaBeans.
М е т о д и к а профессионалов ^Ц^
Приступая к отладке JSP, убедитесь, что в Internet Explorer 5.0 от- ЩШШШк
ключей вывод подробных сообщений об ошибках. ^^^^^ш
енту без изменений и для его создания может быть использован любой инструмент,
предназначенный для генерации Web-страниц. Для создания документов JSP, приве
денных в данной книге, мы использовали Allaire HomeSite.
П р и создании текста шаблона необходимо придерживаться следующих правил. Во-
первых, если вы хотите передать в выходной поток символы "<%", в текст шаблона
необходимо включить последовательность "<\%". Во-вторых, если вы хотите, чтобы
комментарии JSP не были помещены в состав сгенерированного документа, их надо
оформить в следующем виде:
<%-- Комментарии JSP --%>
Комментарии HTML, заданные в формате
<!-- Комментарии HTML -->
будут включены в состав HTML-документа.
Выражения
JSP-выражения используются для того, чтобы непосредственно включать требуе
мые значения в состав выходных данных сервлета. Выражение задается в формате
<^o= Выражение Java %>
Выражение вычисляется, преобразуется в строковый вид и включается в состав
документа. Вычисление выражения осуществляется после получения запроса клиен
та, при этом может использоваться информация, содержащаяся в запросе. Например,
в следующем примере выражение вю1ючает дату и время обращения клиента к JSP:
C u r r e n t t i m e : <%= new J a v a . u t i l . D a t e () %>
В результате в тело метода j s p S e r v i c e (вызываемого из метода s e r v i c e ) будут
помещены следующие строки кода:
out.print("Current time: " ) ;
out.println(new Java.util.Date ());
Предопределенные переменные
п р и вычислении выражений могут использоваться предопределенные перемен
ные; наиболее важные из этих переменных и объекты, которым они соответствуют,
перечислены ниже. (Подробно предопределенные переменные будут рассмотрены
ниже в этом разделе.)
• request — объект H t t p S e r v l e t R e q u e s t .
• response — объект H t t p S e r v l e t R e s p o n s e .
• session— объект H t t p S e s s i o n , связанный с запросом (он может быть запре
щен посредством атрибута s e s s i o n директивы p a g e — см. раздел 20.4).
• out — объект P r i n t W r i t e r , используемый для передачи выходных данных клиенту.
П р и м е р использования предопределенных переменных приведен ниже.
Your h o s t n a m e : <%= r e q u e s t . g e t R e m o t e H o s t ( ) %>
906 Глава 2 0 . JavaServer Pages
Установка JSP-документов
П р и создании сервлетов необходимо задавать значение переменной окружения
CLASS PATH и использовать пакеты для устранения конфликтов имен. П р и обращении
к сервлетам клиенты должны указывать специальные URL. В отличие от сервлетов,
JSP могут размещаться в тех же каталогах, что и обычные HTML-документы, изобра
жения и листы стилей. П р и обращении к JSP указываются такие же URL, как и при
обращении к Web-страницам, изображениям и прочим подобным ресурсам. Ниже
приведено несколько примеров размещения JSP и URL, используемых для обращения
к ним (здесь h o s t означает имя или адрес узла).
Каталог, и с п о л ь з у е м ы й с е р в е р о м T o m c a t
install_dir\webapps\ROOT
install_dir\webapps\ROOT\anyDir
Каталог, и с п о л ь з у е м ы й с е р в е р о м J R u n
install_diг\servers\default\default-app
install_dir\servers\default\default-app\anyDir
http://host/filename.jsp
http://host/anyDir/filename.jsp
2 0 . 3 . Элементы сценариев JSP 907
Листинг 2 0 , 1 . E x p r e s s i o n s . j sp
£te i * У « « я о Convaunicato»
; ^^ ^ 3 й J>!t i ^ ^:f rf Q^ ^Й Щ
JSP Expressions
• Current time: Mon Aug 07 15:06:27 EDT 2000
• Your hostname: 127.0.0,1
• Your session Ш: Tol010mC22565256379010112At
• The t e s t P a r am form parameter: null
Рис. 20.1. Результаты обращения
'^ - i i -Л.. к Expressions.jsp
Скриптлеты
Если вы хотите выполнить действия более сложные, чем включение выражения,
можете использовать скриптлеты. Скриптлеты позволяют помещать произвольный
Java-код в тело метода _ j s p S e r v i c e сервлета (вызываемого из метода s e r v i c e ) .
Скриптлеты задаются в следующем формате:
<% Java-код %>
Скриптлетам, как и выражениям, доступны предопределенные переменные
( r e q u e s t , r e s p o n s e , s e s s i o n , o u t и т.д.). Так, если вы хотите, чтобы некоторые
данные появились в составе результирующей страницы, можете воспользоваться пе
ременной o u t .
<%
String queryData = request.getQueryString();
out.println("Attached GET data: " + queryData);
%>
В данном конкретном примере можно добиться тех же результатов гораздо проще,
используя след}^ющее выражение:
A t t a c h e d GET d a t a : <%= r e q u e s t . g e t Q u e r y S t r i n g ( ) %>
Однако в целом с к р и т л е т ы являются более универсальным средством и мог)^ вы
полнять задачи, недоступные выражениям. В качестве примера таких задач можно
привести установку кода состояния и полей заголовка ответа, обеспечение побочных
эффектов, таких как запись данных в файл протокола или обновление базы данных,
организация циклов, выполнение условных выражений и т.д. Например, следующая
строка кода указывает, что документ, передаваемый клиенту, является текстовым до
кументом и в нем отсутствуют HTML-дескрипторы:
<% r e s p o n s e . s e t C o n t e n t T y p e ( " t e x t / p l a i n " ) ; %>
Заметьте, что устанавливать код состояния и поля заголовка можно в любой части
JSP, даже если на первый взгляд это выглядит как нарушение правила (согласно кото
рому поля заголовка должны быть установлены до начала передачи содержимого до
кумента). Это допустимо потому, что в JSP используется специальный тип потока
( J s p W r i t e r ) , выполняющий частичную буферизацию документа. Возможности бу
феризации могут быть изменены; подробнее об этом разговор пойдет в разделе 20.4.
20.3. Элементы сценариев JSP 909
Пример включения в состав JSP фрагмента кода, более сложного, чем JSP-
выражение, приведен в листинге 20.2. В данном случае для установки цвета фона ис
пользуется значение параметра bgColor, переданного в составе запроса. Результаты
обращения в данному JSP показаны на рис. 20.2 и 20.3.
|.y.'P|jlffl|Wi|i.i.l|Jl.l|.!I^I^IIJ.!JIJi].!).l|Ji|l
Fiis £di' \V4-v Fiivortes Joois Help
Рис. 20.2. Выходные данные, генерируемые Рис. 20.3. Результаты обращения к BGColor.
BGColor. j sp по умолчанию j s p при использовании в качестве значения
параметра bgColor RGB-кода СОСОСО
910 Глава 2 0 . JavaServer Pages
Декларации
Декларации JSP позволяют включать методы и поля в класс сервлета (за пределами
метода j s p S e r v i c e , вызываемого из метода s e r v i c e ) . Декларации задаются в сле
дующем формате:
<%! Java-код %>
Поскольку декларации не генерируют выходные данные, они обычно применяются
в сочетании с JSP-выражениями или скриптлетами. Методы и поля, определяемые дек
ларациями, используются в выражениях или скриптлетах. Не следует, однако, с помо
щью деклараций пытаться переопределить методы, влияющие на жизненный цикл
сервлета ( s e r v i c e , d o G e t , i n i t и т.д.). Эти методы используются сервлетом, в кото-
2 0 . 3 . Э л е м е н т ы с ц е н а р и е в JSP 911
рый преобразуется JSP. Нет необходимости прибегать к услугам декларации, чтобы по
лучить доступ к методу s e r v i c e , d o G e t или do P o s t , поскольку из тела s e r v i c e авто
матически вызывается метод _ j s p S e r v i c e , в который помещается код, реализующий
выражения и скриптлеты. Для инициализации сервлета и освобождения занимаемых
ресурсов вы можете использовать методы j s p l n i t и j s p D e s t r o y . При выполнении
сервлета они обязательно будут вызваны из методов i n i t и d e s t r o y .
На з а м е т к у
Листинг 1 0 . 3 . A c c e s s C o u n t s . j s p
^SZBB
ffc £ * t ^lew go jQomiTiuracator Ь ф
^: -/ 3 й ^^ Й ^л rf L^ Щ iS
^^^Bocfemafk* ^4i toc^^mjhtlp //localhost/'cwpAccessCounts jsp |^|
JSP Declarations
Accesses to page since server
reboot: 10
Рис. 20.4. Результаты очередного
; ^ b » ^ '
. >«;* '^^„ .ел \г^ обращения клиента к AccessCounts. j sp
Предопределенные переменные
Для того чтобы упростить процесс создания JSP-выражений и скриптлетов, разра
ботчику предоставляется ряд автоматически определяемых переменных, которые
иногда называют предопределенными объектами. Поскольку код, создаваемый на базе
деклараций, располагается за пределами метода _ j s p S e r v i c e , в декларациях эти пе
ременные недоступны. К предопределенным переменным относятся r e q u e s t ,
r e s p o n s e , o u t , s e s s i o n , a p p l i c a t i o n , config,pageContext и page.
request
Данная переменная ссылается на объект H t t p S e r v l e t R e q u e s t , представляющий
запрос клиента. С ее помощью можно определить тип запроса (например, GET или
POST) или получить доступ к полям заголовка.
response
Переменная r e s p o n s e ссылается на объект H t t p S e r v l e t R e s p o n s e , связанный с
ответом, передаваемым клиенту. Поскольку выходной поток буферизуется (см.
описание переменной o u t ) , работая с JSP, можно устанавливать код состояния и
заголовки. Как вы знаете, в сервлетах эти действия допустимы только до начала
передачи данных клиенту.
out
Данная переменная предоставляет доступ к объекту P r i n t W r i t e r , который при
меняется для передачи данных клиенту. Для того чтобы в JSP можно было рабо
тать с переменной r e s p o n s e , используется вариант P r i n t W r i t e r с поддержкой
буферизации под названием J s p W r i t e r . Управлять размером буфера можно с по
мощью атрибута b u f f e r директивы p a g e . Переменная o u t используется преиму-
20.4. Директива page 913
session
Данная переменная представляет объект H t t p S e s s i o n , связанный с запросом.
Объект сеанса создается автоматически, поэтому данная переменная доступна все
гда, за исключением тех случаев, когда поддержка сеанса явно отключена с помо
щью атрибута s e s s i o n директивы p a g e . Попытка обращения к переменной
s e s s i o n при отключенной поддержке сеанса приведет к возникновению ошибки
на этапе преобразования JSP в сервлет.
application
Переменная a p p l i c a t i o n ссылается на объект S e r v l e t C o n t e x t , полученный с
помощью вызова g e t S e r v l e t C o n t e x t . Сервлеты и JSP могут использовать объект
S e r v l e t C o n t e x t для постоянного хранения данных, вместо того, чтобы поме
щать их в переменные экземпляра. В классе S e r v l e t C o n t e x t определены методы
s e t At t r i b u t e и g e t A t t r i b u t e , которые позволяют записывать произвольные
данные, связанные со специальными ключами. Разница между хранением инфор
мации в переменных экземпляра и в объекте S e r v l e t C o n t e x t состоит в том, что
S e r v l e t C o n t e x t совместно используется всеми сервлетами, выполняющимися в
среде сервера (или в рамках Web-приложения).
config
Данная переменная представляет объект S e r v l e t C o n f i g для данного документа.
pageContext
В JSP определен новый класс с именем P a g e C o n t e x t , предназначенный для орга
низации доступа к различным атрибутам документа и хранения разделяемых дан
ных. Переменная p a g e C o n t e x t хранит ссылку на объект P a g e C o n t e x t , связан
ный с текущей страницей.
page
Эта переменная является синонимом переменной t h i s и используется достаточно
редко. Предполагается, что она окажется полезной в будущем, когда в JSP будут
поддерживаться другие языки помимо Java.
Атрибут import
Атрибут i m p o r t директивы p a g e позволяет определять пакеты, импортируемые
сервлетом, в который преобразуется JSP-документ. Если вы явно не укажете импорти
руемые классы, сервлет по умолчанию импортирует j a v a . l a n g . *, j a v a x . s e r v l e t . *,
j a v a x . s e r v l e t . j s p . *, j a v a x . s e r v l e t . h t t p . * и, возможно, некоторые пакеты,
специфические для конкретного сервера. Создавая JSP, следует явно импортировать
все пакеты, кроме указанных, поскольку при переходе на другой сервер набор паке
тов, импортируемых по умолчанию, может измениться. Атрибут i m p o r t задается в
одном из двух следующих форматов:
<%@ p a g e i m p o r t = " p a c k a g e . c l a s s " %>
<%@ p a g e i m p o r t = " p a c k a g e . c l a s s l , . . . , p a c k a g e . c l a s s N " %>
Так, например, если в составе документа встречается приведенная ниже директи
ва, это означает, что все классы, входящие в состав J a v a . u t i l , могут использоваться
без явного указания имени пакета.
<%@ p a g e i m p o r t = " J a v a . u t i l . * " %>
Атрибут i m p o r t — единственный из атрибутов директивы p a g e , который может
многократно использоваться в составе одного документа. Несмотря на то что дирек
тиву p a g e разрешено включать в любую точку документа принято располагать выра
жения i m p o r t в начале документа, либо, по крайней мере, перед первым использова
нием класса, входящего в импортируемый пакет.
Заметьте, что разные серверы придерживаются различных правил относительно
того, где следует располагать определенные типы файлов классов. Например, при ра
боте с Java Web Server 2.0 классы сервлетов помещаются в каталог s e r v l e t s, но при
этом классы, используемые сервлетами или JSP, должны находиться в каталоге
20.4. Директива page 915
Листинг20.4. ImportAttribute. j s p
оозв
Re 1<а Vww Fjvmites Jools МФ
Ещвавш^^вш
\ £fe £<St ^вл Fjvonle» Juofe Help
Рис. 20.5. Результаты первого обращения Рис. 20.6. Результаты одного из последую
к I m p o r t A t t r i b u t e . j sp щих обращений к I m p o r t A t t r i b u t e . j sp
Атрибут contentType
Атрибут c o n t e n t T y p e позволяет задавать значение поля заголовка C o n t e n t -
Type, определяющее М1МЕ-тип документа, передаваемого клиенту. Дополнительную
информацию о MIME-типах вы найдете в разделе 19.10. Наиболее часто используемые
MIME-ТИПЫ перечислены в табл. 19.1.
Атрибут c o n t e n t T y p e задается в одном из следующих форматов:
<%@ page contentType="MIME-Type" %>
<%@ page contentType="MIME-Type; charset=Character-Set" %>
Например, директива
<%@ page contentType="application/vnd.ms-excel" %>
Листинг 2 0 , 5 . E x c e l . j s p
• ^ 3 4 aija:i3-J)-J mg.
Add»e«|#J http /Vlocaihosl/'cwp/Excei (Sfj
d
I P7C6 ^ «
1 ,^ _J_ 3„ _ 4 6__
Last Email Address
±:\
1 1 'First "
l_2_ Marty Hall halh^corewebprogramming.com """I
ГЗ"''Larry Brown brown@corewebprogrannmmg com |
1 4 J Bill Gates gates@sun com
j 5 Larry Ellison elliscn^micrcsoft com ^^ |
1И 4 • W \ E K c e l /
\*\ ! >\r\ Рис. 20.7. Документ Excel ( E x c e l . j sp),
отображаемый в броузере Internet Explorer
Атрибут isThreadSafe
Атрибут i s T h r e a d S a f e позволяет определить, должен ли сервлет, созданный на
основе JSP, реализовать и н т е р ф е й с S i n g l e T h r e a d M o d e l . Этот атрибут задается в
одном из двух форматов:
<%0 p a g e i s T h r e a d S a f e = " t r u e " %> <%-- По умолчанию —%>
<%@ p a g e i s T h r e a d S a f e = " f a l s e " %>
В обычных сервлетах каждый новый запрос выполняется в отдельном потоке. П р и
этом предполагается, что разработчиком сервлета приняты меры, необходимые для
нормальной обработки разделяемых данных разными потоками. К таким мерам отно
сится синхронизация доступа к данным, позволяющая исключить их разрушение из-за
одновременного обращения из различных потоков. В одних сл}^чаях (как, например,
при подсчете посетителей) не стоит беспокоиться о том, что два клиента могут полу
чить одно и то же значение, в других случаях (например, при определении иденти
фикаторов пользователей) тот же результат означает грубую ошибку. Например, при
веденный ниже фрагмент кода не обеспечивает корректную многопотоковую обра
ботку, поскольку выполнение потока может быть прервано между чтением idNum и
записью нового значения, что приведет к появлению двух пользователей с одинако
выми идентификаторами.
<%! private int idNum = 0; %>
<%
String userlD = "userlD" + idNum;
out.println ("Your ID is " 4- userlD + " . " ) ;
idNum = idNum + 1;
%>
Ч т о б ы данный фрагмент кода выполнялся корректно, его надо поместить в блок
synchronized.
synchronized(someObject) { }
В этом случае, если поток начал обработку блока, ни один другой поток не может
выполнить аналогичный блок кода до тех пор, пока первый поток не завершит работу
с синхронизированным фрагментом. П р и использовании блока s y n c h r o n i z e d при
веденный выше фрагмент примет следующий вид:
<%! private int idNum = 0; %>
<%
918 Глава 20. JavaServer Pages
synchroni zed(thi s) {
String userlD = "userlD" + idNum;
out.println("Your ID is " + userlD + " . " ) ;
idNum = idNum + 1;
}
%>
Если же сервлет реализует интерфейс S i n g l e T h r e a d M o d e l , система гарантирует,
что один экземпляр сервлета не будет использован для одновременной обработки
двух различных запросов. Ч т о б ы обеспечить подобные условия, система либо создает
очередь запросов к одному экземпляру сервлета, либо создает пул экземпляров, каж
дый из которых обслуживает отдельный запрос.
Задавая директиву <%@ p a g e i s T h r e a d S a f e = " f a l s e " %>, вы указываете на то,
что ваш код не обеспечивает корректную многопотоковую обработку, поэтому серв
лет, созданный на основе JSP, должен реализовывать и н т е р ф е й с S i n g l e T h r e a d
Model. По умолчанию предполагается значение t r u e данного атрибута, т.е. сервлет
обеспечивает более высокую производительность за счет многопотоковой обработки
запросов в рамках одного экземпляра сервлета.
Атрибут session
Атрибут s e s s i o n указывает, должен ли данный документ поддерживать НТТР-
сеанс. Данный атрибут задается в одном из следующих форматов:
<%@ p a g e s e s s i o n = " t r u e " %> <%— По умолчанию --%>
<%@ p a g e s e s s i o n = " f a l s e " %>
Значение t r u e указывает на то, что предопределенную переменную s e s s i o n
(типа H t t p S e s s i o n ) необходимо связать с текущим объектом сеанса, если тот суще
ствует. Если объект сеанса отсутствует, необходимо создать новый объект и связать
его с переменной s e s s i o n . Значение f a l s e указывает на то, что объект сеанса не
должен быть использован. В этом случае попытка обращения к переменной s e s s i o n
приведет к тому, что при преобразовании JSP в сервлет возникнет ошибка. Запрет
поддержки сеанса позволяет сэкономить память сервера. Следует помнить, что под
держка сеанса ориентирована на пользователя, а не на документ. Поэтому нельзя от
ключить поддержку сеанса для одного документа, не отключив его для других доку
ментов, посещаемых тем же самым клиентом.
Атрибут buffег
Атрибут b u f f e r определяет размер буфера, используемого объектом, на который
ссылается предопределенная переменная o u t (обычно это экземпляр класса
J s p W r i t e r , являющегося подклассом класса P r i n t W r i t e r ) . Данный атрибут задается
в одном из следующих форматов:
<%@ p a g e b u f f e r = " p a 3 M e p k b " %>
<%@ p a g e b u f f e r = " n o n e " %>
Размер буфера, используемого сервлетом, может превышать заданный вами, но не
может быть меньше этого размера. Например, директива <%@ p a g e b u f f e r = " 3 2 k b "
20.4. Директива page 919
%> означает, что содержимое документа должно быть буферизовано и не будет от
правлено клиенту до тех пор, пока объем данных, записанных в буфер, не достигнет
32 Кбайт, либо до тех пор, пока в буфер не будет помещен весь документ. Размер бу
фера по умолчанию различается для разных серверов, но не бывает меньше 8 Кбайт.
Отключая буферизацию, соблюдайте осторожность. Если вы сделаете это, вам при
дется следить за тем, чтобы код состояния и поля заголовка устанавливались в начале
файла, перед выводом содержимого HTML-документа.
Атрибут autoflush
Атрибут a u t o f l u s h позволяет указать, должно ли содержимое выходного буфера
автоматически передаваться по сети при его заполнении, либо при переполнении
буфера должно генерироваться исключение. Значение этого атрибута задается в од
ном из следующих форматов:
<%(? p a g e a u t o f l u s h = " t r u e " %> <%— По умолчанию —%>
<%@ p a g e a u t o f l u s h = " f a l s e " %>
Если указан aTpH6yTbuf f e r = " n o n e " , значение f a l s e недопустимо.
Атрибут extends
Атрибут e x t e n d s описывает суперкласс сервлета, генерируемого на основе JSP, и
задается в следующем формате:
<%@ p a g e e x t e n d s = " p a c k a g e . c l a s s " %>
При использовании данного атрибута следует соблюдать осторожность, поскольку
сервер предполагает, что заданный класс будет выбран в качестве суперкласса сервлета.
Атрибут info
Атрибут i n f o определяет строку, возвращаемую при вызове метода g e t S e r v l e t -
I n f o сервлета. Формат данного атрибута приведен ниже.
<%@ p a g e i n f o = " Т е к с т сообщения" %>
Атрибут errorPage
Атрибут e r r o r P a g e задает JSP для обработки исключений (которые описываются
любым подклассом класса T h r o w a b l e ) , не обрабатываемых в рамках текущего доку
мента. Значение атрибута задается в следующем формате:
<%@ p a g e errorPage="относигельный_(7/?Ь" %>
Объект исключения доступен JSP, указанному в качестве значения атрибута, по
средством переменной e x c e p t i o n .
920 Глава 2 0 . JavaServer Pages
Атрибут isErrorPage
Данный атрибут позволяет определить, может ли текущий документ использо
ваться другим JSP-документом для обработки исключений. Значение атрибута
i s E r r o r P a g e задается в одном из следующих форматов:
<%@ page isErrorPage="true" %>
<%@ page isErrorPage="false" %> <%-- По умолчанию — % >
Атрибут language
Предполагается, что в дальнейшем атрибут l a n g u a g e будет определять исполь
зуемый язык программирования, например:
<%@ p a g e l a n g u a g e = " c o b o l " %>
В настоящее время этот атрибут не применяется, поскольку единственным допус
тимым значением является значение Java по умолчанию.
Х1\/И'представление директив
Некоторые серверы позволяют использовать для директив XML-синтаксис. П р и
этом определение директивы принимает следующий вид:
< j s p : d i r e c t i v e . т и л _ л и р е к г и в ы атрибут="значение" />
Например, XML-эквивалент директивы
<%@ p a g e i m p o r t = " j a v a . u t i l . * " %>
выглядит следующим образом:
<jsp:directive.page import="Java.util.*" />
Внимание!!
Листинг20.6. C o n t a c t S e c t i o n . j s p
Листинг 2 0 . 7 . S o m e R a n d o m P a g e . j s p
^o(iдf.!ДЯgШt^||J:iJЛJ!pлaLШ^!l^•li[p•pp•^ СбШ
fa« Edrt Ytew fit? iJommunJcflttof Йе1р ^
Ibis page © 2001 mv-cornpanv.com. This page has been accessed 9 times since sorer
reboot. It was last accessed from localhost at Mon Apr 16 10:57:51 EDT 2001.
у «^^' 'Document Done
Листинг 2 0 . 8 . WhatsNew . j s p
Листинг20.10. Item2.html
^->','^.?П.'ПТ1ГЯ.'НЯВ
Java 2 (т.е. JDK 1.2 или 1.3). Отсутствие такой поддержки накладывает на аплеты сле
дующие ограничения.
• П р и необходимости использовать Swing надо копировать Swing-файлы по сети.
Этот процесс занимает много времени и приводит к ошибке при работе с
Internet Explorer 3 и Netscape 3.x и 4.01 — 4.05 (поскольку данные броузеры под
держивают только J D K 1.02).
• В этих аплетах нельзя использовать Java 2D.
• Пакет c o l l e c t i o n s оказывается недоступным.
• Быстродействие аплета уменьшается, поскольку большинство компиляторов
для платформы Java 2 создают гораздо более э ф ф е к т и в н ы й код, чем их предше
ственники.
Чтобы решить эти проблемы, компания Sun разработала дополнительный модуль
для Netscape и Internet Explorer, позволяющий использовать средства Java 2 при ра
боте с различными броузерами. Java Plug-In можно найти по адресу h t t p : / / j a v a .
s u n . c o m / p r o d u c t s / p l u g i n / , кроме того, он входит в составJDK 1.2.2 и более позд
них версий этого пакета. Поскольку размеры Java Plug-In составляют несколько мега
байт, не стоит ожидать, что основная масса пользователей WWW установит на своих
компьютерах этот продукт. С другой стороны, такое решение оказывается вполне
приемлемым для корпоративных сетей intranet. В аплете можно предусмотреть авто
матическую загрузку пакета в случае его отсутствия на каком-либо из компьютеров.
К сожалению, обычный дескриптор APPLET нельзя использовать с Java Plug-In, по
скольку для обработки аплетов, включенных в документ с помощью этого дескриптора,
автоматически применяется встроенная виртуальная машина Java. Вместо этого при ра
боте с Internet Explorer приходится использовать неудобные для восприятия дескрип
торы OBJECT, а при работе с Netscape — дескрипторы EMBED. Более того, в большинстве
случаев разработчик документа не знает, какой именно броузер будет использован на
стороне клиента, поэтому ему приходится помещать в документ OBJECT и EMBED
(включать EMBED в раздел COMMENT дескриптора OBJECT) либо определять тип броузера
на основании данных запроса и соответственно изменять структуру документа. Это тре
бует от разработчика затраты дополнительных усилий и времени.
Элемент j s p : p l u g i n позволяет создавать дескриптор для аплета, использующего
Java Plug-In. В различных серверах эта возможность реализуется по-разному, но в
большинстве случаев в состав сгенерированной Web-страницы включаются как
OBJECT, так и EMBED.
Элемент jsprplugin
Самый простой способ использования j s p : p l u g i n предполагает указание четы
рех атрибутов: t y p e , c o d e , w i d t h и h e i g h t . В качестве значения атрибута t y p e зада
ется a p p l e t , а остальные т р и атрибута используются так же, как и соответствующие
атрибуты дескриптора <APPLET>, с учетом следующих особенностей: имя атрибута
зависит от регистра символов, а значение всегда должно помещаться в одинарные
или двойные кавычки. Например, фрагмент кода
<APPLET CODE="MyApplet.class"
WIDTH=475 HEIGHT=350>
</APPLET>
20.5. Включение файлов и аплетов в состав JSP-документов 927
• archive
Атрибут a r c h i v e применяется аналогично атрибуту ARCHIVE дескриптора
<APPLET> и задает JAR-файл, из которого должны быть загружены классы и
изображения.
• name
Данный атрибут используется для той же цели, что и атрибут NAME дескрипто
ра <APPLET>, т.е. определяет имя аплета. Это имя идентифицирует объект при
работе сценариев, написанных, например, на JavaScript.
• title
Атрибут t i t l e задает заголовок, предназначенный для отображения в качест
ве подсказки либо для индексирования. Такое же назначение имеет редко ис
пользуемый атрибут TITLE дескриптора <APPLET> (и многих других HTML-
элементов, определенных в HTML 4.0).
• j reversion
Данный атрибут определяет требуемую версию Java Runtime Environment
(JRE). По умолчанию принимается значение L L
• iepluginurl
Атрибут i e p l u g i n u r l задает URL Java Plug-In для Internet Explorer. Пользова
телю, на компьютере которого дополнительный модуль отсутствует, будет
предложено скопировать его с указанного узла. П о умолчанию значение данно
го атрибута ссылается на сервер узла Sun, но в сетя^ intranet можно организо
вать копирование Plug-In с локального узла.
• nspluginurl
Атрибут n s p l u g i n u r l задает URL Java Plug-In для Netscape. По умолчанию
данный атрибут ссылается на сервер узла Sun, но в сетях intranet можно орга
низовать копирование Plug-In с локального узла.
Листинг 2 0 . 1 2 . P l u g i n A p p l e t . j s p
<CENTER>
<jsp:plugin type="applet"
code="PluginApplet.class"
width="370" height="420">
</j sp:plugin>
</CENTER>
</BODY>
</HTML>
import javax.swing.*;
/** Данный аплет использует Swing и Java 2D, поэтому для его
* выполнения требуется Java Plug-In.
Листинг 20.14.TextPanel.Java
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
public TextPanel0 {
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = env.getAvailableFontFamilyNames();
fontBox = new JComboBox(fontNames);
setLayout(new BorderLayout() ) ;
JPanel fontPanel = new JPanel();
fontPanel.add(new JLabel("Font:"));
fontPanel.add(fontBox);
JButton drawButton = new JButton("Draw");
drawButton.addActionListener(this);
fontPanel.add(drawButton) ;
20.5. Включение файлов и аплетов в состав JSP-документов 931
add(fontPanel, BorderLayout.SOUTH);
drawingPanel = new DrawingPanel();
fontBox.setSelectedltem("Serif");
drawingPanel.setFontName("Serif");
add(drawingPanel, BorderLayout.CENTER);
}
Листинг 20.15.DrawingPanel.java
import java.awt.*;
import Java.awt.geom.*;
import javax.swing.*;
-* or
Использование JavaBeans
Действие j s p : u s e B e a n позволяет загружать компонент b e a n для использования в
дoк)^мeнтeJSP. JavaBeans очень удобны, поскольку они позволяют повторно использо
вать Java-классы, не нарушая основные принципы работы с JSP.
Приведенная ниже строка кода иллюстрирует простейший способ объявления
компонента b e a n .
<jsp:useBean id="name" c l a s s = " p a c k a g e . C l a s s " />
Такая конструкция означает: создать объект класса, указанного в качестве значе
ния c l a s s , и связать его с переменной, имя которой задано как значение i d . Напри
мер, следующее действие JSP
<jsp:useBean id="bookl" class="cwp.Book" />
может рассматриваться как аналог скриптлета:
934 Глава 20. JavaServer Pages
Листинг 2 0 . 1 6 . S t r i n g B e a n . J a v a
package cwp;
/** Простой компонент bean, который содержит свойство типа
* String с именем message.
V
public class StringBean {
private String message = "No message specified";
Листинг 20.17.StringBean.j sp
:"l : ^^ -h f£ Л :i;
,f wuc4rr'3fi<s ^' Localton jh'tp/.'localbost/с
1Д.
Using JavaBeans with JSP
1 bubal value (getProperty) No message specified
2. Initial value (JSP expression); No message specified
3. Value after setting property with setProperty: Best string bean: Fortex
4. Value after setting property with scnptlet: My favorite: Kentucky Wonder
После создания экземпляра bean можно использовать входной параметр для уста
новки значения свойства itemlD.
<jsp:setProperty
name="entry"
property="itemID"
value='<%= r e q u e s t . g e t P a r a m e t e r ( " i t e m I D " ) %>' />
Заметьте, что в качестве значения атрибута v a l u e используется JSP-выражение.
Для большинства атрибутов значения задаются в виде строковых литералов, однако
значения атрибутов v a l u e и name действия j s p : s e t P r o p e r t y могут вычисляться в
момент получения запроса. Если в составе выражения содержатся двойные кавычки,
вы можете поместить значение атрибута в одинарные кавычки либо указать перед со
ответствующим символом обратную косую черту ( \ ' или \ " ) .
Листинг 2 0 . 1 8 . S a l e E n t r y . J a v a
package cwp;
/** Простой компонент bean, иллюстрирующий использование
* jsp:setProperty в различных формах.
Ч
public class SaleEntry {
private String itemID = "unknown";
private double discountCode = 1.0;
private int numltems = 0;
Листинг 20.19.SaleEntryl.j sp
<%
double discountCode = 1.0;
try {
String discountString =
request.getParameter("discountCode");
// Double.parseDouble недопустимо в JDK 1.1
discountCode =
Double.valueOf(discountString) doubleValue()
} catch(NumberFormatException nfe) {}
%>
<j sp:setProperty
name="entry"
property="discountCode"
value="<%= discountCode %>" />
<BR>
<TABLE ALIGN="CENTER" B0RDER=1>
<TR CLASS="COLORED">
<TH>Item ID<TH>Unit Price<TH>Number Ordered<TH>Total Price
<TR ALIGN="RIGHT">
<TD><jsp:getProperty name="entry" property="itemID" />
<TD>$<jsp:getProperty name="entry" property="itemCost" />
<TD><jsp:getProperty name="entry" property="numltems" />
<TD>$<jsp:getProperty name="entry" property="totalCost" />
</TABLE>
</BODY>
</HTML>
|.УШУМ, t^iiiiimifflB
fee E<irt View Fgvof^i*^ loo4 4?>lp
"3
Usfna ISD:se№roDerty •
int numltemsOrdered = 1;
try {
numltemsOrdered =
Integer.parseInt(request.getParameter("numltems"));
20.6. Использование JavaBeans с JSP 941
} catch(NumberFormatException nfe) {}
%>
<jsp:setProperty
name="entry"
property="numItems"
value="<%= numltemsOrdered %>" />
К счастью, JSP предлагает изящное решение этой проблемы. Свойство можно свя
зать с параметром запроса, автоматически преобразовывая строки символов в число
вое, символьное или логическое значение. Вместо атрибута v a l u e задается атрибут
p a r a m , с помощью которого устанавливается имя входного параметра. Значение
входного параметра автоматически принимается в качестве значения свойства; при
необходимости выполняется преобразование типа. Если указанный параметр в за
просе отсутствует, никакие действия не выполняются (система не присваивает свой
ству значение n u l l ) . Так, фрагмент кода, предназначенный для установки значения
свойства n u m l t e r n s , сокращается до следующего действия:
<j sp:setProperty
name="entry"
property="numItems"
param="numlterns" />
В листинге 20.20 показан код JSP-документа, созданный с помощью предоставляе
мой возможности.
Листинг 2 0 . 2 0 . S a l e E n t r y 2 . j s p
Листинг 2 0 . 2 1 . SaleEntiryS . j s p
том случае, когда создается новый компонент bean. При использовании существую
щего bean выражение не вычисляется. Такое условное вычисление выражения удобно
в том случае, когда устанавливаются исходные свойства bean, совместно используе
мые несколькими документами. Поскольку неизвестно, к какому документу клиент об
ратится раньше других, вы не знаете, в какой документ следует поместить инициали
зационный код. При использовании условного выражения инициализационный код
содержится во всех документах, но выполняется только один раз. Например, в лис
тинге 20.22 приведен простой компонент bean, который подсчитывает обращения к
любому из связанных документов. В нем также хранится имя документа, обращение к
которому произошло раньше, чем к другим. В каждом из документов для поддержки
счетчика используется следующий фрагмент кода:
<jsp:useBean id="counter"
сlass="cwp.AccessCountBean"
scope="application">
< j s p : s e t P r o p e r t y narne="counter"
property="firstPage"
v a l u e = " C u r r e n t Page Name" />
</jsp:useBean>
p a c k a g e cwp;
Листинг 20.23.SharedCountsl.jsp
package cwp.tags;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
/** Простой JSP-дескриптор, который включает в состав
* выходных данных строку ("Custom tag example...").
* Имя дескриптора здесь не определяется; это
* выполняется в файле описания библиотеки дескрипторов.
* Соответствующая ссылка оформляется с помощью директивы
* taglib в JSP-файле.
V
public class ExampleTag extends TagSupport {
public int doStartTag0 {
try {
JspWriter out = pageContext.getOut();
out.print("Custom tag example " +
"(cwp.tags.ExampleTag)");
} catch(lOException ioe) {
System.out.println("Error in ExampleTag: " + ioe);
}
return(SKIP_BODY);
}
}
Листинг 2 0 . 2 5 . c w p ~ t a g l i b . t l d
<taglib>
<tlibversion>l.0</tlibversion>
<j spversion>l.1</jspversion>
<shortname>cwp</shortname>
<info>
A tag library from Core Web Programming Java 2 Edition,
http://www.corewebprogramming.com/.
</info>
<tag>
<name>example</name>
<tagclass>cwp.tags.ExampleTag</tagclass>
<info>Simplest example: inserts one line of output</info>
</tag>
</taglib>
JSP-файл
Определив класс поддержки дескриптора и файла описания библиотеки дескрип
торов, вы можете приступать к написанию JSP-файла, содержащего пользовательский
дескриптор. П р и м е р такого файла приведен в листинге 20.26. Перед первым исполь
зованием дескриптора необходимо включить директиву t a g l i b , которая представля
ется в следующем формате:
<%@ t a g l i b u r i = " . . . " p r e f i x = " . . . " %>
Значением обязательного атрибута u r i может быть либо абсолютный, либо отно
сительный URL файла описания библиотеки дескрипторов (пример такого файла
приведен в листинге 20.25).
Атрибут p r e f i x , который также является обязательным, задает префикс, который
указывается перед именем дескриптора, определенным в файле описания библиотеки
дескрипторов. Например, если в файле описания библиотеки дескрипторов опреде
лен дескриптор с именем t a g l , а атрибут p r e f i x имеет значение t e s t , то реальным
именем дескриптора будет t e s t : t a g l . Данный дескриптор используется одним из
следующих способов:
<test:tagl>JSP-KOfl</test:tagl>
20.7. Определение новых JSP-дескрипторов 949
<test:tagl />
Файл описания, приведенный в листинге 20.25, называется c w p - t a g l i b . t l d и
находится в том ж е каталоге, ч т о и JSP-файл, код которого представлен в листинге
20.26. Поэтому директива t a g l i b , находящаяся в JSP-файле, содержит только имя
файла.
<%0 t a g l i b u r i = " c w p - t a g l i b . t l d " p r e f i x = " c w p " %>
Поскольку значение атрибута p r e f i x равно cwp, в остальной части JSP-документа
для ссылки на дескриптор e x a m p l e используется выражение cwp: e x a m p l e . Результа
ты обращения к документу показаны на рис. 20.14.
Листинг 2 0 . 2 6 . SimpleExample. j s p
ЕЖ
. lie
шаШ
S^^ )£tem F^vontes
^SM
loois Йе^
i,iriH!imiiff,mifffi-io|>^i
Листинг 20.27.SimplePrimeTag.Java
package c w p . t a g s ;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.
import java.io.*;
import java.math.*;
import cwp.*;
2 0 . 7 . Определение новых JSP-дескрипторов 951
return(SKIP BODY);
}
}
<bodycontent>empty</bodycontent>
К сожалению, Tomcat 3.1 не поддерживает элемент bodycontent, и содержащий
его файл описания библиотеки дескрипторов не работает. Tomcat 3.2, JRun и
большинство других серверов корректно обрабатывают элемент b o d y c o n t e n t .
Внимание!!
<tag>
<name>simplePrime</naine>
<tagclass>cwp.tags.SimplePrimeTag</tagclass>
<info>Outputs a random 50-digit prime.</info>
</tag>
t-r4Mi,rH'Mi-i|IJil,l4M.I-l[if'!l
File £cM View £o £ommuf«cat« IHet
package c w p . t a g s ;
import javax.servlet.jsp.*;
import javax.servlet•j sp.tagext.*;
import java.io.*;
Листинг 2 0 . 3 1 . c w p - t a g l i b . t l d (фрагмент)
<tag>
<name>prime</name>
<tagclass>cwp.tags.PrimeTag</tagclass>
<info>Outputs a random N-digit prime.</info>
<attribute>
<name>length</name>
<required>false</required>
</attribute>
</tag>
Листинг 20.32.PrimeExample.jsp
|[..f'l7M'i^»IWIfJII.:!J«!lfJI.U.!|l!.'IJI.Uiii|.![.]pi ЕШШ
Pe Edit View Favorites Toofs Hel?
Листинг 2 0 . 3 3 . HeadingTag. j a v a
package cwp.tags;
import javax.servlet.jsp.*;
import j avax.servlet.j sp.tagext.*;
import java.io.*;
<tag>
<name>heading</name>
<tagclass>cwp.tags.HeadingTag</tagclass>
<info>Outputs a 1-cell table used as a heading.</info>
<attribute>
<name>bgColor</name>
<required>true</required>
<!-- bgColor - обязательный атрибут -->
</attribute>
<attribute>
<name>color</name>
<required>false</required>
</attribute>
<attribute>
<name>align</name>
<required>false</required>
</attribute>
<attribute>
<name>fontSize</name>
<required>false</required>
</attribute>
<attribute>
<name>fontList</name>
<required>false</required>
</attribute>
960 Глава 20. JavaServer Pages
<attribute>
<name>border</name>
<required>false</required>
<./attribute>
<attribute>
<name>width</name>
<required>false</required>
</attribute>
</tag>
Листинг 2 0 . 3 5 . HeadingExample. j s p
AH
<^f "Sookmoks j | , Locabonc|h«p //localhosl/cwp/TagExamples/HeadingExample |sp
"3
Default Heading
White on Blacic Heading
Листинг 20.36.DebugTag.Java
package cwp.tags;
import javax.servlet.jsp.*;
import javax.servlet.j sp.tagext.*;
import java.io.*;
import javax.servlet.*;
Листинг 2 0 . 3 7 . c w p - t a g l i b . t l d (фрагмент)
<tag>
<name>debug</naine>
<tagclass>cwp.tags.DebugTag</tagclass>
<info>Includes body only if debug param is set.</info>
</tag>
20.7. Определение новых JSP-дескрипторов 963
Листинг 2 0 . 3 8 . D e b u g E x a m p l e . j s p
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4 . 0 T r a n s i t i o n a l / / E N " >
<HTML>
<HEAD>
<TITLE>Using t h e Debug Tag</TITLE>
<LINK REL=STYLESHEET
HREF="JSP-Styles.ess"
TYPE="text/ess">
</HEAD>
<BODY>
<Hl>Using t h e Debug Tag</Hl>
<%@ t a g l i b u r i = " c w p - t a g l i b . t l d " p r e f i x = " c w p " %>
Top of regular page. Blah, blah, blah. Yadda, yadda, yadda.
<P>
<cwp:debug>
<B>Debug:</B>
<UL>
<LI>Current time: <%= new java.util.Date() %>
<LI>Requesting hostname: <%= request.getRemoteHost() %>
<LI>Session ID: <%= session.getid() %>
</UL>
</cwp:debug>
<P>
Bottom of regular page. Blah, blah, blah. Yadda, yadda, yadda.
</BODY>
</HTML>
Ш
^'Booknriarks „4 Lgcattoft:|http.//localhQst/cwp/TeigExamples/DebugExamplejsp
Using t h e Debug T a g
Top of regular page. Blah, blah, blah. Yadda, yadda, yadda.
f u s i n g theOebuq Tag-Netscape
£iie £dit ^iew Qo Communicator Oelp
^ ^ J Л j^. i^ ~.:J^ rf 2l j l SI
. ^ 1 " Bookmerks ^^ iQcatioajhttp //localhost/cwp/TegExamples/DebugExample )sp'?debug'tru~-^ ^ , Г Vvliat's Related
Using t h e Debug T a g
Top of regular page. Blah, blah, blah. Yadda, yadda, yadda.
Debug:
Рис. 20.19. При наличии параметра debug в составе запроса тело дескриптора
cwp: debug присутствует в составе ответа
package c w p . t a g s ;
import javax.servlet.jsp.*;
import j avax.servlet.j sp.tagext.*;
import java.io.*;
import cwp.*;
Листинг 2 0 . 4 0 . c w p - t a g l i b . t l d (фрагмент)
<tag>
<name>filter</name>
<tagclass>cwp.tags.FilterTag</tagclass>
<info>Replaces HTML-specific characters in body.</info>
</tag>
Листинг 2 0 . 4 1 . F i l t e r E x a m p l e . j s p
<TR CLASS="COLORED"><TH>Example<TH>Result
<TR>
<TD><PRE><cwp:filter>
<EM>Some emphasized text.</EM><BR>
<STRONG>Some strongly emphasized text.</STRONG><BR>
<CODE>Some code.</CODE><BR>
<SAMP>Some sample text.</SAMP><BR>
<KBD>Some keyboard text.</KBD><BR>
<DFN>A term being defined.</DFN><BR>
<VAR>A variable.</VAR><BR>
<CITE>A citation or reference.</CITE>
</cwp:filter></PRE>
<TD>
<EM>Some emphasized text.</EM><BR>
<STRONG>Some strongly emphasized text.</STRONG><BR>
<CODE>Some code.</CODE><BR>
<SAMP>Some sample text.</SAMP><BR>
<KBD>Some keyboard text.</KBD><BR>
<DFN>A term being defined.</DFN><BR>
<VAR>A variable.</VAR><BR>
<C1TE>A citation or reference.</CITE>
</TABLE>
</BODY>
</HTML>
hl!lli'.llffHHiTffWnH|i|l41i'Hf#Hl
4^Ж:Ж.^..^..М.^.ЖШ.
^^йкюЫлк^ Д Lfieefiuft jhttp /'/'localhost/'cwp/TagExamples/'FikerExanfple |sp
package c w p . t a g s ;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
Листинг 2 0 . 4 3 . c w p - t a g l i b . t l d (фрагмент)
<tag>
<name>repeat</name>
<tagclass>cwp.tags.RepeatTag</tagclass>
<info>Repeats body the specified number of times.</info>
<attribute>
<name>reps</name>
<required>true</required>
<!-- rtexprvalue указывает, может ли атрибут
представлять собой JSP-выражение. -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
Листинг 2 0 . 4 4 . R e p e a t E x a m p l e . j s p
HREF="JSP-Styles.ess"
TYPE="text/css">
</HEAD>
<BODY>
<Hl>Some 40-Digit Primes</Hl>
Each entry in the following list is the first prime number
higher than a randomly selected 40-digit number.
<%@ taglib uri="cwp-taglib.tld" prefix="cwp" %>
<0L>
<!-- Repeats N times. A null reps value means repeat once. — >
<cwp:repeat reps='<%= request.getParameter("repeats") %>'>
<LI><cwp:prime length="40" />
</cwp:repeat>
</0L>
</BODY>
</HTML>
шззшшшяа miiffimniiii
&» i"^ V<e«^ F#wiJ*« look Ц ф
<^"^-<u-^ib-M^-^M-S\
I Afii^Si | € J h»tp //localhost/cwp/TagExamples/'RepeatExample |sp'^repeats=7 ^
"3
Some 40-Digit Primes
Each entry m the foflowing list is the first prime number higher than
a randomly selected 40-digit number,
1. 779042788484692290696496905990659223259
2. 5654911225096957336845971755232574136573
3. 4440250773563950124888671855331783776667
4. 4557511042237325396986257256572883741037
5. 584476361241995395252711786232246484577 Рис. 20.21. Результаты обращения к
6. 2878822708441674101514196529821727599631
7 9665985263198820747432458513545913598401
RepeatExample. j sp. Значение параметра
r e p e a t s , передаваемого в составе
^Ooiiei"" iltic4ir*t«ne запроса, равно 20
Листинг 2 0 . 4 5 . I f T a g . j a v a
package c w p . t a g s ;
import j a v a x . s e r v l e t . j s p . * ;
import j a v a x . s e r v l e t . j s p . t a g e x t . * ;
import j a v a . i o . * ;
import j a v a x . s e r v l e t . * ;
/** Дескриптор, который действует как i f / t h e n / e l s e .
p u b l i c c l a s s IfTag extends TagSupport {
p r i v a t e boolean conditions-
p r i v a t e boolean hasCondition = falser-
p u b l i c void s e t C o n d i t i o n ( b o o l e a n c o n d i t i o n ) {
this.condition = condition;
hasCondition = t r u e ;
p u b l i c boolean g e t C o n d i t i o n ( ) {
return(condition);
package c w p . t a g s ;
import javax.servlet.jsp.*;
import javax.servlet.j sp.tagext.*;
import java.io.*;
import javax.servlet.*;
package c w p . t a g s ;
import javax.servlet.jsp.*;
import j avax.servlet.j sp.tagext.*;
import java.io.*;
import javax.servlet.*;
Листинг 2 0 . 4 8 . I f E l s e T a g . j a v a
package c w p . t a g s ;
import javax.servlet.jsp.*;
import javax.servlet.j sp.tagext.*;
import java.io.*;
import javax.servlet.*;
out.print(body.getString());
} catch(lOException ioe) {
System.out.println("Error in IfElseTag: " + ioe);
}
}
return(SKIP_BODY);
}
}
<tag>
<name>if</name>
<tagclass>cwp.tags.IfTag</tagclass>
<info>if/condition/then/else tag.</info>
</tag>
<tag>
<name>condition</name>
<tagclass>cwp.tags.IfConditionTag</tagclass>
<info>condition part of if/condition/then/else tag.</info>
</tag>
<tag>
<name>then</name>
<tagclass>cwp.tags.IfThenTag</tagclass>
<info>then part of if/condition/then/else tag.</info>
</tag>
<tag>
<name>else</name>
<tagclass>cwp.tags.IfElseTag</tagclass>
<info>else part of if/condition/then/else tag.</info>
</tag>
976 Глава 20. JavaServer Pages
Листинг 2 0 . 5 0 . I f E x a m p l e . j s p
1"
^' •>'" 3 г'Л ^
-^.1^" Bookrwwks
^ J-
J^ Location |ht;p//locaihc:. , ^ _,_ _ ^ • • 3
я
If Tag Example
j Condition is true
Перенаправление запросов
Для перенаправления запросов или включения внешнего содержимого используется
класс RequestDispatcher. Для получения объекта RequestDispatcher используется
метод g e t R e q u e s t D i s p a t c h e r класса S e r v l e t C o n t e x t , которому передается URL отно
сительно корневого каталога сервера. Например, для получения RequestDispatcher,
связанного с h t t p : / / y o u r h o s t / p r e s e n t a t i o n s / p r e s e n t a t i o n l . j s p , надо использо
вать следующие выражения:
String url = "/presentations/presentationl.jsp";
RequestDispatcher dispatcher =
getServletContext () .getRequestDispatcher(url);
Получив R e q u e s t D i s p a t c h e r , вы можете использовать метод forward для пере
направления запроса по указанному URL либо метод i n c l u d e для вывода содержимо
го указанного документа. В обоих случаях методу необходимо передавать в качестве
параметров объекты H t t p S e r v l e t R e q u e s t и H t t p S e r v l e t R e s p o n s e . Оба метода
могут генерировать исключения S e r v l e t E x c e p t i o n и lOException. Например, в
листинге 20.51 показан фрагмент сервлета, перенаправляющего запрос одному из
трех различных JSP-документов. Решение о перенаправлении принимается в зависи
мости от значения параметра o p e r a t i o n . Для упрощения кода в сервлете использу
ется метод gotoPage, которому передаются URL, а также объекты H t t p S e r v l e t
Request и H t t p S e r v l e t R e s p o n s e . Этот метод посредством вызова g e t R e q u e s t
D i s p a t c h e r получает объект R e q u e s t D i s p a t c h e r и вызывает метод forward этого
объекта.
<jsp:useBean id="customer"
class="cwp.TravelCustomer"
scope="session" />
a затем использует действие j s p i g e t P r o p e r t y для включения и н ф о р м а ц и и в раз
личные части результирующей страницы.
Особое внимание следует уделить классу T r a v e l C u s t o m e r (часть его показана в
листинге 20.55, а полностью его код хранится по адресу www. c o r e w e b p r o g -
r a m m i n g . com). В частности, заметьте, что значительная часть кода посвящена тому,
чтобы сделать информацию о потребителе доступной посредством свойств в виде
строк и даже форматированного HTML-текста. Каждая задача, требующая больших
усилий по созданию программ, решается путем создания компонентов bean. Такой
подход типичен для интеграции сервлетов и JSP — использование JSP не исключает
полностью необходимости форматировать данные посредством Java-кода, представ
ляя их в виде строк и HTML-элементов. Усилия по форматированию информации,
чтобы она была доступна JSP, многократно окупают себя в случае, если к одним и тем
же данным обращается несколько документов.
1^Л|Д1Ш1Ит1>|1!М'1:Ш|||.|у'11У1Я4.1|11^1Ш|^|1|11^^^^^^
У^;^ ШШШ^
i |АЙ#ЙИ \Ш1 Ntp://loe«lM»tArevei/ouick-t8erchh(ml
"И
~
D e s t i l i a t i o u ; |LOS Angeles ^
Start date (MMDDA^'): |1Л/2001
Eiid date (MM''DDA'\') |i/8/200i
<TABLE CELLSPACING=1>
<TR>
<TH> <IMG SRC="airplane.gif" WIDTH=100 HEIGHT=29
ALIGN="TOP" ALT="Book Flight">
<TR>
<TH><SMALL>
<INPUT TYPE="SUBMIT" NAME="flights" VALUE="Book Flight">
</SMALL>
</TABLE>
</CENTER>
</FORM>
</BODY>
</HTML>
984 Глава 20. JavaServer Pages
i ^ Best Av«iable Flight» ^MicfOMifl Internet Exploiei ~ """ ~""^ " ~ ' ~ ' 'шШШ
£te £(* y«w Favodtej Jocfe Нф
^ П ^ ^ ^ Ж : ^ ^ ^ : ^ ? ' ^ ' " ? ' ^ V ; Java AlrwarsFliglit 1522 ($455.95) ^ '^^<:^-'^-; ; • • ' •
Oufgomg: Lea\ es> Baltimore at 9 00 AM on 1/1/2001, aniMiig in Los Angelefc; at 3 15 PM (1 stop - Java, Indonesia).
Retiuii: Lea\es Los Angeles at 900 AM on 1/8/2001, arming in Baltimore at Ъ15 PM (1 stop -- Sim Microsystems),
\ . SfnletEa^ireirsijri^tadaa (1^505.95)
Outgoing: Leaves Baltimore at 9,30 AM on 1 1/2001, aiTi\ing in Los Angeles at 415 PM (1 stop -- Ne>^' Atlanta)
Retmii: Leaves Los Angeles at 9 30 AM on 1/8/2001, anivuig in Baltimore at 415 PM (1 stop -- New Atlanta)
Outgoing: L€a\es Balhmore at 10.02;3'7 . ^ I on 1/1/2001, aiTi\ing ui Los Angeles at 2 22 19 PM (1 stop -- JHIT)
Return: Leaves Los Angeles at 10:0237 AM on l/8/'2001, aiTi\iiig ш Balhmore at 2 22 19 PM (1 stop -- МГГ)
1 HoWfor24Hrs j
Book It! 1
J
i ^ Don* 1 ^ \joceA irtranei
Рис. 20.24. Сервлет, реализующий интерактивный агент (листинг 20.53), перенаправляет запрос
документу B o o k F l i g h t s . j sp (листинг 20.54)
20.8. Интеграция сервлетов и JSP 985
Листинг 2 0 . 5 3 . T r a v e l . j a v a
package cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
request, response);
} else {
gotoPage("/travel/IllegalRequest.j sp",
request, response);
}
}
package cwp;
import java.util.*;
import Java.text.*;
20.9. Резюме
в принципе, любая задача, решаемая посредством JSP, может быть решена с по
мощью сервлетов. Однако на практике JSP упрощают процед)ру генерации HTML-
содержимого и обеспечивают более высокую надежность. Это достигается за счет
разделения статического текста, используемого для оформления Web-страницы, и
Java-кода, генерирующего динамические фрагменты документа. Работу по созданию
различных частей такого документа легко распределить между разными группами
разработчиков.
В результате лишь на немногих узлах используются только сервлеты и не приме
няются JSP. Однако это не означает, что разработчики программ, предназначенных
для выполнения на стороне сервера, полностью отказались от применения сервлетов
в пользуJSP. Как правило, для одних задач используются сервлеты, для других — JSP, а
для третьих — сочетание сервлетов и JSP.
В данной главе мы рассказали вам об основных средствах JSP и показали, как про
исходит управление сервлетами, генерируемыми на основе JSP. Вы также узнали о
применении компонентов bean и пользовательских дескрипторов. Эти возможности
позволяют поручить сопровождение сложных документов сотрудникам, не имеющим
опыта в программировании на языке Java. И, наконец, мы рассмотрели способы объе
динения сервлетов и JSP для решения сложных задач.
Итак, отдохните немного и приготовьтесь отвечать на многочисленные звонки
работодателей, нуждающихся в услугах такого квалифицированного специалиста, ка
ким стали вы.
АПЛЕТЫ
КАК ИНТЕРФЕЙС
К ПРОГРАММАМ
НА СТОРОНЕ
СЕРВЕРА
В ЭТОЙ главе...
try {
URL programURL = new URL(baseURL + "?" + someData);
getAppletContext().showDocument(programURL);
} catch(MalformedURLException mue) { ... }
П р и м е р использования данного подхода приведен в следующем разделе.
2 1 . 2 . Интерфейс к нескольким поисковым серверам 993
Листинг 2 1 . 1 . S e a r c h / ^ p l e t . Java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.*;
import java.net.*;
submitButton.addActionListener(this);
add(submitButton);
}
/** Данные передаются после щелчка на кнопке <В>или</В>
* после нажатия клавиши <Enter> в тот момент, когда
* фокус ввода принадлежит полю редактирования.
Ч
public void actionPerformed(ActionEvent event) {
String query = URLEncoder.encode(queryField.getText());
SearchSpec[] coinmonSpecs = SearchSpec.getCommonSpecs();
// HotBot (последний пункт) пропускается, поскольку
/ / в данном случае для вывода результатов в верхний
// фрейм используется JavaScript to. Поэтому ниже
// указано значение length-1.
for(int i=0; i<coimnonSpecs.length-1; i++) {
try {
SearchSpec spec = commonSpecs[i];
// Класс SearchSpec создает URL в формате,
// соответствующем популярным поисковым серверам.
URL searchURL = new URL(spec.makeURL(query, "10"));
String frameName = "results" + i;
getAppletContext().showDocument(searchURL, frameName);
} catch(MalformedURLException mue) {}
}
}
Листинг 21.2.SearchSpec.Java
i-y{jriiaHmi«iiiiHiiiiffliH.;HHiifflHiHaa
Search Stiiiig:
S«tiil to Scardi Enffaiei [
Рис. 21.1. Аплет SearchApplet позволяет пользователю передавать один набор ключевых слов
нескольким поисковым серверам
996 Глава 2 1 . Аплеты как интерфейс.
БШШ
lie £d* Yew F^vortes Tooh НФ
Рис. 21.2. В ответ на запрос отображаются результаты поиска, выполненного тремя серверами
Листинг 2 1 . 3 . P a r a l l e l S e a r c h e s . h t m l
<FRAMESET ROWS="120,*">
<FRAME SRC="SearchAppletFrame.html" SCROLLING="NO">
<FRAMESET COLS="*, *f''">
<FRAME SRC="GoogleResultsFrame.html" NAME="resultsO">
<FRAME SRC="InfoseekResultsFranie.html" NAME="resultsl">
<FRAME SRC="LycosResultsFrame.htral" NAME="results2">
</FRAMESET>
</FRAMESET>
Листинг 21.4.SearchAppletFrame.html
</HEAD>
<BODY BGCOLOR="WHITE">
<CENTER>
<APPLET CODE="SearchApplet.class" WIDTH=600 HEIGHT=100>
<B>This example requires a Java-enabled browser.</B>
</APPLET>
</CENTER>
</BODY>
</HTML>
Листинг 2 1 . 5 . S h o w Q u e r i e s . j a v a
i m p o r t J a v a , a p p l e t .Applets-
import j a v a . a w t . ^ ;
import J a v a . a w t . e v e n t . * ;
im.port j a v a . n e t . * ;
Листинг 21.6.QueryCollection.Java
import java.net.*;
import java.io.*;
new ObjееtInputstream(connection.getInputStream())/
try {
// Метод readObject возвращает значение Object,
// поэтому необходимо выполнить приведение типов.
String[] queryStrings = (String[])in.readObject();
return(queryStrings);
} catch(ClassNotFoundException cnfe) {
return(null);
}
~3
Search Engine Queiy Viewer
Interested in what other people are searching for on super-search-engine.com? Press "Start" in the viewer
below to see a random selection of the most recent queries.
jJ
•;0j Recewed data hom sefver. f g locae'irttane*
Листинг 2 1 . 7 . Q u e r y G e n e r a t o r . J a v a
package cwp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.
1006 Глава 2 1 . Аплеты как интерфейс.
out.print(data); / / Метод p r i n t , a не p r i n t l n .
o u t . f l u s h O ; / / Метод f l u s h должен быть вызван,
/ / поскольку p r i n t l n не и с п о л ь з у е т с я .
8. Установка поля Content-Length. Для запроса POST это поле является обяза
тельным.
connection.setRequestProperty
{"Content-Length", S t r i n g . v a l u e O f ( b y t e S t r e a m . s i z e ( ) ) ) /
9. Установка поля Content-Type. По умолчанию Netscape устанавливает тип
m u l t i p a r t / f o r m - d a t a , однако для передачи данных необходимо задать зна
чение a p p l i c a t i o n / x - w w w - f orm-urlencoded, которое используется Internet
Explorer по умолчанию.
connection.setRequestProperty
("Content-Type", "application/x-www-form-urlencoded");
10. Передача данных.
byteStream.writeTo(connection.getOutputStream());
11. Открытие входного потока. Для приема ASCII или двоичных данных обычно
применяется Buf feredReader, а для приема сериализованных Java-объектов—
ObjectInputStream.
BufferedReader in =
new BufferedReader(new InputStreamReader
(connection.getInputStream()));
12. Чтение результатов. Детали этого процесса зависят от типа информации, пе
редаваемой сервером. В приведенном ниже примере над каждой строкой полу
ченных данных выполняются некоторые действия.
String line;
while((line = in.readLine()) != null) {
doSomethingWith(line);
}
Как видите, формирование и обработка запроса POST — достаточно длительная и
рутинная процедура, однако последовательность действий легко запоминается и вы
полняется автоматически. Кроме того, вы можете скопировать пример с узла
www. corewebprogramming. com и использовать его при написании своих программ.
В следующем разделе приводится пример аплета, выполняющего описанную по
следовательность де11ствий.
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import J a v a . a w t . e v e n t . * ;
import j a v a . n e t . * ;
import j a v a . i o . * ;
currentPage = getCodeBase();
// Для аплета, расположенного на локальном диске,
// метод getHost возвращает пустую строку.
String host = currentPage.getHost();
String resultsMessage = "Results will be shown here...";
if (host.length 0 == 0) {
resultsMessage = "Error: you must load this applet\n" +
"from a real Web server via HTTP,\n" +
"not from the local disk usingXn" +
"a »file:' URL. It is fine,\n" +
"however, if the Web server is\n" +
"running on your local system.";
setEnabled(false);
}
hostField.getTextField().setText(host);
inputPanel.add(hostField);
portField =
new LabeledTextField("Port (-1 means default):", 4 ) ;
String portString = String.valueOf(currentPage.getPort());
portField.getTextField().setText(portString);
inputPanel.add(portField);
uriField =
new LabeledTextField("URI:", 40);
String defaultURI = "/servlet/cwp.ShowParameters";
uriField.getTextField0 .setText(defaultURI);
inputPanel.add(uriField);
Canvas separator2 = new Canvas();
inputPanel.add(separator2);
sendButton = new Button("Submit Data");
sendButton.addActionListener(this);
Panel buttonPanel = new Panel();
buttonPanel.add(sendButton);
inputPanel.add(buttonPanel);
add(inputPanel, BorderLayout.NORTH);
resultsArea = new TextAreaO;
resultsArea.setFont(new Font("Monospaced", Font.PLAIN, 14))
resultsArea.setText(resultsMessage);
add(resultsArea, BorderLayout.CENTER);
connection.setUseCaches(false);
ByteArrayOutputStream byteStream =
new ByteArrayOutputStream(512); // При необходимости
// размеры буфера увеличиваются.
// Поток, который записывает данные в буфер
PrintWriter out = new PrintWriter(byteStream, true);
String postData =
"firstName=" + encodedValue(firstNameField) +
"&lastName=" + encodedValue(lastNameField) +
"&emailAddress=" + encodedValue(emailAddressField);
connection.setRequestProperty
("Content-Type", "application/x-www-form-urlencoded");
BufferedReader in =
new BufferedReader(new InputstreamReader
(connection.getlnputStream0));
String line;
String linefeed = "\n";
resultsArea.setText("");
while((line = in,readLine()) ?= null) {
resultsArea.append(line);
resultsArea.append(linefeed);
}
catch(lOException ioe) {
21.6. Аплет, который передает данные методом POST 1013
}
// LabeledTextField представляет собой объект Panel,
// содержащий компоненты Label и TextField.
// Данный метод извлекает текст из TextField,
// кодирует его и возвращает результаты.
t-#fT-mii'HifinmffiHna[infff
"^ ^ -./ 31 Й ^- '^ -^ ^ i i ^H
„^i^" Boolyn«fk$ J ' loc«ion"Jhttp //localhost/'SendPoslApplet/SendPost html
3
Sending POST Data from Applets
Host bcnlhost
,J
лГ
jj^-sa^as'
>' C3 -г-
Рис, 21.4. Результаты использования SendPost для передачи
данных сервлету ShowParameters методом POST
1014 Глава 2 1 . Аплеты как интерфейс...
21.8. Резюме
HTML-формы представляют собой самый простой и часто используемый интер
фейс для взаимодействия с программами, выполняющимися на стороне сервера.
В отличие от форм, аплеты позволяют создавать более сложный интерфейс, поддер
живают постоянное обновление информации и упрощают передачу сложных струк
тур. Поэтому в подавляющем большинстве случаев применяются HTML-формы. Если
же ограничения, связанные с формами, не позволяют выполнить поставленную зада
чу, в качестве интерфейса используется Java-аплет.
JDBC
В ЭТОЙ главе...
3. Установить соединение.
4. Создать выражение (объект Statement).
5. Выполнить запрос.
6. Обработать результаты.
7. Закрыть соединение.
Ниже эта процедура описана детально.
Загрузка драйвера
Драйвер — это программа, которая позволяет взаимодействовать с сервером баз
данных. Для загрузки драйвера надо загрузить соответствующий класс; средства клас
са, объявленные как s t a t i c , автоматически создают экземпляр драйвера и регистри
руют его посредством диспетчера драйверов JDBC. Для того чтобы сделать код более
гибким, надо избегать непосредственного использования имени класса.
Последняя рекомендация обязательно вызовет вопросы. Во-первых, как, спросите
вы, загрузить класс, не создавая его экземпляр? Во-вторых, вам, наверное, непонятно,
как ссылаться на класс, имя которого неизвестно на этапе компиляции. На оба вопро
са можно дать один ответ: необходимо использовать метод C l a s s . forName. Этому
методу передается строка, представляющая полное имя класса (т.е. имя с указанием
пакета), после чего метод загружает указанный класс. П р и выполнении данного мето
да может генерироваться исключение C l a s s N o t F o u n d E x c e p t i o n , поэтому его вызов
надо поместить в блок t r y / c a t c h . П р и м е р кода, в котором использован данный под
ход, приведен ниже.
try {
Class.forName{"connect.microsoft.MicrosoftDriver");
Class.forName("oracle.jdbc.driver.OracleDriver");
Class.forName("com.Sybase.jdbc.SybDriver");
} catch(ClassNotFoundException cnfe) {
System.err.println("Error loading driver: " + cnfe);
}
Преимуществом JDBC является тот факт, что сервер баз данных для различных
приложений остается неизменным. Вместо этого JDBC-драйвер (расположенный на
стороне клиента) преобразует вызовы, написанные на языке Java, в специальный
формат, поддерживаемый сервером. Чтобы обеспечить работу с драйвером, специ
фическим для конкретной базы данных, надо найти в документации полное имя клас
са. Большинство производителей баз данных поставляют JDBC-драйверы для своих
продуктов; для других баз драйверы создаются независимыми производителями.
Исчерпывающий список доступных драйверов вы найдете по адресу h t t p : / /
i n d u s t r y . j a v a . s u n . c o m / p r o d u c t s / j d b c / d r i v e r s . Многие разработчики бес
платно предоставляют оценочные версии драйверов (обычно в них ограничены срок
использования или число одновременных соединений), эти версии можно применять
для изучения JDBC.
Метод C l a s s . forName можно применять для загрузки любого класса, доступного
посредством CLASS PATH. На практике большинство производителей поставляют
JDBC-драйверы в составе JAR-файлов, поэтому необходимо следить за тем, чтобы со-
2 2 . 1 . Основные этапы работы с JDBC 1019
ответствующий JAR-файл был указан в переменной окружения CLASS PATH. Как пра
вило, серверы, поддерживающие сервлеты и JSP, автоматически добавляют к
CLASSPATH JAR-файлы, содержащиеся в каталоге l i b . Поэтому для программ, выпол
няющихся на стороне сервера и использующих JDBC, JAR-файлы, содержащие драй
веры, необходимо помещать в каталог l i b сервера.
Установление соединения
Для того чтобы установить реальное сетевое соединение, надо, как показано в при
веденном ниже примере, передать URL, имя пользователя базы данных и пароль методу
g e t C o n n e c t i o n класса DriverManager. Так как при выполнении g e t C o n n e c t i o n мо
жет генерироваться исключение S Q L E x c e p t i o n , вызов этого метода необходимо по
местить в блок t r y / c a t c h . Поскольку методы, вызываемые в приведенном примере,
могуо' генерировать то же прерывание, весь фрагмент надо расположить внутри блока
try/catch.
String username = " j a y _ d e b e s e e " ;
String password = " s e c r e t " ;
Connection c o n n e c t i o n =
DriverManager.getConnection(oracleURL, username, password);
Ha данном этапе также может выполняться поиск информации о базе данных с помо
щью метода g e t M e t a D a t a класса C o n n e c t i o n . Данный метод возвращает объект
D a t a b a s e M e t a D a t a , содержащий методы для определения имени и версии базы данных
( g e t D a t a b a s e P r o d u c t N a m e , g e t D a t a b a s e P r o d u c t V e r s i o n ) и драйвера ( g e t D r i v e r Name,
g e t D r i v e r V e r s i o n ) . Пример поиска сведений о базе приведен ниже.
1020 Глава 22. JDBC
DatabaseMetaData dbMetaData = c o n n e c t i o n . g e t M e t a D a t a ( ) ;
S t r i n g productName =
dbMetaData.getDatabaseProductName();
S y s t e m . o u t . p r i n t l n ( " D a t a b a s e : " + productName);
S t r i n g productVersion =
dbMetaData.getDatabaseProductVersion();
System.out.println("Version: " + productVersion);
Кроме того, в классе Connection содержатся методы p r e p a r e S t a t e m e n t
(создает объект P r e p a r e d S t a t e m e n t , который будет рассматриваться в разделе
22.6), p r e p a r e C a l l (создает объект C a l l a b l e S t a t e m e n t ) , r o l l b a c k (отменяет дей
ствия, выполненные с момента завершения последней транзакции), commit
(завершает транзакцию), c l o s e (закрывает соединение), i s C l o s e d (определяет, бы
ло ли соединение закрыто явно или по тайм-ауту).
Выполнение запроса
Имея объект S t a t e m e n t , его можно использовать для передачи SQL-запросов базе
данных посредством метода executeQuery. Метод executeQuery возвращает на
бор результатов (объект R e s u l t S e t ) . Пример получения набора результатов приве
ден ниже.
S t r i n g query = "SELECT c o l l , c o l 2 , col3 FROM sometable";
ResultSet r e s u l t S e t = s t a t e m e n t . e x e c u t e Q u e r y ( q u e r y ) ;
Для того чтобы внести изменения в базу данных, надо вместо executeQuery вы
звать метод e x e c u t e Update, передавая ему строку запроса, содержащую команду
UPDATE, INSERT или DELETE. Помимо executeQuery и executeUpdate в классе
Statement определены методы e x e c u t e (выполнение произвольной команды) и
QueryTimeout (установка максимального времени ожидания результатов). Кроме то
го, вы можете создавать параметризованные запросы, в которых значения передают
ся заранее скомпилированному запросу фиксированного формата. Этот вопрос будет
рассмотрен в разделе 22.6.
Обработка результатов
Обрабатывать результаты проще всего, перебирая строки (записи) набора с по
мощью метода n e x t объекта R e s u l t S e t . Для обработки строки класс R e s u l t S e t
предоставляет различные методы qetXxx. В качестве параметра такому методу пере
дается индекс, либо имя столбца (поля); в результате выполнения метода возвраща
ются различные типы данных. Например, если возвращаемое значение должно быть
целым числом, надо использовать метод g e t l n t ^ для получения объекта S t r i n g —
метод g e t S t r i n g и т.д. Если вам необходимо отображать результаты, независимо от
типа столбца надо вызывать метод g e t S t r i n g . Если вы передаете методу индекс, еле-
2 2 . 1 . Основные этапы работы с JDBC 1021
Закрытие соединения
Для того чтобы закрыть соединение, надо включить в программу следующее вы
ражение:
connection.close();
Если вы собираетесь выполнять дополнительные операции с базой данной, може
те закрыть соединение позже, однако следует помнить, что открытое соединение по
требляет большое количество ресурсов.
1022 Глава 2 2 . JDBC
Prompt> J a v a c w p . F r u i t T e s t d b h o s t l . a p l . j h u . e d u РТЕ
h a l l xxxx o r a c l e
Database: Oracle
Version: Oracle7 Server Release 7 . 2 . 3 . 0 . 0 - Production Release
PL/SQL R e l e a s e 2 . 2 . 3 . 0 . 0 - P r o d u c t i o n
Comparing A p p l e s and O r a n g e s
Prompt> J a v a c w p . F r u i t T e s t d b h o s t 2 . a p l . j h u . e d u 605741
h a l l xxxx Sybase
D a t a b a s e : A d a p t i v e S e r v e r Anywhere
Version: 6.0.2.2188
2 2 . 2 . Пример использования JDBC 1023
Листинг 22.3.FruitTest.Java
package cwp;
import java.sql.*;
string url,
String username,
String password) {
try {
// Если драйвер базы данных еще не загружен,
// производится его загрузка.
Class.forName(driver);
// Установление соединения с базой данных.
Connection connection =
DriverManager.getConnection(url, username, password);
// Поиск информации о базе данных в целом.
DatabaseMetaData dbMetedData = connection.getMetaData();
String productName =
dbMetaData.getDatabaseProductName();
System.out.println("Database: " + productName);
String productVersion =
dbMetciData. getDatabaseProductVersion () ;
System.out.println("Version: " + productVersion + " \ n " ) ;
System.out.println("Comparing Apples and Oranges\n" +
"============:=:=========:======:" ) ;
Statement statement = connection.createstatement();
String query = "SELECT * FROM fruits";
// Передача запроса базе данных и сохранение результатов.
ResultSet resultSet = statement.executeQuery(query);
// Поиск информации о конкретной таблице.
ResultSetMetaData resultsMetaData =
resultSet .getMetedData О ;
int coliunnCount = resultsMetaData.getColumnCount0;
// Нумерация столбцов начинается с 1, а не с О.
for(int i=l; i<columnCount+l; i++) {
System, ou t. print (result sMetaData.getColглtlnName (i) +
}
System.out.println();
// Вывод результатов,
while(resultSet.next О ) {
// Квартал
System.out.print(" " + resultSet.getint(1));
// Информация о яблоках
System.out.print(" " + resultSet.getint(2));
// Уровень продаж яблок
System.out.print(" $" + resultSet.getFloat(3));
// Информация об апельсинах
System.out.print(" " + resultSet.getint(4));
// Уровень продаж апельсинов
System.out.print(" $" + resultSet.getFloat(5));
// Ведущий продавец
System.out.println(" " + resultSet.getString(6));
}
} catch(ClassNotFoundException cnfe) {
System.err.println("Error loading driver: " + cnfe);
} catch(SQLException sqle) {
System.err.println("Error connecting: " + sqle);
2 2 . 2 . Пример использования JDBC 1025
)
}
package cwp;
package cwp;
import java.sql.*;
package cwp;
import java.sql.*;
results.getProductName());
System.out.println("Version: " +
results.getProductVersion());
System.out.println() ;
}
System.out.println(tableName + " : " ) ;
String underline =
padString("", tableName.length()+1, " = " ) ;
System.out.println(underline);
int columnCount = results.getColumnCount();
String separator =
makeSeparator(entryWidth, columnCount);
System.out.println(separator);
String row = makeRow(results.getColumnNames0, entryWidth);
System.out.println(row);
System.out.println(separator);
int rowCount = results.getRowCount0;
for(int i=0; i<rowCount; i++) {
row = makeRow(results.getRow(i), entryWidth);
System.out.println(row);
}
System.out.println(separator);
}
// Строка в формате "| xxx | xxx | xxx I"
package cwp;
import java.sql.*;
import java.util.*;
}
}
buffer.append("\n</TABLE>");
return(buffer.toString());
}
}
package cwp;
import j a v a . s q l . * ;
/** Соединение с базой Oracle или Sybase и вывод
* таблицы employees.
V
p u b l i c c l a s s EmployeeTest {
p u b l i c s t a t i c void m a i n ( S t r i n g [ ] args) {
i f ( a r g s . l e n g t h < 5) {
printUsage ( ) ;
return;
}
S t r i n g vendorName = a r g s [ 4 ] ;
i n t vendor = D r i v e r U t i l i t i e s . g e t V e n d o r ( v e n d o r N a m e ) ;
i f (vendor == DriverUtilities.UNKNOWN) {
printUsage ( ) ;
return;
}
String driver = DriverUtilities.getDriver(vendor);
S t r i n g host = a r g s [ 0 ] ;
S t r i n g dbName = a r g s [ l ] ;
String url =
D r i v e r U t i l i t i e s . m a k e U R L ( h o s t , dbName, v e n d o r ) ;
S t r i n g username = a r g s [ 2 ] ;
S t r i n g password = a r g s [ 3 ] ;
DatabaseUtilities.printTable(driver, url,
username, pas sword,
"employees", 12, true)
}
1036 Глава 22. JDBC
package cwp;
import java.sql.*;
<TD>l<TD>Wye<TD>Tukay<TD>COBOL<TD>42500.О
<TR>
<TD>2<TD>Britt<TD>Tell<TD>C++<TD>62000.0
<TR>
<TD>3<TD>Max<TD>Manager<TD>none<TD>15500.0
<TR>
<TD>4<TD>Polly<TD>Morphic<TD>Sinalltalk<TD>51500.0
<TR>
<TD>5<TD>Frank<TD>Function<TD>Common Lisp<TD>51500.0
<TR>
<TD>6<TD>Justin<TD>Timecompiler<TD>Java<TD>98000.0
<TR>
<TD>7<TD>Sir<TD>Vlet<TD>Java<TD>114750.0
<TR>
<TD>8<TD>Jay<TD>Espy<TD>Java<TD>128500.0
</TABLE>
Листинг 22.13.EmployeeCreation.Java
package cwp;
import java.sql.*;
if (args.length < 5) {
printUsage();
return;
}
String vendorName = args[4];
int vendor = DriverUtilities.getVendor(vendorName);
if (vendor == DriverUtilities.UNKNOWN) {
printUsage();
return;
}
String driver = DriverUtilities.getDriver(vendor);
String host = args[0];
String dbName = args[l];
String url =
DriverUtilities.makeURL(host, dbName, vendor);
String username = args[2];
String password = args[3];
createEmployees(driver, url, username, password, true);
{шввшишвтяшшшшшшшшшшшш^шт
: ^ Of*cl« С Sybase
U«^narw. 1 Pa)5$wo«f; |
Ousry: 1
SfKi^Resciltg 1
Ou«iyOa!a •- ;-•
Ho«t jdbhosti apl jhu edu DBName:(PTE Ui^f <^ Orid« г $уЬдб» 1
IrisiivowRie^
1 b en 1 rrm-.frniVi ffiiTi rttir». muTifi
- <;iuaiyfllesu{t9
iD 1 RftSTHAME J LASTHAtiE { LANGUAGE \ S«.ARy II
1 Wye Tukay COBOL 42500
"<lue«yOaUi -
: Host jdbhostl apljhuedu . D0Name;|PTE Orhw: <^ OmtiB Г Sybase .'
jj BKowResiSs^t
1
Ouety Results - -
ID j FIR STKAME j LASTMAItE j LAMOUAGE 1 SAU
6 Justin Time compiler Java 98000
OueryData "-- ;-
if ShowRdsytts l l
Quejy Results
qwafter 1 apples | ajpplesalet j oraitges j of9ii$es3te« 1 tojpseHer \
1 32248 3547 28 :18459 313803 Maria i
II I I I l l l l l l l l l l l I — |||||||"";["f^f|
<Ju«ryD«ta
Host |dDhost2apljhu edu 00 Name J605741 Oilvef:^ Oracia c^ Sybase
1stwwRaa5tsn|
. Query RdsuH^
i7ti:r-7fnriTftTtri-iirriifniMmiHitii
apples fMr«ng««
32248 18459 и
1 11
42001 19333
Код QueryViewer
Написать программу, окна которой представлены на рис. 22.1-22.5, относительно
несложно. Если использовать средства класса D a t a b a s e U t i l i t i e s , рассмотренного
выше в этой главе, то объем кода, необходимого для взаимодействия с базой данных,
окажется даже меньше, чем объем кода, реализующего пользовательский интерфейс.
Исходный текст класса QueryViewer приведен в листинге 22.14, здесь же мы вкратце
опишем действия, выполняющиеся после щелчка на кнопке Show Results.
Сначала программа извлекает из интерфейсных элементов сведения об узле, пор
те и типе драйвера, а также имя базы данных, имя пользователя и пароль. После этого
QueryViewer передает запрос базе и сохраняет результаты.
DBResults results =
DatabaseUtilities.getQueryResults(driver, url,
username, password,
query, true);
1042 Глава 2 2 . JDBC
package cwp;
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public QueryViewer () {
super("Database Query Viewer");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
contentPane = getContentPane();
contentPane.add(makeControlPanel(), BorderLayout.NORTH);
packO ;
setVisible(true);
}
/** Если активизируется кнопка Show Results либо если
* пользователь нажимает клавишу <Enter> в момент, когда
* поле редактирования имеет фокус ввода, осуществляется
* обращение к базе данных, результаты помещаются в
* JTable и размеры окна изменяются с тем, чтобы в нем
* могла поместиться таблица.
22.5. Интерактивная программа просмотра запросов 1043
(BorderFactory.createTitledBorder("Query Results"));
return(panel);
package cwp;
import javax.swing.table.^;
Листинг 2 2 . 1 6 . P r e p a r e d S t a t e m e n t s . j a v a
p a c k a g e cwp;
import java.sql.*;
if (connection != null) {
doPreparedStatements(connection, print);
doRawQueries(connection, print);
}
}
throws SQLException {
while(results.next О ) {
System.out.print(results.getString(1) + " " ) ;
}
System.out.println();
}
22.7. Резюме
JDBC обеспечивает стандартные средства взаимодействия программ, написанных
на Java, с реляционными базами данных. При этом нет необходимости в использова
нии кода, зависящего от производителя базы, что упрощает процесс работы с не
сколькими базами данных или переход от одной базы к другой.
Несмотря на то что JDBC стандартизует механизм взаимодействия с базами дан
ных и структуру данных, получаемых в составе ответа, попытки стандартизовать SQL-
синтаксис не предпринимаются. Это значит, что в составе запросов должны присут
ствовать SQL-команды, специфические для базы данных конкретного производителя.
SQL-запросы создаются в виде строк символов; специальные методы, предназначен
ные для этой цели, отсутствуют.
Средства JDBC могут использоваться приложениями и аплетами. При этом следует
помнить, что возможности аплета по установке соединений ограничены узлом, с кото
рого этот аплет был загружен. Чаще всего JDBC-взаимодействие выполняют приложе
ния, работающие на стороне сервера, в частности сервлеты и JSP. На стороне сервера
основная задача решается системами управления базами данных; сервлеты и JSP выпол
няют роль программ промежуточного уровня, обеспечивая базе передачу информации,
переданной броузером, и форматирование результатов, полученных от базы.
ОБРАБОТКА
XML-ДОКУМЕНТОВ
В этой главе...
С п е ц и ф и к а ц и я X M L LО
http://www.w3.org/TR/REC-xml
И н ф о р м а ц и я WWW C o n s o r t i u m о б XML
http://www.w3.org/XML/
A p a c h e X M L Project
http://xml.apache.org/
O'Reilly X M L R e s o u r c e C e n t e r
http://www.xml.com/
Инсталляция и настройка
DOM не является стандартным компонентом ни Java 2 Standard Edition, ни API
севлетов и JSP. Поэтому, чтобы обеспечить работу с DOM, необходимо скопировать
требуемые классы и настроить их. Для этого надо выполнить следующие действия.
1. Скопировать DOM-совместимые средства разбора. П р и этом вы получаете
Java-классы, совместимые с DOM Level 2 API. Список доступных средств разбо
ра находится по адресу h t t p : / / w w w . x m l . c o m / p u b / r g / J a v a _ P a r s e r s . В дан
ной книге мы используем для этой цели Apache Xerces-J. В комплекте с данным
средством разбора поставляется полное описание DOM API в формате Javadoc.
2. Скопировать Java API для обработки XML (JAXP). Данный API реализует
"поверх" DOM специальный слой, который позволяет работать со средствами
разбора различных производителей, не внося изменений в код программы.
Указанный API находится по адресу h t t p : / / J a v a . s u n . c o m / x m l / .
3. Включить информацию о классах DOM в состав переменной окруясения
CLASS PATH. Работая с Apache Xerces, надо предусмотреть в CLASS PATH запись
x e r c e s _ i n s t a l l _ d i r \ x e r c e s . j a r . Например, для приложений в системе
Windows соответствующая установка CLASS PATH будет иметь такой вид:
set CLASSPATH=xerces_install_dir\xerces.jar;%CLASSPATH%
2 3 . 1 . Разбор XML-документа посредством DOM Level 2 1053
Разбор
Для того чтобы выполнить обработку документа средствами DOM, надо решить
две основные задачи: преобразовать XML-текст в структуру данных DOM и найти в
этой структуре интересующую вас информацию. Ниже описаны основные действия,
необходимые для решения данных задач.
1. Сообщить системе, какие средства разбора вы намереваетесь использо
вать. Это можно сделать различными способами: с помощью системного свой
ства p a r s e r s . D o c u m e n t B u i l d e r F a c t o r y , посредством j r e _ d i r / l i b / j a x p .
p r o p e r t i e s , используя J2EE Sei"vices API и класс, заданный в МЕТА-INF/
s e r v i c e s / j a v a x . x m l . p a r s e r s . DocumentBuilderFactory. Кроме того, можно
использовать средства разбора, принятые по умолчанию для конкретной сис
темы. Проще всего воспользоваться DocumentBuilderFactory. Ниже приве
ден фрагмент кода, который позволяет пользователю указать средства разбора
в командной строке с помощью опции -D. Если данная опция отсутствует, ис
пользуется Apache Xerces.
public static void main(String[] args) {
String jaxpPropertyName =
"j avax.xml.parsers.DocumentBuilderFactory" ;
if {System.getProperty{jaxpPropertyName) == null) {
String apacheXercesPropertyValue =
"org.apache.xerces.jaxp.DocumentBuilderFactorylmpl";
System.setProperty(jaxpPropertyName,
apacheXercesPropertyValue);
}
1054 Глава 23. Обработка XML-документов
}
2. Создать JAXP-объект для построения документов. О н представляет собой
оболочку для средств разбора XML.
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newlnstance();
DocumentBuilder b u i l d e r =
builderFactory.newDocumentBuilder();
Заметьте, что для работы с пространством имен можно использовать методы
s e t N a m e s p a c e A w a r e и s e t V a l i d a t i n g класса D o c u m e n t B u i l d e r F a c t o r y .
3. Вызвать средство разбора для создания объекта Document, представляю
щего XML-документ. Средство разбора вызывается посредством метода p a r s e
объекта создания документа. Этому методу передается входной поток, URI
(представленный в виде строки) или объект o r g . x m l . s a x . I n p u t S o u r c e .
Класс Document содержит результаты разбора, о ф о р м л е н н ы е в виде древовид
ной структуры.
Document document = builder.parse(somelnputStream);
4. Нормализовать дерево. Нормализация подразумевает объединение узлов для
нескольких строк и удаление пустых узлов.
document.getDocumentElement().normalize();
5. Получить корневой узел дерева. Корневой узел возвращается как объект
E l e m e n t , являющийся подклассом более общего класса Node, представляюще
го XML-элемент.
Element rootElement = document.getDocumentElement ();
6. Проверить свойства узла. К этим свойствам относятся имя элемента
(getNodeName), тип узла ( g e t N o d e T y p e ; возвращаемые значения сравниваются с
константами, определенными в классе Node), значение узла ( g e t N o d e V a l u e ; для
текстовых узлов значение представляет собой строку символов, содержащуюся
между открывающим и закрывающим дескрипторами элемента), атрибуты, при-
сутствутощие в открывающем дескрипторе ( g e t At t r i b u t e s ) , и дочерние узлы
( g e t C h i l d N o d e s ; элементы, содержащиеся между открывающим и закрываю
щим дескрипторами тек}тцего элемента). Каждый из дочерних узлов можно про
верить рекурсивно.
7. Модифицировать свойства узлов. Вместо извлечения данных из XML-доку
мента можно модифицировать документ, добавляя ( a p p e n d C h i l d ) или удаляя
( r e m o v e C h i l d ) дочерние узлы либо изменяя значение узла ( s e t N o d e V a l u e ) .
К сожалению, DOM не предоставляет стандартных методов вывода DOM-струк
туры в текстовом формате. Поэтому вы должны либо сделать это самостоя
тельно (вывести символ "<", имя узла, имена и значения атрибутов, разделен
ные знаком равенства, поместив значения атрибутов в кавычки, и завершить
вывод символом ">"), либо воспользоваться одним из существующих пакетов,
генерирующих текстовое представление DOM-элемента.
2 3 . 2 . Пример использования DOM... 1055
ШЕШШШШШШШШШ шшшшшшшшшшшш^
Lookin. j iCWP-Code
jii ^ ^ Й1 Jil®
лЯ\ cwp-taglib.tid
|i*) orders.xml
iifi] teslxml
^E;\CWP2\XML-Code\CWP-Code\p€
S perennials
* ._„] ciaylily(status=in-stock)
шщ ^E:\CWP2\XML-Code\CWP-Code\perennials.xmliililO
-
•^ perennials
„>4 daylily (status=in-stock)
+ 5 daylily (status=in-stock) * cultlvar
+ ..J daylily (status=sold-out) •*•' ,„ J award
+ I daylily (status=in-stock) - _J award
> ™i daylily (status=limited) # name (note=snnall-flowered)
» year
+ I award
« bloom (code=M)
* cost(currency^US, dlscount=3)
+ ; d ay 11 ly (statu s=i n- sto с k)
- ^ daylily (status=sold-ou^
* cultivar
% award
* name
« year
» bloom (code=E)
* cost(currency=US)
• < daylily (status=in-stock)
+ ™J daylily (status=limlted)
Листинг 23.1.XMLTree.java
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.^;
/** Данный класс генерирует объект JTree, который
* представляет структуру XML-документа, содержащегося
* в указанном файле либо полученного через заданный
* входной поток. Для разбора используется DOM.
V
public class XMLTree extends JTree {
public XMLTree(String filename) throws lOException {
this(filename, new FileInputStream(new File(filename)))
23.2. Пример использования DOM... 1057
}
public XMLTree(String filename, InputStream in) {
super(makeRootNode(in));
}
// Данный метод должен быть объявлен как static, поскольку
/ / о н вызывается при обращении к родительскому конструктору
// (super). В этот момент объект еще на создан.
private static DefaultMutableTreeNode
makeRootNode(InputStream in) {
try {
// Благодаря использованию JAXP DocumentBuilderFactory
// код не зависит от конкретных средств разбора DOM.
// Для указания используется системное свойство
// javax.xml.parsers.DocumentBuilderFactory
// (устанавливается либо из Java-программы, либо
// посредством опции -D) или
// jre_dir/lib/jaxp.properties.
DocumentBuilderFactory builderFactory =
DocvimentBuilderFactory. newlnstance () ;
DocumentBuilder builder =
builderFactory.newDocumentBuilder();
// Стандартный DOM-код. Метод parse запускает процесс
// разбора и возвращает полностью обработанный объект
// Document. Рекурсивно обходя дерево, мы копируем
// узлы (не текстовые) в узлы JTree.
Document document = builder.parse(in);
document.getDocumentElement().normalize();
Element rootElement = document.getDocumentElementO;
DefaultMutableTreeNode rootTreeNode =
buildTree(rootElement);
return(rootTreeNode) ;
} catch(Exception e) {
String errorMessage =
"Error making root node: " + e;
System.err.println(errorMessage);
e.printStackTrace();
return(new DefaultMutableTreeNode(errorMessage));
}
}
private static DefaultMutableTreeNode
buildTree(Element rootElement) {
// Для корневого узла создается узел JTree, после чего
// для каждого дочернего узла создается узел JTree и
// добавляется к корневому узлу. Метод addChildren
// вызывается рекурсивно.
DefaultMutableTreeNode rootTreeNode =
new DefaultMutableTreeNode(treeNodeLabel(rootElement)) ;
addChildren(rootTreeNode, rootElement);
return(rootTreeNode);
}
private static void addChildren
(DefaultMutableTreeNode parentTreeNode,
1058 Глава 23. Обработка ХМЬ-документов
Node parentXMLElement) {
// Данный метод вызывается рекурсивно, находит дочерние
// элементы и присоединяет их к родительскому узлу.
/ / В данном случае используются два типа узлов: узлы,
// отражающие структуру XML-документа, и узлы,
// соответствующие графическому представлению JTree.
// Для узлов, соответствующих графическому представлению
// Jtree, будем использовать в составе имен переменных in the
// слово "tree". Таким образом, "childElement" - дочерний
// XML-элемент, а "childTreeNode" - JTree-элемент.
// Данный метод копирует узлы, отличные от текста и
// комментариев, из структуры XML в структуру JTree.
NodeList childElements =
parentXMLElement.getChildNodes();
for(int i=0; i<childElements.getLength(); i++) {
Node childElement = childElements.item(i);
if (!(childElement instanceof Text ||
childElement instanceof Comment)) {
DefaultMutableTreeNode childTreeNode =
new DefaultMutableTreeNode
(treeNodeLabel(childElement));
parentTreeNode.add(childTreeNode);
addChildren(childTreeNode, childElement);
}
}
}
// Если XML-элемент не содержит атрибутов, узел JTree
// получает имя XML-элемента. При наличии атрибутов
/ / и х имена и значения указываются в скобках после имени
// XML-элемента.
import java.awt.*;
import javax.swing.*;
import java.io.*;
content.add(new JScrollPane(tree));
frame.раск() ;
frame.setVisible(true);
} catch(lOException ioe) {
System.out.println("Error creating tree: " + ioe)
}
import Java.io.File;
import java.util.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
return(getFileName(initialDirectory, description,
extensions, mode));
}
public static String getFileName(String initialDirectory,
String description.
String[] extensions) {
return(getFileName(initialDirectory, description,
extensions, LOAD));
}
<year>1965</year>
</award>
<award>
<name>Lenington All-American</name>
<year>1970</year>
</award>
<bloom code="M">Midseason</bloom>
<cost discount="3" currency="US">ll.75</cost>
</daylily>
<daylily status="in-stock">
<cultivar>Green Flutter</cultivar>
<award>
<name>Stout Medal</naine>
<year>197 6</year>
</award>
<award>
<name note="small-flowered">Annie T. Giles</name>
<year>1970</year>
</award>
<bloom code="M">Midseason</blooiTi>
<cost discount="3+" currency="US">7.50</cost>
</daylily>
<daylily status="sold-out">
<cultivar>My Belle</cultivar>
<award>
<name>Stout Medal</name>
<year>1984</year>
</award>
<bloom code="E">Early</bloom>
<cost currency="US">12.00</cost>
</daylily>
<daylily status="in-stock">
<cultivar>Stella De Oro</cultivar>
<award>
<name>Stout Medal</name>
<year>1985</year>
</award>
<award>
<name note="miniature">Donn Fishcer Memorial Cup</name>
<year>197 9</year>
</award>
<bloom code="E-L">Early to Late</bloom>
<cost discount="10+" currency="US">5.00</cost>
</daylily>
<daylily status="limited">
<cultivar>Brocaded Gown</cultivar>
<award>
<name>Stout Medal</name>
<year>198 9</year>
</award>
<bloom code="E">Early</bloom>
<cost currency="US" discount="3+">14.50</cost>
</daylily>
</perennials>
1064 Глава 23. Обработка XML-доку ментов
Листинг 23.5. p e r e n n i a l s . d t d
Инсталляция и настройка
SAX не является стандартным компонентом ни Java 2 Standard Edition, ни API
сервлетов и JSP. Поэтому, чтобы обеспечить работу с SAX, необходимо скопировать
требуемые классы и настроить их для использования в вашей программе, т.е. выпол
нить следующие действия.
Разбор
Чтобы выполнить обработку документа средствами SAX, надо решить две основ
ные задачи: создать объект поддержки содержимого и вызвать средств разбора для
этого объекта. Ниже описаны основные действия, необходимые для решения данных
задач.
1. Сообщить системе, какие средства разбора вы намереваетесь использовать.
Это можно сделать различными способами: с помощью системного свойства
j a v a x . x m l . p a r s e r s . SAX-ParserFactory, посредством j r e _ d i r / l i b / j a x p .
p r o p e r t i e s , используя J2EE Services API и класс, заданный в МЕТА-INF/
s e r v i c e s / j a v a x . x m l . p a r s e r s . SAX-ParserFactory. Кроме того, можно ис
пользовать средства разбора, принятые по умолчанию для конкретной системы.
Ниже приведен фрагмент кода, который позволяет пользователю указать средст
ва разбора в командной строке с помощью опции -D. Если данная опция отсутст
вует, используется Apache Xerces.
public static void main(String[] args) {
String jaxpPropertyName =
"javax.xml.parsers.SAXParserFactory";
if (System.getProperty(jaxpPropertyName) == null) {
String apacheXercesPropertyValue =
"org.apache.xerces.j axp.SAXParserFactorylmpl";
System.setProperty(jaxpPropertyName^
apacheXercesPropertyValue);
}
}
2. Создать экземпляр объекта для разбора документов. Для этого надо сначала
создать фабрику объектов, а затем сам объект разбора.
SAXParserFactory f a c t o r y = S A X P a r s e r F a c t o r y . n e w l n s t a n c e ( ) ;
SAXParser p a r s e r = f a c t o r y . n e w S A X P a r s e r ( ) ;
Заметьте, что для работы с пространством имен можно использовать методы
setNamespaceAware и s e t V a l i d a t i n g класса SAXParserFactory.
3. Создать объект поддержки содержимого для обработки событий разбора.
Данный объект поддержки обычно представляет собой подкласс класса
D e f a u l t Handler; в нем надо переопределить некоторые из описанных ниже
методов.
• startDocument, endDocument
Эти методы переопределяются для того, чтобы выполнять требуемые дейст
вия в начале и в конце разбора документа. Они вызываются без параметров.
• startElement, endElement
23.4. Пример использования SAX: вывод общих сведений... 1067
• startElement
Данный метод выводит сообщение о том, что найден открывающий дескрип
тор элемента. Атрибуты, связанные с этим элементом, отображаются в скобках.
Этот метод начинает отображение данных выводом пробелов. Число пробелов
определяется переменной i n d e n t a t i o n . Перед завершением работы данный
метод увеличивает значение i n d e n t a t i o n на 2 (в начале работы программы
значение этой переменной устанавливается равным 0).
• endElement
Данный метод уменьшает значение переменной i n d e n t a t i o n на 2, после чего
выводит сообщение о том, что встретился закрывающий дескриптор элемента.
• characters
Метод c h a r a c t e r s отображает первое слово в теле элемента; уровень отступа,
определяемый переменной i n d e n t a t i o n , остается неизменным.
1068 Глава 23. Обработка XML-документов
ШЕЕОВНВШВН! ШШШШШШШШЩ
Lookr»: , J„jCWP-Code
"3 ^ ^ j ^ i g p l
.:?^Yt«^r?i^
Ilia) cwp-tagllb-Md
| i « | perennials.xml
1 *il test.xml
9.95
End tag: price
Start tag: yacht
Start tag: manufacturer
Luxury...
End tag: manufacturer
Start tag: model
M-1
End tag: model
Start tag: standardFeatures (oars=plastic, lifeVests=none)
false
End tag: standardFeatures
End tag: yacht
End tag: order
... (Остальные результаты пропущены)
End tag: orders
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.util.StringTokenizer;
/** Класс поддержки содержимого, который выводит сведения
* об открывающем и закрывающем дескрипторах, а также
* первое слово в теле элемента. Для каждого вложенного
* элемента отступ увеличивается на два пробела.
System.out.print(", " ) ;
}
System.out.print(attributes.getQName(i) + "=" +
attributes.getValue(i));
}
System.out.print(")");
}
System.out.println();
indentation = indentation + 2;
Листинг 23.8.SAXPrinter.Java
import j a v a x . x m l . p a r s e r s . * ;
import o r g . x m l . s a x . * ;
import org.xml.sax.helpers.*;
/** Программа, использующая SAX для вывода данных об
* открывающих и закрывающих дескрипторах в ХМЬ-файле,
* а также первых слов в теле элемента.
<isbn>0130897 930</isbn>
<title>Core Web Programming Second Edition</title>
<authors>
<author>Marty Hall</author>
<author>Larry Brown</author>
</authors>
</book>
</order>
</orders>
</book>
</orders>
Программа подсчитывает, сколько экземпляров книги с указанным ISBN содер
жится в составе набора заказов. Таким образом, большинство элементов в файле не
представляет никакого интереса. Поскольку в SAX, в отличие от DOM, не предусмот
рено автоматическое хранение данных, необходимо специально позаботиться о том,
чтобы требуемая информация была записана. При этом возникают трудности, свя
занные с тем, что элемент i s b n располагается после элемента count. Поэтому значе
ние count надо временно сохранять, но учитывать его в общем объеме заказов следу
ет только в том случае, если значение i s b n совпадает с ISBN интересующей книги.
Для того чтобы данная задача могла быть выполнена, в объекте поддержки содержи
мого переопределены следующие четыре метода.
• startElement
Данный метод проверяет, совпадает ли имя элемента со значением count или
i s b n . Если совпадение обнаружено, то устанавливается соответствующий флаг,
который сообщает методу c h a r a c t e r s о том, что содержимое элемента долж
но быть обработано.
• endElement
Метод endElement проверяет, совпадает ли имя элемента со значением count
или i s b n . Если совпадение обнаружено, сбрасывается флаг, установленный в
методе s t a r t E l e m e n t .
1074 Глава 23. Обработка XML-доку ментов
• characters
Если установлен флаг c o u n t , данный метод разбирает значение элемента, пре
образует его в тип i n t и сохраняет до получения данных об элементе i s b n . Ес
ли установлен флаг i s b n , метод читает информацию в теле дескриптора и
сравнивает ее с требуемым значением ISBN. П р и положительном результате
сравнения временно сохраненное содержимое c o u n t добавляется к значению
основного счетчика, учитывающего общее количество заказов на книгу.
• endDocument
Данный метод выводит значение основного счетчика. Если заказано менее 250
экземпляров книги, программа советует сделать в будущем больше заказов.
Юхасс C o u n t B o o k s (листинг 23.11) применяет к XML-файлу средство разбора, ука
занное пользователем. В качестве объекта поддержки содержимого используется
C o u n t H a n d l e r . На рис. 23.5 показано окно выбора файла, а на рис. 23.6 — результаты
обработки файла o r d e r s . xml (см. листинг 23.9).
Is^iifW.!
Look In: jljCWP-Code "3 ©j _gj d^ s pm
_л] cwp-taglib.tid
л\ perennialsj<ml
«3 test.xml ^Message
Y o u Ofder^Kl ^ ?OJ>l^«; "HH
import org.xml.sax.^;
import org.xml.sax.helpers.*;
import java.util.StringTokenizer;
import javax.swing.*;
* <count>23</count>
* <book>
* <isbn>01308 97 930</isbn>
</book>
</ХМР>
Прочая информация, содержащаяся в документе,
23.5. Пример использования SAX: подсчет заказов на книги 1075
* не учитывается.
V
public class CountHandler extends DefaultHandler {
private boolean collectCount = false;
private boolean collectlSBN = falser-
private int currentCount = 0;
private int totalCount = 0;
Листинг 23.11.CountBooks.Java
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
* </ХМР>
* Прочая информация в составе документа игнорируется.
23.6. Преобразование XML посредством XSLT 1077
XSLT L 0
http://www.w3.org/TR/xslt.html
XSL LO
http://www.w3.org/TR/xsl/
XPath LO
http://www.w3.org/TR/xpath.html
Кроме того, информацию об XSLT, XSL и XPath можно получить, обратившись к
URL h t t p : / / w w w . w 3 . o r g / S t y l e / X S L / . Узел, поддерживаемый GoXML и содержа
щий XSLT-ресурсы, расположен по адресу h t t p : //www. x s l t . com/.
Инсталляция и настройка
XSLT не является стандартным компонентом ни Java 2 Standard Edition, ни API
сервлетов и JSP. Поэтому, чтобы обеспечить работу с XSLT, необходимо скопировать
требуемые классы и настроить их для использования в вашей программе, т.е. выпол
нить следующие действия.
L Скопировать XSLT-совместимые средства преобразования. К ним относятся
Java-классы, соответствующие спецификации XSLT LO. Список средства разбо
ра XSLT можно получить по адресу h t t p : / / w w w . w 3 . o r g / S t y l e / X S L / или
h t t p : / / w w w . x s l t . c o m / x s l t _ t o o l s _ e n g i n e s . h t m . П р и написании данной
книги использовался продукт Apache Xalan-J ( h t t p : / / x m l . a p a c h e . o r g /
xalan-j /).
2. Учесть в п е р е м е н н о й окрулсения CLASSPATH к л а с с ы DOM и SAX. Работа
средств XSLT базируется на DOM и SAX. П р и использовании Apache Xalan-J на
до указать в составе CLASSPATH архив x e r c e s . j a r . Конфигурация Apache
Xalan-J была рассмотрена в разделах 23.1 и 23.3. Заметьте, что x e r c e s . j a r
включает инсталляционный каталог Apache Xalan-J.
3. Учесть в п е р е м е н н о й о к р у ж е н и я CLASSPATH к л а с с ы XSLT. П р и работе с
Xalan эти классы находятся в архиве x a l a n _ i n s t a l l _ d i r \ x a l a n . j a r . На
пример, для Windows следует задать
set CLASSPATH=xalan_install_dir\xalan.jar;
%CLASSPATH%
23.6. Преобразование XML посредством XSLT 1079
Для UNIX/Linux и оболочки С shell данная установка будет иметь следующий вид:
setenv CLASSPATH xalan_install_dir/xalan.jar:
$CLASSPATH
Если вы собираетесь использовать XSLT в сервлетах и JSP, вам следует скопи
ровать JAR-файлы DOM, SAX и XSLT в каталог l i b сервера, распаковать JAR-
файл (используя для этого команду j a r - x v f ) в каталог c l a s s e s либо изме
нить переменную окружения сервера CLASSPATH; обычно это выполняется в
сценарии запуска сервера.
4. Обеспечить доступ к спецификациям XSL L0 и XPath L0. Официальные доку
менты, содержащие данные спецификации, находятся по адресу h t t p : / / w w w .
w3.org/Style/XSL/.
5. Обеспечить доступ к спецификации XSLT. Спецификацию XSLT можно най
ти по адресу h t t p : / / w w w . w 3 . o r g / T R / x s l t . h t m l . В составе Apache Xalan
спецификация XSLT реализована посредством ТгАХ (Transformation API for
XML— API преобразования для XML). Документация по ТгАХ API в формате
Javadoc доступна по адресу h t t p : / / x m l . a p a c h e . o r g / x a l a n - j / a p i d o c s / .
Преобразование
в процессе XSLT-конвертирования решаются две основные задачи: создание XSL-
шаблона и запуск процедуры преобразования XML-документа. Н и ж е описаны основ
ные действия, необходимые для выполнения этих задач.
1. Сообщить системе, какое средство разбора доллсно использоваться для
преобразования. Это можно сделать несколькими способами: посредством сис
темного свойства j a v a x . x m l . t r a n s f o r m . T r a n s f o r m F a c t o r y , с помощью
j r e _ d i r / l i b / j a x p . p r o p e r t i e s , используя J2EE Services API и класс, заданный
в M E T A - I N F / s e r v i c e s / j a v a x . x m l . t r a n s f o r m . T r a n s f o r m F a c t o r y . Кроме то
го, можно использовать средства обработки, принятые по умолчанию для кон
кретной системы. Поскольку XSLT зависит от DOM и SAX, необходимо сообщить
системе, какие средства разбора DOM и SAX должны применяться при обработке
документа. Конфигурация средств DOM и SAX была рассмотрена в разделах 23.1
и 23.3. По умолчанию Apache Xalan-J использует Apache Xerces-J.
2. Сформировать фабрику объектов для создания преобразователей. Перед
обработкой XML-документа необходимо создать объект T r a n s f o r m e r F a c t o r y .
О н позволяет создать различные преобразователи для разных шаблонов, за
данных посредством листов стилей.
TransformerFactory factory =
TransformerFactory.newlnstance();
3. Создать преобразователь для конкретного шаблона. Для всех листов стилей
можно сгенерировать отдельные преобразователи. Каждый преобразователь
применим к различным XML-документам.
S o u r c e x s l = new S t r e a m S o u r c e ( x s l S t r e a m ) ;
Templates template = factory.newTemplates(xsl);
Transformer transformer = template.newTransformer();
1080 Глава 23. Обработка ХМЬ-документов
Листинг 2 3 . 1 2 . X s l T r a n s f o r m e r . j a v a
p a c k a g e cwp;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import java.io.*;
import java.util.*;
public XslTransformer() {
factory = TransformerFactory.newlnstance0;
}
23.6. Преобразование XML посредством XSLT 1081
Л и с т и н г 2 3 . 1 3 . X s l t E x a m p I e . Java
import javax.xml.transform.*;
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import cwp.XslTransformer;
public XsltExample() {
super(DEFAULT_TITLE) ;
transformer = new XslTransformer();
WindowUtilities.setNativeLookAndFeel();
Container content = getContentPane{);
content.setBackground(SystemColor.control);
// Установка меню.
JMenuBar menubar = new JMenuBar();
openAction = new OpenAction()
saveAction = new SaveAction{)
exitAction = new ExitAction()
JMenu fileMenu = new JMenu("File");
fileMenu.add(openAction);
fileMenu.add(saveAction);
fileMenu.add(exitAction);
menubar.add(fileMenu) ;
setJMenuBar(menubar) ;
// Установка вкладок.
tabbedPane = new JTabbedPane();
documents = new DocumentPane[3];
for(int i=0; i<3; i++) {
documents[i] = new DocumentPane();
JPanel panel = new JPanelO;
JScrollPane scrollPane = new JScrollPane(documents[i]);
panel.add(scrollPane) ;
tabbedPane.add(tabTitles[i], scrollPane);
}
documents[XSLT].setContentType(DocumentPane.HTML);
// Компонент JEditorPane содержит ошибку: метод setText
// некорректно распознает HTML-документ, в состав которого
// входит элемент МЕТА, содержащий CONTENT-TYPE.
// Это не происходит, если предварительно посредством setPage
// создается EditorKit. Xalan автоматически добавляет
/ / к документу МЕТА CONTENT-TYPE. Таким образом, необходимо
1084 Глава 23. Обработка XML-документов
documents[XSLT].loadFile("XSLT-Instructions.html");
documents[XSLT].setEditable(false);
tabbedPane.addChangeListener(this);
content.add(tabbedPane, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize (450, 350);
setVisible(true);
}
setTitle(title);
}
}
import java.awt.*;
import Java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
* <code>setText</code>.
Листинг 2 3 . 1 5 . p e r e n n i a l s . x s l
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE>Daylilies</TITLE>
</HEAD>
23.7. Пример использования XSLT: редактор документов 1089
<BODY>
<TABLE CELLPADDING^"3">
<CAPTION>Stout Medal Award</CAPTION>
<TR>
<TH>Year</TH>
<TH>Cultivar</TH>
<TH>Bloom Season</TH>
<TH>Cost</TH>
</TR>
< ! — Выбор элементов daylily, содержащих элемент
award, для которого значение элемента name
равно Stout Medal. -->
<xsl:apply-templates
select="/perennials/daylily[award/nanie='Stout Medal*]"/>
<TR>
<TD C0LSPAN="4" ALIGN="CENTER">
E-early M-midseason L-late</TD>
</TR>
</TABLE>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="daylily">
<TR>
<TD><xsl:value-of select="award/year"/></TD>
<TD><xsl:value-of select="cultivar"/></TD>
< ! — Выбор bloom. -->
<TD ALIGN="CENTER"><xsl:value-of select="bloom/@code"/></TD>
<TD ALIGN="RIGHT"><xsl:value-of select="cost"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
^ jfM
Рис. 23.7. Внешний вид вкладки XML, содер Рис. 23.8. Внешний вид вкладки XSL,
жащей XML-код, загруженный из файла содержащей XSL-код, загруженный из файла
p e r e n n i a l s .xml (листинг 23.4) p e r e n n i a l s . x s l (листинг23.15)
1090 Глава 23. Обработка XML-документов
|к^Ж-^к^Д!т'1^|ЦШ|Я -lOlxlj
FISe
TOMCAT_HOME/webapps/ROOT/
• cwp/Daylilies.jsp
L cwp-tags/xsltransform.tid
WEB-INF/classes/cwp/perennials.xml
perennials-ie.xml
perennials-ns.xsl
XslTransformer.class
U dtds/perennials.dtd
L tags/XslTransformTag.class
Листинг 2 3 . 1 6 . p e r e n n i a l s - i e . x s l
<COL ALIGN="CENTER"/>
</COLGROUP>
<COLGROUP ALIGN="RIGHT"/>
<THEAD>
<TR>
<TH>Year</TH>
<TH>Cultivar</TH>
<TH>Bloom Season</TH>
<TH>Cost</TH>
</TR>
</THEAD>
<TBODY>
< ! — Выбор элементов daylily, содержащих элемент
award, для которого значение элемента name
равно Stout Medal. — >
<xsl:apply-templates
select="/perennials/daylily[award/name= * Stout MedalЧ"/>
</TBODY>
<TFOOT>
<TR>
<TD C0LSPAN="4">E-early M-midseason L-late</TD>
</TR>
</TFOOT>
</TABLE>
</xsl:template>
<xsl:template match="daylily">
<TR>
<TD><xsl:value-of select="award/year"/></TD>
<TD><xsl:value-of select="cultivar"/></TD>
<!-- Выбор bloom. — >
<TD><xsl:value-of select="bloom/@code"/></TD>
<TD><xsl:value-of select="cost"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Листинг 2 3 . 1 7 . p e r e n n i a l s - n s . x s l
<?xml version="l.0"?>
< ! — Использование основных элементов, предназначенных
для создания таблицы. — >
< ! — Данный код ориентирован на броузер Netscape. -->
<xsl:stylesheet version="l.О"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<TABLE CELLPADDING="3" B0RDER="1" ALIGN="CENTER">
<CAPTION>Stout Medal Award</CAPTION>
<TR>
<TH>Year</TH>
<TH>Cultivar</TH>
<TH>Bloom Season</TH>
<TH>Cost</TH>
23.8. Пример использования XSLT... 1093
</TR>
< ! — Выбор элементов daylily, содержащих элемент
award, для которого значение элемента name
равно Stout Medal. — >
<xsl:apply-templates
select="/perennials/daylily[award/name=*Stout Medal']"/>
<TR>
<TD C0LSPAN="4" ALIGN="CENTER">
E-early M-midseason L-late</TD>
</TR>
</TABLE>
</xsl:template>
<xsl:template match="daylily">
<TR>
<TD><xsl:value-of select="award/year"/></TD>
<TD><xsl:value-of select="cultivar"/></TD>
< ! — Выбор bloom. — >
<TD ALIGN="CENTER"><xsl:value-of select="bloom/@code"/></TD>
<TD ALIGN="RIGHT"><xsl:value-of select="cost"/></TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Листинг 23.18.Daylilies.j sp
Листинг 23.19.xsltransform.tld
<taglib>
1094 Глава 23. Обработка XML-доку ментов
<tlibversion>l.0</tlibversion>
<jspversion>l. К/jspversion>
<shortname>cwp</shortname>
<urn></urn>
<info>
A tag library from Core Web Programming,
http://www.corewebprogramming.com/.
</info>
<tag>
<name>xsltransform</name>
<tagclass>cwp.tags.XslTransformTag</tagclass>
<info>Applies xslt transform based on browser type.</info>
<attribute>
<name>xml</name>
<required>yes</required>
</attribute>
<attribute>
<name>xslie</name>
<required>false</required>
</attribute>
<attribute>
<name>xslns</name>
<required>true</required>
</attribute>
</tag>
</taglib>
Листинг 23.20.XslTransformTag.Java
package cwp.tags;
import java.io.*;
import javax.servlet.*;
import javax.servlet.jsp.*;
import javax.servlet.http.*;
import javax.servlet.j sp.tagext.*;
import javax.xml.transform.*;
import cwp.XslTransformer;
HttpServletRequest request =
(HttpServletRequest)pageContext.getRequest();
catch(TransformerException tx) {
context.log("XslTransformTag: " + tx.getMessage());
}
return(SKIP_BODY);
}
1096 Глава 23. Обработка XML-документов
b-^^lS, '. ji
^
Katie^s Favorite Daylilies
Stout Medal Award
ш:\пЩ
Ш Ы )£ifw Шо Sioemxm^it НФ
а ^ т ^ ^ ^ Ш ' ^ rfa
Katie^s Favorite Daylilies
Stout Medal Award
23.9. Резюме
Данная глава завершает часть III, посвященную созданию программ, предназна
ченных для выполнения на стороне сервера. Теперь вы знаете, как обрабатывать
XML-файлы с помощью DOM, SAX и XSLT. Вы также умеете создавать сервлеты и
JavaServer Pages, выполнять НТТР-туннелирование и организовывать взаимодействие
с базами данных посредством JDBC. Несомненно, что вы уже пробовали применять
полученные знания на практике и ваш начальник наверняка оценил результаты.
(А может быть, вы и сами уже стали начальником?)
В следующей части книги мы вернемся к рассмотрению программ, выполняющих
ся на стороне клиента, и обсудим JavaScript — интерпретируемый язык, предназна
ченный для написания сценариев, которые запускаются в среде броузера. Примене
ние JavaScript-сценариев позволяет сделать Web-страницу более гибкой и динамич
ной. В частности, JavaScript-сценарии очень часто применяются для проверки
данных, введенных посредством HTML-формы, перед передачей их на сервер.
-JzJS^-r±
JAVASCRIPT
В ЭТОЙ части...
В ЭТОЙ главе...
Синтаксис JavaScript.
Текущее положение дел с JavaScript несколько осложняется тем, что Microsoft вы
пустила собственную реализацию стандарта ECMAScript под названием JScript. Не
смотря на то что Microsoft предоставляет различные платформы для выполнения
сценариев (Internet Information Server, Windows Scripting Host, Visual Studio), под
держивающие разные версии JScript, мы вкратце рассмотрим лишь версии JScript,
поддерживаемые Internet Explorer. Средства JavaScript 1.1 в основном реализованы в
Internet Explorer З.Ох; полную поддержку JavaScript 1.2 и соответствие второй редак
ции ЕСМА-262 обеспечивает Internet Explorer 4.Ox. Internet Explorer 5.0x поддержива
ет JavaScript 1.3 и большинство средств JavaScript 1.4. В Internet Explorer реализованы
полная поддержка третьей редакции ЕСМА-262 и спецификации JavaScript 1.5.
Основные языковые средства JavaScript с момента создания версии 1.2 не претер
пели существенных изменений и поддерживаются практически всеми популярными
броузерами (в частности, Netscape 4, Internet Explorer 4 и более поздними версиями).
Рассмотрению этих языковых средств посвящены эта и следующая главы. DOM
(Document Object Model — объектная модель документа) для реализации DHTML об
суждаться не будет. Сведения о DOM и различных версиях языков сценариев вы най
дете по следующим адресам.
С п е ц и ф и к а ц и я ECMAScript
h t t p : / / w w w . e c m a . c h / e c m a l / S T A N D / E C M A - 2 62.HTM
И н ф о р м а ц и я д л я р а з р а б о т ч и к о в , и с п о л ь з у ю щ и х JavaScript,
предоставляемая Netscape
http://developer.netscape.com/tech/javascript/
Microsoft JScript
http://msdn.microsoft.com/scripting/
И н ф о р м а ц и я , п р е д о с т а в л я е м а я Mozilla Organization
http://www.mozilla.org/js/
D o c u m e n t Object M o d e l
http://www.w3.org/DOM/
2 4 . 1 . Динамическая генерация
НТМ L-документов
Код JavaScript-сценария содержится в элементе SCRIPT и выполняется в процессе
загрузки Web-страницы. Выходные данные, генерируемые сценарием, включаются в
том месте документа, где находится элемент SCRIPT. Формат JavaScript-сценария
приведен в листинге 24.1. Если какие-то из особенностей синтаксиса JavaScript вам
непонятны, не стоит беспокоиться, мы рассмотрим их в конце данного раздела.
<BODY>
HTML-текст
HTML-текст
</BODY>
Листинг 2 4 . 2 . F i r s t S c r i p t . h t m l
</BODY>
</HTML>
Ш
First JavaScript Page
HeUo World Wide Web
Рис. 24.1. Горизонтальные линии и текст
между ними сгенерированы JavaScript-
^^^^p„. ^b:^6>^iiD^";-l 'jy;;^]|ycgguvjsag;^,.. сценарием
М е т о д и к а профессионалов
<SCRIPT TYPE="text/javascript">
<? —
function referringPage() {
if (docioment. ref errer. length = = 0 ) {
return("<I>none</I>");
} else {
return (dociiment. referrer) ;
}
}
document.writeln
("Document Info:\n" +
"<UL>\n" +
" <LIXB>URL: </B> " + document. location + "\n" +
" <LIXB>Modification Date:</B> " + "\n" +
document.lastModified + "\n" +
" <LIXB>Title:</B> " + docianent. title + "\n" +
" <LIXB>Ref erring page:</B> " + ref err ingPage () + "\n" +
"</UL>");
document.writeln
("Browser Info:" + "\n" +
"<UL>" + "\n" +
" <LIXB>Name:</B> " + n a v i g a t o r . appName + " \ n " +
" <LIx:B>Version:</B> " + navigator.appVersion + "\n" +
"</UL>");
// — >
</SCRIPT>
<HR>
</BODY>
</HTML>
1106 Глава 24. JavaScript...
• JDixi|
yniHi'iiiiiniiniJiHiiimiifffwiHi'nm
• URL: http://www.corewebprogramming.coin/JavaScnpt/ShowInfo.html
• Modification Date: Wednesday, April 11, 2001 17:19:10
• Title: Extracting Document Info with JavaScript
• Referring page: none
Browser Info:
• Name: Netscape
• Version: 4.7 [en] (Win98.1)
шш^
"^
Extracting Document Info with JavaScript
Document Info:
Browser Info:
d
Щ2 0опе Д | My Computer
<SCRIPT LANGUAGE="JavaScriptl.l">
<! —
languageVersion = "1.1";
// — >
</SCRIPT>
<SCRIPT LANGUAGE="JavaScriptl.4">
<! —
1108 Глава 24. JavaScript.
languageVersion = "1.4";
// — >
</SCRIPT>
<SCRIPT LANGUAGE="JavaScriptl.5">
<! —
languageVersion = "1.5";
// — >
</SCRIPT>
Выполняя этот пример, не используйте атрибут TYPE=" t e x t / j a v a s c r i p t " .
В большинстве броузеров наличие атрибута TYPE приводит к выполнению сценария
независимо от версии JavaScript. В Netscape 6 эта проблема не возникает.
Листинг 2 4 . 4 . D o n t C l i c k . html
function dontClick0 {
a l e r t ( " I t o l d you n o t t o c l i c k ! " ) ;
}
/ / —>
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<Hl>Simple JavaScript Button</Hl>
<FORM>
24.3. Синтаксис JavaScript 1109
<INPUT TYPE="BUTTON"
VALUE="Don't Click Me"
onClick="dontClick() ">
</FORM>
</BODY>
</HTML>
^»jjijU;p|MI|^juUt
t^nfflffimfmrfflf шшт
"D
Simple JavaScript Button
~ сьлаа^ш.
d
.C]l>one ;^Ы;>Ос*ч»««
javascnpt typein
Объявление функций
Для объявления функции используется ключевое слово f u n c t i o n . П р и этом не
указываются ни тип возвращаемого значения, ни типы параметров. П р и м е р ы функ
ций приведены ниже.
function square(х) {
return(х * х ) ;
}
function factorial(n) {
if (n <= 0) {
return(1);
} else {
return(n * factorial(n - 1));
}
}
function printHeading(message) {
document.writeln("<Hl>" + message + "</Hl>");
}
Функции могут присваиваться переменным, например:
: fun = Math.sin;
^rt("sin(pi/2)=" + fun(Math.PI/2));
Результаты выполнения данного фрагмента показаны на рис. 24.7.
Л JavaiSaipt Alert
stn(pi/2)-1
|ГГ7ЖГ111 1
Объекты и классы
Для тех, кто привык писать объектно-ориентированные программы на языке Java,
код на JavaScript покажется странным, в частности, может создаться впечатление, что
при написании JavaScript-программ объектный подход не используется. Некоторые
особенности JavaScript описаны ниже.
Листинг 2 4 . 5 . F o r i n . html
</SCRIPT>
</BODY>
</HTML>
:»'111Н11Н11М|||НМ]|'11^!1ЯШ1^1м14
1For/In Loops -^ i Ц
Ships
1 test shipl
1 1 Reld Value
Held Value
field 1 Reld One 1 |x |0
field2PieldTwo ;y 0
fields Reld ТЪгее 1 ;speed '1 1
1 jdirecbon '90 1
1^ d [ ^_^ d
Рис. 24.9. Выражение for/in позволяет Рис. 24.10. Использование конструк
перебирать свойства объекта в цикле тора— это лишь упрощенный способ
создания объекта и присвоения значе
ний свойств
1114 Глава 2 4 . JavaScript...
function degreesToRadians(degrees) {
return(degrees * Math.PI / 180.0);
}
function move() {
var angle = degreesToRadians(this.direction);
this.x = this.x + this.speed * Math.cos(angle);
this.у = this.у + this.speed * Math.sin(angle);
}
function Ship(x, y, speed, direction) {
this.x = x;
this.у = у;
this.speed = speed;
this.direction = direction;
this.move = move;
}
М е т о д и к а профессионалов
• ^
Ships
shipl (originally)
Field Value
X 0
У _ 0 _
speed 1
direcbon 90
fiinchon moveO { var angle = degreesToRadians
(tbs direction); this.x = this.x +this, speed * Math.cos
(angle); this у = this у + this.speed * Math. sin(angle);)
_J
^ Done '^ЩОщлЛт
Массивы
в JavaScript массивы используются почти так же, как и в языке Java. Ниже приведены
примеры применения конструктора A r r a y , который упрощает создание массивов.
v a r s q u a r e s = new A r r a y ( 5 ) ;
for(var i=0; i<squares.length; i++) {
vals[i] = i * i;
}
/ / Создание м а с с и в а з а один э т а п ,
v a r s q u a r e s = new A r r a y ( 0 , 1, 4, 9, 1 6 ) ;
v a r a r r a y l = new A r r a y C ' f e e " , " f i e " , " f o " , "fum") ;
/ / Создание м а с с и в а в " л и т е р а л ь н о м " в и д е ,
v a r а г г а у 2 = [ " f e e " , " f i e " , " f o " , "fum" ] ;
Следуя подобному подходу, вы не испытаете затруднений при работе с массивами.
На самом деле в JavaScript массивы представляются в виде объекта с нумерованными по
лями. Кроме того, вы можете пользоваться именованными полями, используя выраже
ния в формате объект, поле либо объект [''поле"]. Для доступа к нумерованным полям мо
жет применяться только выражение объект [ номер_поля]. Ниже приведен пример рабо
ты с массивом. Результаты выполнения этого примера показаны на рис. 24.12.
v a r a r r a y O b j = new O b j e c t O ;
arrayObj[0] = "Index zero";
arrayObj[10] = "Index t e n " ;
a r r a y O b j . f i e l d l = " F i e l d One";
a r r a y O b j [ " f i e l d 2 " ] = " F i e l d Two";
щшшшЕватт
ВЧ £ * li9» ^^^тянжШиси Н Ф
i ^ ^ 3 й 4^ A ^ rf a Ш ffl
Array/Object Duality
arrayObj
Field Value
jo b d e x zero
Index ten
.field 1 Field One
|field2 Field Two
Обратите также внимание, что в данном примере вместо двойных кавычек ис
пользуются одинарные. JavaScript поддерживает как двойные, так и одинарные ка
вычки, поэтому, помещая строку текста в одинарные кавычки, вы можете включать в
нее выражения в двойных кавычках.
1118 Глава 2 4 . JavaScript.
На з а м е т к у
Листинг 2 4 . 6 . s t r a w b e r r i e s , h t m l
<SCRIPT TYPE="text/javascript">
<! —
function image(url, width, height) {
r e t u r n ( ' < I M G SRC="' + u r l + " " +
' WIDTH=' + w i d t h +
' HEIGHT=' + h e i g h t + ' > ' ) ;
}
function strawberryl(width) {
return(image("Strawberryl.gif", width, Math.round(width*l.323))
}
function strawberry2(width) {
return(image("Strawberry2.gif", width, Math.round(width*!.155))'
}
/ / —>
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<HR>
<SCRIPT TYPE="text/javascript">
<! —
var imageWidth = window.innerWidth/4;
var fontSize = Math.min(7, Math.round(window.innerWidth/100));
}
document.writeln
('<TABLE>\n' +
<TR><TD>' + strawberryl(imageWidth) + '\n' +
<TH><FONT SIZE=' + fontSize + '>\n' +
"Doubtless God <I>could</I> have made\n' +
a better berry, but doubtless He\n' +
never did."</FONT>\n' +
<TD>' + strawberry2(imageWidth) + '\n' +
'</TABLE>');
// — >
</SCRIPT>
<HR>
2 4 . 4 . Использование JavaScript при создании Web-страниц 1119
</BODY>
</HTML>
>41тя?дп?г дэд
Ы
"Doubtless God
could hsi\e made
a better berry,
but doubtless He
never did."
Strawberries are my favonte garden crop; a fresh strawberry picked five minutes ago makes the dry and woody grocery
store variety seem like a totally different fruit My favonte vanebes are Surecrop and Cardinal
S ач4>я=
,A Ш ..?i(^ .Лк^.. Ш . л ^ , , .
Я'ТШдЦПР???
^^ ^ -^ 9 А ^ «а Jfll
"Doubtless
. ^ Goi could
'U^i> kave made
<SCRIPT TYPE="text/javascript">
<! —
function printRow(plugin) {
document.write
(" <TR><TD>" + plugin.name + "\n" +
" <TD>" + plugin.description + "\n" +
<TD>");
document.write(plugin[0].type);
24.4. Использование JavaScript при создании Web-страниц 1121
// ~->
</SCRIPT>
</HEAD>
<BODY>
<Hl>Plug-ins Supported</Hl>
<SCRIPT TYPE="text/javascript">
<! —
if (navigator.appName == "Netscape") {
document.writeln
("<TABLE BORDER=l>\n" +
" <TR><TH>Plug-in\n" +
" <TH>Description\n" +
<TH>MIME Types Supported");
for(var i=0; Knavigator .plugins . length; i-H-b)
printRow(navigator.plugins[i]);
document.writeln
("\n</TABLE>");
}
// — >
</SCRIPT>
</BODY>
</HTML>
|[gJD|)CJ|
Я
Plugins Supported
Plugin Description MIME Types Supported
'Headspace Beatnik Headspace Player Stub for audio/x-rmf
Player Stub VI.0.0 1 Netsc^e Conimunicator laudio/rmf
|арр11са110пУх-1ф
iSmartDownload Plugin
:appEcation/idp
iappEcation/x-java-bean;version=l. 1.2
i^plicationyx-java-applet;version=l.l 2
Java Plug-in 1.3 for Netscape
iJava Plug-in 1.3 for ^application/x-java-bean;version=l 1 3
Navigator with JDK/JRE 1.3
iNetscape Navigator appIication/x-java-applet,version=l. 1 3
(DLL Helper)
apphcation/x-java-bean;version=l. 2
application/x-java-applet,version=l 2
iQiacken 99 for Windows IPA Plugin stub application/x-ipa-plugin
d
^Оосяяа^йЛ: Done
function changelmage() {
document.images[0].src = "images/new-image.gif";
.}
Кнопка с изображением
Возможность динамически изменять изображение на Web-странице применяется
при создании кнопок. Функция c l i c k B u t t o n , код которой приведен ниже, временно
отображает новое изображение, а затем, по прошествии 1/10 секунды, снова восста
навливает старую картинку. Это осуществляется с помощью функций s e t Image и
s e t T i m e o u t . Код функции s e t l m a g e приведен перед кодом c l i c k B u t t o n , а
24.5. Использование JavaScript для изменения... 1123
<A HREF="location2.html"
onClick="clickButton('Button2',
* images/Button2-Down.gif')">
<IMG SRC="images/Button2-Up.gif" NAME="Button2"
WIDTH=150 HEIGHT=25></A>
В листинге 24.8 показана вся процедура создания кнопки. Если вам надо работать с
большим количеством изображений, вы можете упростить процедуру, следуя опреде
ленному принципу именования изображений. Пример такого подхода будет приведен
в следующем разделе.
Листинг 2 4 . 9 . HxghPeaksNavBar.html
<SCRIPT TYPE="text/javascript">
<l —
function regularlmageFile(imageName) {
r e t u r n ( " i m a g e s / " + imageName + " . g i f " ) ;
}
f u n c t i o n negativelmageFile(imageName) {
r e t u r n ( " i m a g e s / " + imageName + " - N e g a t i v e . g i f " ) ;
}
f u n c t i o n cachelmages(index) {
r e g u l a r l m a g e O b j e c t s [ i n d e x ] = new Image(150, 2 5 ) ;
regularlmageObjects[index].src =
regularlmageFile(imageNames[index]);
n e g a t i v e l m a g e O b j e c t s [ i n d e x ] = new Image(150, 2 5 ) ;
negativelmageObjects[index].src =
negativelmageFile(imageNames[index]);
}
1126 Глава 24. JavaScript...
function highlight(imageName) {
document.images[imageName].src =
negativelmageFile(imageName);
function unHighlight(imageName) {
document.images[imageName].src = regularlmageFile(imageName);
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<NOFRAMES>
If you can't hack frames, how do you expect
to handle the Himalayas? Get a real browser.
</NOFRAMES>
</FRAMESET>
</HTML>
Работа CO слоями
в Netscape 4.0 был реализован механизм слоев. Слои— это области HTML-до
кумента, которые могут перекрываться и отображаться один поверх другого. Под
робно о слоях см. в разделе 5.12. Для работы со слоями в JavaScript 1.2 можно исполь
зовать массив d o c u m e n t . l a y e r s , каждый элемент которого представляет собой объ
ект L a y e r . Свойства данного объекта соответствуют атрибутам элемента LAYER. Дос
туп к именованному слою осуществляется посредством выражения d o c u m e n t .
l a y e r s [ " и м я с л о я " ] ; такой подход предпочтительнее использования числового
индекса или выражения d o c u m e n t . и м я _ с л о я . П р и этом не имеет значения, каким
образом слои определяются в HTML: посредством элемента LAYER, с помощью эле
мента ILAYER либо средствами листов стилей.
В листинге 24.12 представлен код примера, в котором используются слои. Перво
начально два слоя, используемых для аннотации изображения, скрыты (рис. 24.17).
После щелчка на одной из кнопок первый слой становится видимым, отображается в
верхнем левом углу изображения, затем перемещается в требуемую точку (рис. 24.18).
После щелчка на второй кнопке первый слой перестает быть видимым, а вместо него
выводится изображение второго слоя, которое также перемещается в конечную точ
ку. Свойства и методы объекта L a y e r описаны в разделе 25.15; в данном случае нас
интересуют свойства v i s i b i l i t y (значение show или h i d d e n ) и радеХ (абсолютная
позиция в окне). Из методов в рассматриваемом примере используются m o v e T o -
A b s o l u t e (перемещение слоя в абсолютную позицию) и moveBy (смещение слоя от
носительно его предыдущей позиции).
24.5. Использование JavaScript для изменения. 1129
NEPAL
jueniu
swrrzERum
High Peaks Travel Inc.
Tired of the same old vacations in Cleveland? Tour
the high peaks with High Peaks Travel!
• Tibet
• Nepal
• Austna
• Switzerland
Sign up todayl
|^1;;|ьГ^ ^ W ^ B B ^ . g P Ш. ,v^„
function hideCamps() {
// Модель документа Netscape 4.
document.layers["baseCamp"].visibility = "hidden";
document.layers["highCamp"].visibility = "hidden";
// Или document.baseCamp.visibility = "hidden";
}
function moveBaseCamp() {
baseCamp.moveBy(1, 3) ;
if (baseCamp.pageX < 130) {
setTimeout("moveBaseCamp{)", 10);
}
function showBaseCamp() {
hideCamps();
baseCamp = document.layers["baseCamp"];
baseCamp.moveToAbsolute(0, 20);
baseCamp.visibility = "show";
moveBaseCamp();
}
function moveHighCamp() {
highCamp.moveBy(2, 1 ) ;
if (highCamp.pageX < 110) {
setTimeout("moveHighCamp()", 10);
}
}
function showHighCamp() {
hideCamps();
highCamp = document.layers["highCamp"];
highCamp.moveToAbsolute(0, 65);
highCamp.visibility = "show";
moveHighCamp();
}
// — >
</SCRIPT>
</HEAD>
<BODY>
<FORM>
<INPUT TYPE="Button" VALUE="Show Base Camp"
onClick="showBaseCamp()">
<INPUT TYPE="Button" VALUE="Show High Camp"
onClick="showHighCamp()">
<INPUT TYPE="Button" VALUE="Hide Camps"
onClick="hideCamps()">
</FORM>
</BODY>
</HTML>
var f i r s t F o r m = document.forms[0];
/ / Предполагается <FORM NAME="orders" , . . >
var orderForm = d o c u m e n t . f o r m s [ " o r d e r s " ] ;
/ / Предполагается <FORM NA]yiE="register" . . . >
var r e g i s t r a t i o n F o r m = d o c u m e n t . r e g i s t e r ;
Объект Form содержит свойство elements, которое обеспечивает доступ к масси
ву объектов Element. Извлекать элементы из массива можно по номеру или по имени,
кроме того, можно использовать для этой цели имя свойства.
var f i r s t E l e m e n t = f i r s t F o r m . e l e m e n t s [ 0 ] ;
/ / Предполагается <INPUT . . . NAME="quantity">
var q u a n t i t y F i e l d = o r d e r F o r m . e l e m e n t s [ " q u a n t i t y " ] ;
/ / Предполагается <INPUT . . . NAME="submitSchedule">
var submitButton = r e g i s t e r . s u b m i t S c h e d u l e ;
BHMBHMHMMMHMHHDSSl
Ш ^
\уг/Ш/гг/А
, Show 8as« Camp |-р#|Ь1?'ЙдЬСз1тр | HHeC^mps |
J
Ш¥ШШ^ ;Docw»*«tDom
'' - "-^^''feaaBtJu^Lxa-^^^,-' 4
Рис. 24.17. После того как страница загружается в Netscape 4.7, оба слоя скрыты
24.6. Использование JavaScript для проверки HTML-форм 1133
:4<:'^^UitIlS'^Tl'^Z^nj
Camps on К-3
The High Peaks Tours trip to the
summit;
« Й : 1 И В ^ 1 1 ШЩЙШШ^ т» ошт:
Ш^Ш^Ё
Рис. 24.18. После щелчка на кнопке Show Base Camp первый слой отображается
в левом верхнем углу страницы, а затем перемещается в конечную позицию
Листинг 2 4 . 1 3 . C h e e k T e x t . h t m l
<SCRIPT TYPE="text/javascript">
<! —
function describeLanguage() {
s t a t u s = " E n t e r an i m p o r t a n t Web l a n g u a g e " ;
}
function checkLanguage() {
var field = document.langForm.langField;
// Или document.forms["langForm"].elements["langField"]
var lang = field.value;
var prefix = lang.substring(0, 4).toUpperCase();
if (prefix != "JAVA") {
alert("Sorry, '" + lang + "* is not valid.\n" +
"Please try again.");
field.value = ""; // Erase old value
field.focus 0 ; // Give keyboard focus
}
}
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<Hl>On-Line Training</Hl>
<FORM ACTION="cgi-bin/registerLanguage" NAME="langForm">
To see an introduction to any of our on-line training
24.6. Использование JavaScript для проверки HTML-форм 113
c o u r s e s , p l e a s e e n t e r t h e name of an i m p o r t a n t Web
programming l a n g u a g e below.
<P>
<B>Language:</B>
<INPUT TYPE="TEXT" NAME="langField"
onFocus="describeLanguage()"
onBlur="clearStatus() "
onChange="checkLanguage()">
<P>
<INPUT TYPE="SUBMIT" VALUE="Show It To Me">
</FORM>
</BODY>
</HTML>
М'||»||П1Н1|||||«ИШ
Jji
i ^ ^ ^ ^ ^ a t a rfa
On-Line Training
To see an introduction to any of our on-line training courses, please
enter the name of an important Web programming language below.
Language: | v i s u a l B a s i c
л'Show IITo Me J
BBS
ei^i' ^EO«»t«ft«P»,;J,^j|^,
ветственно целое число и число с плавающей точкой. В JavaScript, если начало стро
ки, предаваемой в качестве параметра, не является целым числом, функция возвра
щает значение NaN (Not а Number— не число), которое распознается встроенной
функцией isNaN (опреатор == применять нельзя, поскольку выражение NaN==NaN
возвращает значение f a l s e ) . Как было сказано в разделе 24.1, JavaScript не поддер
живает свойство, которое сообщало бы текущую версию языка.
Код, представленный в листинге 24.14, иллюстрирует проверку на наличие число
вых значений. Результаты выполнения данного кода в броузере Internet Explorer 5.0
показаны на рис. 24.20.
Листинг 2 4 . 1 4 . Numbers, h t m l
<SCRIPT TYPE="text/javascript">
function isint(numString) {
/ / Функция p a r s e i n t в о з в р а щ а е т либо ц е л о е ч и с л о , либо NaN
return(!isNaN(parseint(numString)));
}
/ / —>
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<SCRIPT TYPE="text/javascript">
<! —
function testint(numString) {
return("<TR><TD>" + numString +
"<TD>" + p a r s e i n t ( n u m S t r i n g ) +
"<TD>" + i s I n t ( n u m S t r i n g ) + " X n " ) ;
}
document.writeln
( " < H l > T e s t i n g f o r Numbers i n J a v a S c r i p t 1 . 2 + < / H l > \ n " +
"<TABLE B0RDER=5 CELLSPACING=5>\n" +
"<TR><TH>Input<TH>Parsed Value<TH>Legal I n t e g e r ? \ n " +
testlntC'O") +
testint("10") +
testint("-10") +
testint("FF") +
testint("#FF") +
testint("123abc") +
testint("abcl23") +
"</TABLE>");
/ / —>
24.6. Использование JavaScript для проверки HTML-форм 1137
</SCRIPT>
</BODY>
</HTML>
ii»!ll4!i4H.i.lH
le £ЕЙ )£*M Favorte»
BOS
lock йф
El
Листинг 24.15. CheckSeveral. html
<SCRIPT TYPE="text/javascript">
<! —
// Проверки:
// 1) В поле Age задано целое число.
/ / 2 ) В поле Rank введено нечисловое значение.
// 3) Значение в поле Rank присутствует.
// 4) В поле Serial number задано целое число.
// Если хотя бы одна проверка дает отрицательный результат,
// данные на сервер не передаются.
function checkRegistration() {
var ageField = document.registerForm.ageField;
if (!isInt(ageField.value)) {
alert("Age must be an integer.");
return(false);
}
var rankField = document.registerForm.rankField;
if (isInt(rankField.value)) {
alert("Use rank name, not rank number.");
return(false);
}
if (rankField.value == "") {
alert("Missing rank.");
return(false);
}
var serialField = document.registerForm.serialField;
if (!isInt(serialField.value)) {
24.6. Использование JavaScript для проверки HTML-форм 1139
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<Hl>Camp Registration</Hl>
<FORM ACTION="cgi-bin/register"
NAME="registerForm"
onSubmit="return(checkRegistration())">
Age: <INPUT TYPE="TEXT" NAME="ageField"
onFocus="promptAge()"
onBlur="clearStatus()">
<BR>
Rank: <INPUT TYPE="TEXT" NAME="rankField"
onFocus="promptRank()"
onBlur="clearStatus()">
<BR>
Serial Number: <INPUT TYPE="TEXT" NAME="serialField"
onFocus="promptSerial()"
onBlur="clearStatus()">
<P>
<INPUT TYPE="SUBMIT" VALUE="Submit Registration">
</FORM>
</BODY>
</HTML>
Camp Registration
Agcijie"
Rank:}Geek
Senal Number |#FFAA|
!^^pf ~Bi^m(>iiM:^j^^.j^:^m.^^<j
Внимание!
1^ vBrffl№iHMii»jiBmiffl3»r Ш ^ шшштшршшшшшмщ
~}
Widgets "R" Us Widgets "R" Us
First Name: jLoreen 1 First Name: JLoreen
Last Name: iDeWitt 1 Last Name: JDeWitt
Account Number |1100-BC 1 Account Number |1100-BC
Widget Name jAcme-Ultra-Widget 1 Widget Name' j
SubmrtOrdet 1 l4eg»9tasrA<xooot j Submit Ofdef j
d
,€3Done [ЩЩ^ёт^а' '{gjOone I ;Д(%Ь(Ш]М"
Рис. 24.23. Эта страница предназ Рис. 24.24. Даже если пользователь
начена для передачи заказа. При пе Loreen завершит работу с броузе
редаче данных на сервер или после ром, а затем повторно обратится к
щелчка на кнопке Register Account Web-странице, некоторые поля фор
имя и номер счета сохраняются мы будут автоматически заполнены
1144 Глава 24. JavaScript.
В объектной модели HTML для каждого фрейма в окне создается отдельное свой
ство, поэтому тот же результат будет получен с помощью следующего выражения:
someFrame.frames.frameName.location = "url";
Затем эту функцию надо связать с кнопкой, используя для этого атрибут o n C l i c k :
Листинг 2 4 . 1 7 . ShowURL.html
</HTML>
<SCRIPT TYPE="text/javascript">
<! —
function showURL() {
var url = document .urlForm.urlField. valued-
parent .displayFrame. location = url;
// Или parent.frames["displayFrame"]•location = url;
}
function preloadUrlO {
if (navigator.appName == "Netscape") {
document.urlForm.urlField.value =
"http://home.netscape.com/";
} else {
document.urlForm.urlField.value =
"http://www.microsoft.com/";
}
}
// — >
</SCRIPT>
</HEAD>
1146 Глава 24. JavaScript...
<CENTER>
<FORM N A M E = " u r l F o r m " >
URL: <INPUT TYPE="TEXT" N A M E = " u r l F i e l d " SIZE=35>
<INPUT TYPE="BUTTON" VALUE="Show URL"
onClick="showURL()">
</FORM>
</CENTER>
</BODY>
</HTML>
</BODY>
</HTML>
HQQj^l
iCTBirewRrai—
s.^^a^^ amm
'4Eh- £'^# ^*
)imt go ^«мптк^ог \Ыр
ш\
Choose a URL
XJRL: | h t t p : / / h o m e . n e t s c a p e . com/
—r- J
1 Enter a URL in the textfleld above. Press "Show URL" to display it in this
j frame.
п ^ ^' -a Л A ^ ^ rf's «
Choose a URL
XJRL" [http://hoine.netscape.com/ SH^wURl I
Рис. 24.26. После щелчка на кнопке Show URL в нижнем фрейме отображается
документ, URL которого задан в поле редактирования, находящемся в верхнем
фрейме. (Приведено с разрешения Netscape Communications Corp.)
Листинг24.20. C a l l J a v a . h t m l
<SCRIPT TYPE="text/javascript">
document.writeln
("This browser uses a virtual machine from " +
Java.lang.System.getProperty("Java.vendor") + " . " ) ;
var pt = new Java.awt.Point(3, 5 ) ;
pt.translate(7, 5 ) ;
document.writeln("<P>");
document.writeln("Translating (3,5) by (7,5) yields (" +
pt.X + "," + pt.у + " ) . " ) ;
// — >
</SCRIPT>
</BODY>
</HTML>
Calling Java
This browser uses a virtual machine from Netscape Communications Corporation.
Листинг 2 4 . 2 1 . Wonder-Widget. h t m l
<SCRIPT TYPE="text/javascript">
<! —
function c o n t a i n s ( s t r i n g , substring) {
return(string.indexOf(substring) != - 1 ) ;
}
2 4 . 9 . Обращение к Java из JavaScript 1151
function showResume() {
if (contains(document.gethost.getHost(),
"widgets-r-us.com")) {
location = "ResumeLoyal.html";
} else {
location = "ResumeReal.html";
}
return(false) ;
}
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<Hl>WonderWidget</Hl>
Description:
<UL>
<LI>Name: Wonder Widget
<LI>Serial Number: 1544X
<LI>Cost: $7.95 (plus 22.50 shipping and handling)
<LI>Designer:
<A HREF="ResumeLoyal.html" onClick="return(showResume())">
J. Random Hacker</A>
</BODY>
</HTML>
Листинг 24.22.GetHost.java
^ W o n d e t W k ^ l ^ • Netscape
Efc £cft yiew So jQocnmunicator й ф
^^ y'^ J г-л ^ !jvi ,.> f^' ti i; 1Л;
WonderWidget
Description:
• Name: WonderWidget
• Senal Number: 1544X
• Cost $7 95 (plus 22.50 shipping and handling)
• Designer J Fvandom Hacker Рис. 24.28. Данная страница
содержит аплет, однако он не
' ''--i.^ Dcxumertl, bont ;^ i^ iM -г отображается на экране
J. Random Hacker
Гш looking for а job!
For the last five years, I've been undeфald and underappreciated by
Widgets R Us, Inc. Now^ I'm ready to take my immense talents' Риа. 24.30. Если, судя по
elsewhere. Who will open the bidding? доменному имени клиента, автору
Web-страницы "ничего не грозит",
:a^ ~4^>- ?\ppiet gethosi itopped ^ J - ' ZM \ ^ отображаются другие сведения
<SCRIPT TYPE="text/javascript">
function startCircles() {
for (var i=0; i<docuinent. applets . length; i++) {
document.applets[i].startCircles() ;
}
}
function stopCircles() {
for (var i=0; i<docuinent. applets . length; i++) {
document.applets[i].stopCircles();
}
}
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#C0C0C0">
<Hl>Mold Propagation Simulation</Hl>
<FORM>
<INPUT TYPE="BUTTON" VALUE="Start Simulations"
onClick="startCircles ()">
<INPUT TYPE="BUTTON" VALUE="Stop Simulations"
onClick="stopCircles ()">
</FORM>
</BODY>
</HTML>
24.9. Обращение к Java из JavaScript 1155
^ ^ И i^BS
| Я ^ ^ 1
!Ш
liiP
JfciM
k^J^yM'MW'M^'en Ш li
МшШ
llff?:]
i-liiitiliiiiee^
i#ЩriiШ:-€»lfilшs*з шт^тшш Шшт™Ш;
Рис. 24.31. Сразу после загрузки Web-страницы "имитаторы"
не работают
|ШШх||
{штшшшштшвташшштштт
р'Ш|ЩШШШШ*<ШШШШ«И^ W#'-JH
:;^oid:^^lpiag^^
;^jpi*iielifiiiiii
|:„, |;.viiiii;iiiillil:lft
и i'дГ** -^'I ' ''iiii eiisi
• • •
1 ^
:Ш!Ы
Рис. 24.32. Все три имитатора управляются с помощью
одной кнопки. Включение дополнительных аплетов не потре
бует изменения кода Java или JavaScript
2 4 . 1 0 . Доступ к средствам JavaScript из Java 1157
П о л у ч е н и е и и н с т а л л я ц и я класса J S O b j e c t
Класс J S O b j e c t входит в поставку Netscape 4 в составе JAll-файла с именем
j a v a 4 0 . Расположение этого файла может быть различным для разных операци
о н н ы х систем. В Windows 98 он находится в каталоге
NetscapeInstallPath\Program\Java\Classes\
Здесь N e t s c a p e I n s t a l l P a t h означает главный каталог, в котором инсталлиро
ван Netscape. Если файл в этом каталоге отсутствует, его можно найти, вызвав
пункт Find (Найти) главного меню системы.
В системе UNIX этот файл обычно находится в том каталоге, в котором инсталли
рован броузер Netscape. П р и необходимости его можно найти с помощью следую
щих команд:
Unix> cd / u s r / l o c a l
Unix> f i n d . -name j a v a 4 0 - p r i n t
Получив требуемый файл, его надо указать в переменной окружения CLASS PATH;
компилятор Java способен находить требуемые классы в JAR-файле. Перед запуском
a p p l e t v i e w e r переменную окружения CLASSPATH надо отключить, в противном
случае программа будет выполняться некорректно. Поскольку и Netscape, и Internet
Explorer предоставляют классам, указанным в CLASSPATH, специальные привилегии,
желательно отключить CLASSPATH перед запуском любого броузера. П р и желании
вы можете распаковать JAR-файл, вызвав в командной строке команду j a r x f
j a v a 4 0 . j a r , извлечь файл J S O b j e c t . c l a s s и установить его отдельно. Вам обяза
тельно придется сделать это, если в системе, в которой вы работаете, не установлен
броузер Netscape. Возможно, вам потребуется включить класс J S O b j e c t в состав ва
шего аплета, так как на клиентской машине может быть установлен другой броузер.
1158 Глава 24. JavaScript.
Р а з р е ш е н и е д о с т у п а к Web-странице
Ч т о б ы аплет мог обращаться к Web-странице, в которой он расположен, автор до
кумента должен явным образом р а з р е ш и т ь аплету выполнять подобные действия.
Это предотвращает случайную модификацию документа. Для предоставления прав
доступа используется атрибут MAY SCRIPT элемента APPLET. Н а п р и м е р :
<APPLET CODE=... WIDTH=... HEIGHT=... MAYSCRIPT>
</APPLET>
Листинг 2 4 . 2 7 . MatchColor. j a v a
import J a v a . a p p l e t . A p p l e t ;
import j a v a . a w t . * ;
import netscape.javascript.JSObject;
<BODY BGCOLOR="RED">
<Hl>MatchColor</Hl>
<APPLET CODE="MatchColor.class" WIDTH=300 HEIGHT=300 MAYSCRIPT>
</APPLET>
</BODY>
</HTML>
Листинг 2 4 . 2 9 . E v e r e s t . html
Листинг 24.30.Everest.java
import Java.applet.Applet;
import java.awt.*;
import Java.awt.event.^;
import netscape.j avascript.JSObject;
tniglyj
тзшшшшшшш
^•&1 £<£t ^«m Qp Qemttjeioeiat ]ЬИ>
Design Your
Trek!
"I i. jee a bstaig of the treks ttat loterest
you, tract tbe dusked ahitude (t^ to
29,000 feet) аЫ liie т а я т ш п cost you
йаск your budget can afford. Tlxea
dwose "Show Treks" belofw. Well
show 8 list of аД pk&ned УИф Р е а Ь
Travel expedmons that arc under i b ^
price and reach the desired altitude or
hi^cr'
Desired AJtthiid^
Mkdmnin Cost:
import j ava.awt.*;
maxValue^
initialValue,
app) ;
add(slider, BorderLayout.CENTER);
}
}
Листинг 24.32.CostSlider.java
Листинг 24.33.Slider.java
import j ava.awt.*;
import Java.awt.event.*;
/** Класс, содержащий горизонтальную полосу прокрутки
* (компонент Scrollbar) и поле редактирования (компонент
* TextField) справа от полосы прокрутки. В поле
* редактирования отображается текущее значение линейного
* регулятора, кроме того, если задано setEditable(true),
* оно может быть непосредственно использовано для изменения
* значения.
Ч
public class Slider extends Panel implements ActionListener,
AdjustmentListener {
private Scrollbar scrollbar;
private TextField textfield;
private ScrollbarPanel scrollbarPanel;
private int preferredWidth = 250;
/** Построение линейного регулятора с заданными минимальным,
* максимальным и начальным значениями. Размер ползунка
* устанавливается равным 1/10 от размера полосы.
V
24.10. Доступ к средствам JavaScript из Java 1165
setTextFieldValue();
doAction(scrollbar.getValue());
}
/** Возвращается объект Scrollbar, входящий в состав Slider. */
import j a v a . a w t . * ;
/** Объект Panel с изменяемыми верхней и нижней границами.
V
public class ScrollbarPanel extends Panel {
private Insets insets;
p u b l i c static J S O b j e c t g e t W i n d o w ( A p p l e t applet)
Данный статический метод позволяет получить JavaScript-объект Window, соот
ветствующий окну, содержащему аплет.
public void r e m o v e M e m b e r ( S t r i n g p r o p e r t y N a m e )
Метод removeMember удаляет указанное свойство.
24.11. Резюме
Прочитав данную главу, вы получили общее представление о JavaScript и познако
мились с некоторыми примерами применения данного языка. Часто JavaScript-сцена-
р и и применяются для р е ш е н и я следующих задач.
В ЭТОЙ главе...
2 5 . 1 . Объект Array
В первой версии JavaScript массивы реализовывались как объекты с множествен
ными свойствами. Позже в JavaScript 1.1 для поддержки массивов был введен отдель
ный объект A r r a y .
Конструкторы
n e w АггауО
Д а н н ы й конструктор создает новый массив нулевой длины. П р и включении ново
го элемента с указанием индекса длина массива изменяется. Н а п р и м е р :
v a r а = new A r r a y ( ) ; / / а.length = О
а[12] = "foo"; / / а . l e n g t h = 13
n e w Array(length)
Рассматриваемый конструктор создает массив указанной длины. Элементы масси
ва идентифицируются с помощью индекса, лежащего в пределах от О до l e n g t h - 1 .
Сразу после создания массива все элементы инициализируются значениями n u l l .
1174 Глава 25. Краткое руководство по JavaScript
[entryO, entry 1 , . . . , e n t r y N ]
Данный конструктор представлен в "литеральном" виде. Н а п р и м е р , следующие
два конструктора дают одинаковые результаты:
v a r a l = new A r r a y C ' f o o " , " b a r " , " b a z " ) ;
v a r a2 = [ " f o o " , " b a r " , " b a z " ] ;
Свойства
length
Данное свойство определяет число элементов в массиве. Ч и с л о элементов на еди
ницу превышает значение последнего индекса. Свойство l e n g t h допускает как
чтение, так и запись. Если вы присвоите данному свойству новое значение меньше
текущего, последние элементы массива будут утеряны. Если присваиваемое значе
ние превышает текущее, в состав массива будут включены новые элементы, кото
рые получат специальное значение u n d e f i n e d (при сравнении этого значения с
n u l l с помощью оператора == возвращается t r u e ) .
Методы
concat(secondArray)
Данный метод возвращает новый массив, созданный путем конкатенации текуще
го массива и массива, указанного в качестве параметра ( s e c o n d A r r a y ) .
join()
j o i n ( d e l i m i t e r String)
Первый из указанных методов возвращает строку, которая получена путем преобразо
вания всех элементов массива в строковые значения с последующей их конкатенацией.
Второй метод отличается от первого тем, что в результирующей строке между элемен
тами массива помещается строка, определяемая параметром d e l i m i t e r S t r i n g (перед
первым элементом и после последнего эта строка не включается).
reverse()
Данный метод перестраивает элементы текущего массива в обратном порядке.
Н о в ы й массив не создается.
2 5 . 1 . Объект Array 1175
slice(startlndex)
slice(startlndex, endlndex)
Метод s l i c e возвращает новый массив, состоящий из элементов с индексами от
s t a r t l n d e x до endlndex, извлеченных из текущего массива. Элемент s t a r t l n d e x
входит в состав нового массива, а элемент endlndex не входит в новый массив.
sort()
sort(comparisonFunction)
Первый из указанных методов (т. е. метод s o r t без параметров) размещает эле
менты массива в алфавитном порядке, при этом новый массив не создается. Для
второго метода порядок размещения элементов определяется функцией сравне
ния ( c o m p a r i s o n F u n c t i o n ) . При вызове этой функции ей в качестве параметров
передаются два элемента массива. В результате выполнения функции возвращает
ся отрицательное значение, если первый параметр "меньше" второго, нулевое
значение, если параметры "равны", и положительное значение, если первый па
раметр "больше" второго. Ниже приведена функция сравнения, которая получает
при вызове два объекта Саг и сравнивает свойства maxSpeed этих объектов.
function slower(carl, саг2) {
return(carl.maxSpeed - car2.maxSpeed);
}
В листинге 25.1 данный подход применяется при создании массива объектов Саг и
последующей сортировке массива в соответствии с максимальной скоростью
(свойство maxSpeed). Результаты выполнения сценария показаны на рис. 25.1.
Листинг25.1. Sort.html
function carStringO {
return("Car{" + this.maxSpeed + " } " ) ;
}
function Car(maxSpeed) {
this.maxSpeed = maxSpeed;
this.toString = carString;
}
function slower(carl, car2) {
return(carl.maxSpeed - car2.maxSpeed);
}
var cars = new Array(new Car(10), new Car(20),
new Car(30), new Car(25),
new Car(15), new Car(5));
// ~ >
</SCRIPT>
<TABLE>
<TR><TD>
<SCRIPT TYPE="text/javascript">
<! —
makeObjectTable("Original Car Array", cars);
// — >
</SCRIPT>
<TD><PRE> </PRE>
<TD><SCRIPT TYPE="text/javascript">
<! —
cars.sort(slower) ;
makeObjectTable("Sorted Array (slow to fast)", cars)
// — >
</SCRIPT>
</TABLE>
</BODY>
</HTML>
Ешгаш
file £А' y«w Favorite» lixjl» Hefc ""
"H
Sorting
Original Car Array Sorted Arra
Обработчики событий
Обработчики событий отсутствуют.
Свойства
form
Данное свойство, предназначенное только для чтения, содержит объект Form, со
ответствующий ф о р м е , в состав которой входит данная кнопка.
name
Если при создании кнопки использовался атрибут NAME, значение этого атрибута
доступно с помощью свойства name. Это свойство предназначено только для чтения.
type
Для обычных объектов B u t t o n данное свойство имеет значение b u t t o n . Для кнопок
SUBMIT и RESET данное свойство содержит соответственно значение s u b m i t и r e
s e t . Объект E l e m e n t содержит свойство t y p e , которое может использоваться для
определения типа элемента. Свойство t y p e предназначено только для чтения.
value
Данное свойство предназначено как для чтения, так и для записи и определяет
надпись на кнопке. В случае кнопки SUBMIT значение этого свойства передается
на сервер вместе с именем элемента.
Методы
blurO
В результате выполнения данного метода кнопка теряет фокус ввода.
clickO
Данный метод выполняет те же действия, которые выполняются после щелчка
мышью на кнопке, но не генерирует событие o n C l i c k . Для кнопок SUBMIT и
RESET вместо c l i c k можно использовать методы s u b m i t и r e s e t формы.
1178 Глава 25. Краткое руководство по JavaScript
focus()
в результате выполнения метода f o c u s кнопка получает фокус ввода.
Обработчики событий
onblur()
Данный метод получает управление при потере кнопкой фокуса ввода. О б ы ч н о он
определяется посредством атрибута o n B l u r , как показано ниже.
<INPUT TYPE="BUTTON" . . .
onBlur="doSomeAction()">
onclickO
Метод o n c l i c k вызывается тогда, когда пользователь щелкает мышью на кнопке.
П р и вызове метода c l i c k метод o n c l i c k управление не получает. Обычно дан
ный метод определяется с помощью атрибута o n C l i c k , как показано ниже.
<INPUT TYPE="BUTTON" . . .
onClick="doSomeAction()">
Если данный метод возвращает значение f a l s e , дополнительные действия, свя
занные с активизацией кнопки (например, передача данных на сервер или сброс
ф о р м ы ) , подавляются. Например:
<INPUT TYPE="RESET" . . .
onClick="return(maybeReset())">
Так же ведут себя обработчики событий o n S u b m i t и o n R e s e t ф о р м ы , содержащей
кнопку.
ondblclickO
Метод o n d b l c l i c k вызывается после двойного щелчка мышью. После первого
щелчка вызывается метод o n c l i c k . Данный метод определяется с помощью атри
бута o n D b l C l i c k ; он не поддерживается Macintosh и Netscape 6.
onfocusO
Метод on f o c u s вызывается тогда, когда кнопка получает фокус ввода. Для опре
деления данного обработчика используется атрибут o n F o c u s .
Свойства
checked
Данное свойство, предназначенное как для чтения, так и для записи, содержит ло
гическое значение, которое определяет, установлен ли в данный момент флажок
опции.
defaultChecked
Свойство d e f a u l t C h e c k e d содержит логическое значение, определяющее, дол
жен ли флажок опции быть изначально установлен. Значение этого свойства зада
ется посредством атрибута CHECKED и предназначено только для чтения.
form
Данное свойство, предназначенное только для чтения, содержит объект Form, в
состав которого входит флажок опции.
type
Это свойство содержит последовательность символов " c h e c k b o x " . Поскольку
свойство t y p e имеют все объекты E l e m e n t , оно может быть использовано для
идентификации типа объекта, содержащегося в массиве f o r m , e l e m e n t s . Свойст
во t y p e предназначено только для чтения.
value
Данное свойство, предназначенное как для чтения, так и для записи, содержит
значение элемента, которое вместе с именем элемента передается программе на
стороне сервера в случае, если флажок опции установлен.
Методы
blurO
В результате выполнения этого метода флажок опции теряет фокус ввода.
clickO
Данный метод выполняется те же действия, которые выполняются после щелчка
мышью на элементе, но не генерирует событие o n C l i c k .
focus()
в результате выполнения метода f o c u s элемент получает фокус ввода.
1180 Глава 25. Краткое руководство по JavaScript
Обработчики событий
onblur()
Данный метод получает управление при потере флажком опции фокуса ввода.
О б ы ч н о он определяется посредством атрибута o n B l u r , как показано ниже.
<INPUT TYPE="CHECKBOX" . . .
onBlur="doSomeAction()">
onclickO
Метод o n c l i c k вызывается тогда, когда пользователь щелкает мышью на элемен
те. П р и вызове метода c l i c k метод o n c l i c k управление не получает. Обычно
данный обработчик определяется с помощью атрибута o n C l i c k .
onfocusO
Метод o n f OCUS вызывается тогда, когда флажок опции получает фокус ввода. Для
определения данного метода обычно используется атрибут on F o c u s .
Конструкторы
n e w Date()
Данный конструктор создает объект D a t e , соответствующий текущему времени.
n e w Date(year, m o n t h , day)
Этот конструктор создает объект D a t e , соответствующий началу указанных суток.
new Date(millisecondsSinceEpoch)
Данный конструктор создает объект D a t e , соответствующий указанному числу
миллисекунд с начала эпохи, т.е. с полуночи по гринвичскому времени (GMT) пер
вого января 1970 г.
25.4. Объект Date 1181
Свойства
Свойства отсутствуют.
Методы
Заметьте, что описанные ниже p a r s e D a t e и UTC на самом деле не являются мето
дами объекта D a t e , а работают как статические методы "класса" D a t e (т.е. конструк
тора). Для их вызова надо использовать соответственно выражения D a t e . p a r s e D a t e
и Date.UTC. Другие методы вызываются с помощью выражения s o m e D a t e O b j e c t .
m e t h o d ( a r g s ) , где s o m e D a t e O b j e c t — объект D a t e , m e t h o d — имя метода, a a r g s —
параметры.
getDateO
setDate(dayOfMonth)
Данные методы предназначены для получения и установки информации о дне ме
сяца. День месяца определяется целым числом в интервале от 1 до 31.
getDayO
Метод g e t Day возвращает день недели. День недели определяется числовым зна
чением; О соответствует воскресенью, а 6 — субботе.
getHoursO
setHours(hours)
Указанные методы позволяют получить и задать число часов дня. Число часов за
дается как целочисленное значение в интервале от О до 23.
getMinutesO
setMinutes(minutes)
Метод g e t M i n u t e s возвращает число минут часа, информация о котором получе
на с помощью метода g e t H o u r s . Метод s e t M i n u t e s позволяет задать число ми
нут. И н ф о р м а ц и я о минутах представляется в виде целого числа в интервале от О
до 59.
getMonthO
setMonth(monthlndex)
Данные методы позволяют получить и задать значение месяца. Месяц указывается
как число в диапазоне от О (январь) до 11 (декабрь).
getSecondsO
setSeconds(seconds)
Эти методы позволяют получить и задать число секунд, прошедших с начала мин)а'ы,
возвращаемой методом g e t M i n u t e s . Число секунд лежит в интервале от О до 59.
1182 Глава 25. Краткое руководство по JavaScript
getTimeO
setTime(millisecondsSince£poch)
Метод g e t T i m e возвращает, а метод s e t T i m e устанавливает число миллисекунд,
прошедших с полуночи про гринвичскому времени (GMT) 1 января 1970 г.
getTimezoneOffsetO
Данный метод возвращает разницу в минутах между GMT и локальным временем.
getFuUYearO
setFullYear(year)
Первый метод, g e t F u l l Y e a r , возвращает год, содержащийся в объекте D a t e , как
целое число, содержащее четыре знака. Второй метод, s e t F u l l Y e a r , устанавли
вает год в объекте D a t e и возвращает число миллисекунд, прошедших с полуночи
1 января 1970 г. до момента, соответствующего значению объекта D a t e . Заметьте,
что методы g e t F u l l Y e a r / s e t F u l l Y e a r были введены в JavaScript 1.0 и в на
стоящее время не рекомендованы для использования, так как в одних броузерах
год задается числом, содержащим два знака, в других — числом из четырех знаков.
parse(dateString)
Данный метод на самом деле не является методом объекта D a t e . К нему следует
обращаться с помощью выражения D a t e . p a r s e . В качестве параметра данному
методу передается строка в одном из допустимых форматов, а в результате выпол
нения метода возвращается число миллисекунд, прошедших с полуночи 1 января
1970 г. Метод p a r s e поддерживает стандартный формат даты IETF, используемый
в Internet (генерируемый методом t o G M T S t r i n g ) . Например:
// Время тихоокеанского побережья США.
var dateString = "Wed, 3 Sep 1997 08:30:00 -0700";
var dl = new Date(Date.parse(dateString));
// Восточное время США.
document.writeln(dl.toLocaleString());
Метод p a r s e также может обрабатывать строки в формате "Month Day, Y e a r "
("Месяц День, Год"), где месяц задается полным именем либо первыми тремя бук
вами (в верхнем или нижнем регистре). В формате IETF разрешается задавать
смещение временного пояса либо временные пояса США (например, EDT).
toGMTStringO
Данный метод генерирует строку, которая представляет дату и время, соответст
вующие GMT. Строка форматируется по соглашениям IETF (см. описание метода
parse).
toLocaleStringO
Метод t o L o c a l e S t r i n g генерирует строку, которая представляет значение объ
екта D a t e для локального временного пояса. Форматирование выполняется в со
ответствии с соглашениями для локального пояса.
25.5. Объект Document 1183
UTC(year, m o n t h , day)
UTC(year, m o n t h , day, hrs)
UTC(year, m o n t h , day, h r s , mins)
UTC(year, m o n t h , day, hrs, m i n s , sees)
Указанные методы на самом деле не являются методами объекта D a t e . Обращать
ся к ним надо с помощью выражения Date.UTC. Считается, что значения пара
метра соответствуют гринвичскому времени, или GMT (оно также называется
универсальным временем, или UTC). В результате выполнения методов возвраща
ется число миллисекунд, прошедших с полуночи 1 января 1970 г.
Обработчики событий
Обработчики событий отсутствуют. Объект D a t e не соответствует ни одному из
HTML-элементов.
Свойства
alinkColor
Данное свойство содержит строку, определяющую цвет активизированной ссыл
ки. Это свойство задается с помощью атрибута ALINK дескриптора <BODY> и мо
жет быть м о д и ф и ц и р о в а н о только сценариями в разделе HEAD документа (разбор
которого выполняется раньше, чем разбор раздела BODY). Свойство a l i n k C o l o r
предназначено только для чтения.
anchors
Свойство a n c h o r s позволяет обращаться к массиву объектов A n c h o r , каждый из
которых соответствует вхождению в документ дескриптора <А NAME= . . . >.
applets
Данное свойство обеспечивает дост)^п к массиву объектов A p p l e t , каждый эле
мент которого соответствует вхождению в документ дескриптора <APPLET . . . >.
Если в составе дескриптора <APPLET> прис)^ствует атрибут MAYSCRIPT, вы може
те непосредственно вызывать методы аплета из JavaScnpt-сценария. Соответст
вующий пример см. в разделе 24.9.
bgColor
Данное свойство содержит строку, определяющую цвет фона документа. Первона
чально значение данного свойства устанавливается с помощью атрибута BGCOLOR
1184 Глава 25. Краткое руководство по JavaScript
cookie
Данное свойство, доступное как для чтения, так и для записи, содержит значения
cookie, связанных с документом. Установка свойства c o o k i e изменяет значения
cookie, сохраненные броузером (подробно об этом см. в разделе 24.7).
domain
Свойство d o m a i n содержит строку, определяющую Internet-домен, из которого
был получен документ. Данное свойство доступно только для чтения. В JavaScript
отсутствуют стандартные средства, позволяющие определить домен или имя узла
клиента (программы, с помощью которой пользователь просматривает документ,
но вы можете сделать это посредством Java-аплета. О вопросах взаимодействия
JavaScript и Java см. в разделе 24.9.
embeds
Данное свойство обеспечивает дост)'п к массиву объектов J a v a O b j e c t , соответст
вующих встроенным объектам в составе элементов EMBED документа. Если встро
енные объекты являются Java-объектами, вы можете вызывать их общедоступные
методы, в противном случае вам не удастся использовать их. Массив e m b e d s также
называется p l u g i n s .
fgColor
Указанное свойство содержит строку, определяющую цвет переднего плана доку
мента. Первоначально значение f g C o l o r устанавливается посредством атрибута
TEXT дескриптора <BODY> и может быть изменено лишь сценарием, выполняю
щимся в разделе HEAD документа. Свойство f g C o l o r дост)^пно только для чтения.
forms
Массив, состоящий из объектов Form, каждый из которых соответствует вхожде
нию в документ дескриптора <FORM . . . >. Дополнительную информацию об объ
екте Form вы найдете в разделе 25.8.
images
Массив объектов Image, каждый из которых соответствует вхождению в документ де
скриптора <IMG . . . >. Примеры использования данного свойства см. в разделе 24.5.
lastModified
Свойство l a s t M o d i f i e d содержит дату последнего изменения документа. Для
пользователей, часто обращающихся к одной Web-странице за новой информаци
ей, удобно, если значение l a s t M o d i f i e d будет отображаться в начале документа.
Данное свойство дост)'пно только для чтения.
25.5. Объект Document 1185
linkColor
Значением данного свойства является строка. Эта строка определяет цвет гипер
текстовых ссылок, указывающих на документы, которые еще не просматривались
клиентом. Первоначально значение l i n k C o l o r устанавливается с помощью атри
бута LINK дескриптора <BODY> и может быть изменено только сценарием в разде
ле HEAD документа. Данное свойство дост)'пно только для чтения.
links
Данное свойство предоставляет доступ к массиву объектов L i n k , каждый из кото
рых соответствует вхождению в документ дескриптора <А HREF. . . >.
location
Свойство l o c a t i o n , доступное только для чтения, ссылается на тот же объект
L o c a t i o n , что и свойство window, l o c a t i o n , и предоставляет доступ к URL, кото
рый может быть изменен вследствие перенаправления. Свойство d o c u m e n t . URL со
держит реальный URL.
plugins
Данное имя свойства является синонимом свойства e m b e d s . Заметьте, что массив
p l u g i n s содержит не объекты P l u g i n , а объекты типа J a v a O b j e c t и описывает
элементы, встроенные в текущий документ, а не дополнительные модули броузера.
Для того чтобы получить массив, описывающий дополнительные модули броузера,
следует использовать свойство n a v i g a t o r . p l u g i n s .
referrer
Значением свойства r e f e r r e r является строка (возможно, пустая), которая со
держит URL документа. В этом документе находится ссылка, в результате активи
зации которой была получена текущая Web-страница. Данное свойство доступно
только для чтения.
title
Свойство t i t l e содержит строку, определенную посредством дескриптора <TITLE>.
Это свойство доступно только для чтения.
URL
Строка, содержащая URL текущего документа. Свойство доступно только для чтения.
vlinkColor
Значением данного свойства является строка. Эта строка определяет цвет гипер
текстовых ссылок, указывающих на документы, которые уже посещались клиен
том. Первоначально значение v l i n k C o l o r устанавливается с помощью атрибута
VLINK дескриптора <BODY> и может быть изменено только сценарием в разделе
HEAD документа. После этого свойство v l i n k C o l o r доступно лишь для чтения.
1186 Глава 25. Краткое руководство по JavaScript
Методы
close()
Данный метод закрывает выходной поток для документа. В результате выводятся
данные, которые еще не были отображены. Совместно с методом o p e n метод
c l o s e используется при создании новых документов.
getSelectionO
Метод g e t S e l e c t i o n возвращает текст, содержащийся в выделенной области.
ореп()
open(mimeType)
o p e n ( m i m e T y p e , "replace")
Данный метод создает в текущем окне новый документ. Чаще всего используется
первый из приведенных вариантов метода, после чего с помощью методов w r i t e
и w r i t e l n включается содержимое документа. П р и вызове метода o p e n можно
также задать МШЕ-тип.
Если указан параметр "replace", новый документ замещает существующий в списке
предыстории, в противном случае создается новый пункт списка.
write(argl, a r g 2 , . . . , argN)
w r i t e l n ( a r g l , a r g 2 , . . . , argN)
Эти методы передают указанные данные документу; второй из приведенных мето
дов завершает данные символом новой строки.
Обработчики событий
в объекте Document обработчики событий отсутствуют. Атрибуты o n l o a d и
o n u n l o a d дескриптора <BODY> определяют обработчики объекта Window, а не объ
екта Document.
Свойства
Перечисленные ниже свойства принадлежат не всем типам объектов E l e m e n t .
Подробно конкретные т и п ы элементов будут рассмотрены далее в этой главе; там же
будут описаны их свойства.
25.6. Объект Element 1187
checked
Данное свойство используется объектами Checkbox и Radio.
defaultChecked
Данное свойство используется объектами Checkbox и Radio.
defaultValue
Данное свойство используется объектами FileUpload, Password, Text и Textarea.
form
Данное свойство используется всеми объектами Element и ссылается на HTML-
форму, в состав которой входит элемент.
length
Данное свойство используется только объектом S e l e c t .
name
Данное свойство используется всеми объектами Element и содержит значение
HTML-атрибута NAME.
options
Данное свойство используется только объектом Select.
selectedlndex
Данное свойство используется только объектом Select.
type
В JavaScript LI это свойство используется всеми объектами Element и может быть
использовано для определения типа элемента. Свойство t y p e может принимать
следующие значения: b u t t o n , checkbox, f i l e , hidden, password, r a d i o , r e s e t ,
select-one, select-multiple,submit,text и textarea.
value
Данное свойство используется всеми объектами Element и содержит значение,
связанное с именем элемента. Значение вместе с именем передается на сервер.
Методы
Как и свойства, перечисленные ниже методы используются не всеми типами объ
ектов Element. Дополнительная информация о методах приводится при рассмотре
нии конкретных типов элементов.
1188 Глава 25. Краткое руководство по JavaScript
blurO
Данный метод используется всеми типами объектов E l e m e n t за исключением
объекта H i d d e n .
clickO
Данный метод используется объектами Button, Checkbox, Radio, Reset и Submit.
focus()
Данный метод используется всеми типами объектов E l e m e n t за исключением
объекта H i d d e n .
select()
Данный метод используется теми типами объектов E l e m e n t , которые имеют тек
стовые значения, а именно: F i l e U p l o a d , P a s s w o r d , T e x t и T e x t a r e a .
Обработчики событий
Здесь перечислены типы объектов E l e m e n t и связанные с ними события.
onblur()
Данный метод используется всеми типами объектов E l e m e n t за исключением
объекта H i d d e n .
onchange()
Данный метод используется объектами F i l e U p l o a d , P a s s w o r d , T e x t и T e x t a r e a .
onclickO
Данный метод используется объектами Button, Checkbox, Radio, Reset и
Submit.
ondblclick()
Данный метод используется объектами B u t t o n , R e s e t и S u b m i t .
onfocus()
Данный метод используется всеми типами объектов E l e m e n t за исключением
объекта H i d d e n .
Свойства
form
Д а н н о е свойство, предназначенное только для чтения, предоставляет доступ к
объекту Form, содержащему данный элемент.
name
Если в составе элемента присутствует атрибут NAME, данное свойство содержит
значение этого атрибута. Свойство name предназначено только для чтения.
type
Д а н н о е свойство всегда содержит значение f i l e . Свойство t y p e соответствует
всем объектам E l e m e n t , поэтому оно о б ы ч н о используется для идентификации
типа элемента.
value
Значением свойства v a l u e является строка, заданная посредством атрибута
VALUE. Это свойство предназначено только для чтения.
Методы
blurO
В результате выполнения этого метода элемент теряет фокус ввода.
focus()
в результате выполнения этого метода элемент получает фокус ввода.
select()
Д а н н ы й метод выделяет текст в составе элемента. Любой символ, введенный поль
зователем, замещает выделенный текст.
Обработка событий
onblurO
Д а н н ы й метод вызывается при потере элементом фокуса ввода. О б ы ч н о обработ
чик o n b l u r определяется посредством атрибута o n B l u r , например:
<INPUT TYPE="FILE" . . .
onBlur="doSomeAction()">
onchange()
Для того чтобы метод on c h a n g e получил управление, надо чтобы элемент потерял
фокус ввода после изменения его значения. Данный метод определяется посред
ством атрибута o n C h a n g e .
1190 Глава 25. Краткое руководство по JavaScript
onfocusO
Метод o n f o c u s , определяемый посредством атрибута o n F o c u s , вызывается при
получении элементом фокуса ввода.
Свойства
action
Значением этого свойства является строка, содержащая URL, по которому должны
быть переданы данные ф о р м ы . Свойство a c t i o n доступно как для чтения, так и
для записи.
elements
Свойство e l e m e n t s обеспечивает доступ к массиву, состоящему из объектов E l e
m e n t . Каждый элемент массива соответствует интерфейсному элементу, содержа
щемуся в HTML-форме. Объекты E l e m e n t рассматривались в разделе 25.6.
encoding
Данное свойство содержит строку, определяющую метод кодирования формы.
Первоначально значение свойства устанавливается с помощью атрибута ENCTYPE.
Свойство e n c o d i n g доступно как для чтения, так и для записи.
method
Данное свойство, первоначально устанавливаемое посредством атрибута METHOD,
может иметь значение либо g e t , либо p o s t . Свойство m e t h o d допускает как чте
ние, так и запись.
target
Свойство t a r g e t содержит строку, определяющую ф р е й м , в котором должны
отображаться результаты, полученные при активизации ф о р м ы . Это свойство по
зволяет читать и записывать значение и первоначально определяется посредст
вом атрибута TARGET.
Методы
reset()
Данный метод вызывает обработчик события o n r e s e t , после чего, если обработ
чик возвращает значение t r u e , восстанавливает начальное состояние элементов
формы, определенное в документе. Данный метод выполняет те же действия, ко
торые выполняются после щелчка на кнопке RESET.
25.9. Объект Function 1191
submit()
Данный метод передает данные ф о р м ы на сервер, не вызывая перед этим обработ
чик o n s u b m i t .
Обработчики событий
onreset()
Данный метод вызывается после щелчка на кнопке RESET либо при выполнении
метода r e s e t . Обычно обработчик o n r e s e t определяется посредством атрибута
onReset.
<FORM A C T I O N = " . . . " ...
onReset="return(maybeReset())">
onsubmit()
Обработчик o n s u b m i t вызывается при активизации пользователем кнопки SUBMIT.
П р и выполнении метода s u b m i t автоматический вызов o n s u b m i t не производится.
Данный обработчик определяется посредством атрибута o n S u b m i t .
<FORM A C T I O N = " . . . " . . .
onSubmit="return(validateEntries ())">
П р и м е р использования o n s u b m i t см. в разделе 24.6.
Конструктор
n e w Function(argOName,... , a r g N N a m e , bodyString)
Данный конструктор создает новую функцию. Ниже показаны два способа созда
ния одной и той же функции, но второй способ может быть использован в другой
программе в процессе выполнения сценария.
function square(х) { return(х * х ) ; }
square = new Function("х", "return(х * х)");
Свойства
arguments
В теле функции это свойство предоставляет массив параметров, заданных при вы
зове. Благодаря наличию свойства a r g u m e n t s имеется возможность создавать
функции с переменным числом параметров. В следующем примере функция сум
мирует значения переданных ей параметров:
1192 Глава 25. Краткое руководство по JavaScript
function sum О {
var t o t a l = 0;
f o r ( v a r i=0; i < a r g u m e n t s . l e n g t h ; i++) {
t o t a l = t o t a l + arguments[i];
}
return(total) ;
}
arity
Данное свойство, предназначенное только для чтения, определяет число пара
метров, объявленных для данной функции. Реальное число параметров может от
личаться от значения свойства a r i t y , в этом случае можно воспользоваться свой
ством arguments . l e n g t h .
caller
В теле функции это свойство позволяет определить объект Function, из которого
данная функция была вызвана. Если вызов осуществлялся непосредственно из
сценария, свойство c a l l e r содержит значение n u l l . Данное свойство предназна
чено только для чтения.
prototype
В конструкторе p r o t o t y p e определяет свойства, совместно используемые всеми
объектами указанного типа. Пример использования свойства p r o t o t y p e см. в раз
деле 24.3.
Методы
Объект F u n c t i o n содержит только те методы, которые присутствуют в каждом
объекте Obj e c t .
Обработчики событий
Обработчики событий отсутствуют. Объект F u n c t i o n не соответствует ни одному
из HTML-элементов.
Свойства
form
Указанное свойство, предназначенное только для чтения, ссылается на объект
Form, в котором содержится данный элемент.
name
Данное свойство, предназначенное только для чтения, содержит имя элемента,
определенное посредством атрибута NAME.
type
Свойство t y p e доступно только для чтения и содержит значение h i d d e n .
value
Это свойство содержит строку, которая вместе с именем передается программе на
стороне сервера.
Методы
Методы отсутствуют.
Обработчики событий
Обработчики событий отсутствуют.
2 5 . 1 1 . Объект History
Объект H i s t o r y соответствует списку предыстории окна или фрейма. В нем со
держится список JavaScript, которые ранее посещались данным клиентом. Объект
H i s t o r y доступен посредством свойства h i s t o r y объекта Window, т.е для обраще
ния к нему используется выражение w i n d o w , h i s t o r y или h i s t o r y .
Свойства
current
JavaScript-сценарий позволяет получить URL текущего документа. Свойство c u r
r e n t содержит строку символов и предназначено только для чтения.
length
Данное свойство предназначено только для чтения и сообщает число URL, содер
жащихся в списке предыстории.
next
Строка, являющаяся значением свойства n e x t , содержит URL следующего доку
мента в списке предыстории. Данное свойство предназначено только для чтения.
1194 Глава 25. Краткое руководство по JavaScript
previous
Значением свойства p r e v i o u s является строка символов, которая определяет
URL предыдущего документа в списке предыстории. Данное свойство предназна
чено только для чтения.
Методы
ЬаскО
Д а н н ы й метод дает команду броузеру п е р е й т и на один пункт назад по списку пре
дыстории.
forwardO
Этот метод дает команду броузеру п е р е й т и на один пункт вперед по списку пре
дыстории.
go(n)
Данный метод дает команду броузеру перейти на п пунктов вперед (если п положи
тельное) или на п пунктов назад (если п отрицательное) по списку предыстории.
Обработчики событий
Обработчики событий отсутствуют. Объект H i s t o r y не соответствует ни одному
из HTML-элементов.
Конструктор
n e w I m a g e ( w i d t h , height)
Данный конструктор создает новый объект I m a g e , описывающий изображение
заданного размера. Объект Image в основном создается для того, чтобы, задавая
значение свойства s r c , выполнить предварительную загрузку изображения и со
хранить его в кэше броузера. Особенность такого подхода заключается в том, что
после установки значения свойства s e t объект Image больше не используется.
П р и м е р применения конструктора Image см. в разделе 24.5.
2 5 . 1 2 . Объект Image 1195
Свойства
border
Данное свойство задает размер обрамления вокруг изображения, которое создает
ся тогда, когда изображение оформляется как гипертекстовая ссылка. Значение
свойства b o r d e r , предназначенного только для чтения, определяется посредст
вом атрибута BORDER элемента IMG.
complete
Данное свойство, предназначенное только для чтения, содержит логическое зна
чение, указывающее, окончена ли загрузка изображения.
height
Свойство h e i g h t содержит сведения о высоте изображения, заданной посредст
вом атрибута HEIGHT, либо, если атрибут HEIGHT отсутствует, определенной в
графическом файле. Данное свойство доступно только для чтения.
hspace
Свойство h s p a c e определяет число пустых пикселей слева и справа от изображе
ния. Данное свойство предназначено только для чтения; значение его задается с
помощью атрибута HSPACE.
lowsrc
Netscape (но не Internet Explorer) поддерживает нестандартный атрибут LOWSRC
элемента IMG, посредством которого задается альтернативное изображение,
предназначенное для вывода на дисплей с малой разрешающей способностью.
Строка, определенная с помощью атрибута LOWSRC, является значением свойства
l o w s r c . Это свойство допускает как чтение, так и запись.
name
Данное свойство, предназначенное только для чтения, содержит имя изображе
ния, определенное с помощью атрибута NAME.
src
Данное свойство содержит строку, которая представляет URL графического фай
ла, содержащего изображение. Свойство s r c допускает как чтение, так и запись.
vspace
Свойство v s p a c e , предназначенное только для чтения, определяет число пустых
пикселей сверху и снизу изображения. Значение свойства задается с помощью ат
рибута VSPACE.
width
Свойство w i d t h содержит значение ш и р и н ы изображения, заданной посредством
атрибута WIDTH, либо, если атрибут WIDTH отсутствует, определенной в графиче
ском файле. Данное свойство доступно только для чтения.
1196 Глава 25. Краткое руководство по JavaScript
Методы
Методы отсутствуют.
Обработчики событий
onabort()
Этот метод вызывается в том случае, если пользователь останавливает загрузку
изображения, щелкая на кнопке S t o p либо активизируя гипертекстовую ссылку,
указывающую на другую Web-страницу. О б ы ч н о метод o n a b o r t определяется по
средством атрибута o n A b o r t , как показано ниже.
<IMG S R C = " . . . " ...
onAbort="takeSomeAction()">
onerror()
Метод o n e г г o r получает управление, если графический файл, содержащий изо
бражение, не найден либо если он имеет некорректный формат. О б ы ч н о метод
o n e г г o r определяется посредством атрибута о п Е г г о г .
<IMG S R C = " . . . " . . .
onError="alertС Error loading image')">
Значение n u l l атрибута o n E r r o r подавляет вывод сообщения об ошибке.
<IMG SRC="..." ...
onError ="null">
onload()
Метод o n l o a d вызывается тогда, когда броузер оканчивает загрузку изображения.
Каждое изменение свойства s r c приводит к вызову этого метода. О б ы ч н о метод
o n l o a d определяется посредством атрибута onLoad.
<IMG S R C = " . . . " ...
onLoad="startImageAnimation()">
В данном примере функция s t a r t l m a g e A n i m a t i o n может изменять значение свойст
ва s r c , что, в свою очередь, приведет к повторному вызову s t a r t l m a g e A n i m a t i o n .
Конструкторы
n e w Layer(width)
Данный конструктор создает новый объект L a y e r . Для определения содержимого
надо установить свойство s r c либо использовать метод l o a d .
n e w Layer(width, parentLayer)
Данный конструктор создает слой, дочерний по о т н о ш е н и ю к указанному.
Свойства
above
Данное свойство, предназначенное только для чтения, определяет слой над теку
щим слоем.
background
Указанное свойство задает изображение для фонового слоя. Свойство b a c k g r o u n d
допускает как чтение, так и запись. Например:
someLayer.background.src = "bricks.gif";
below
Данное свойство, предназначенное только для чтения, определяет слой под теку
щим слоем.
bgColor
Обычно слои прозрачны, но с помощью свойства b g C o l o r , допускающего как
чтение, так и запись, их можно сделать непрозрачными. Например:
someLayer.bgColor = " b l u e " ;
1198 Глава 25. Краткое руководство по JavaScript
anotherLayer.bgcolor = "#FFOOFF";
thirdLayer.bgColor = null; // прозрачный
clip
Данное свойство, предназначенное как для чтения, так и для записи, определяет
область отсечения. В его состав входят c l i p , t o p , c l i p . b o t t o m , c l i p , l e f t ,
clip.right, clip.width и clip.height.
document
Каждый слой содержит собственный объект Document. Данное свойство, предна
значенное только для чтения, ссылается на объект документа.
left
Это свойство представляет горизонтальную составляющую позиции слоя относи
тельно родительского слоя. Свойство l e f t допускает чтение и запись.
name
Свойство name предназначено только для чтения и определяется атрибутом ID
или NAME.
pageX
Данное свойство представляет абсолютную позицию (ее горизонтальную состав
ляющую) слоя на странице. Свойство радеХ допускает как чтение, так и запись.
pageY
Данное свойство представляет абсолютную позицию (ее вертикальную состав
ляющую) слоя на странице. Свойство pageY допускает как чтение, так и запись.
parentLayer
Свойство p a r e n t L a y e r содержит данные о родительском слое, если таковой су
ществует. В противном случае о н о ссылается на объект Window. Д а н н о е свойство
предназначено только для чтения.
siblingAbove
Данное свойство ссылается на слой, расположенный над текущим. Текущий слой и
слой, на который ссылается свойство, должны быть дочерними слоями одного и
того же слоя. Свойство s i b l i n g A b o v e доступно только для чтения.
siblingBelow
Д а н н о е свойство ссылается на слой, расположенный под текущим. Текущий слой и
слой, на который ссылается свойство, должны быть дочерними слоями одного и
того же слоя. Свойство s i b l i n g A b o v e доступно только для чтения.
src
Данное свойство, допускающее как чтение, так и запись, предоставляет URL, ко
т о р ы й определяет содержимое слоя.
25.15. Объект Layer 1199
top
Данное свойство определяет вертикальную составляющую позиции слоя относи
тельно родительского слоя. Свойство t o p доступно как для чтения, так и для записи.
visibility
Свойство v i s i b i l i t y определяет видимость слоя. Оно может иметь значения
show (слой является видимым), h i d e , или h i d d e n (слой невидим) и i n h e r i t
(слой наследует видимость родительского слоя). Данное свойство допускает как
чтение, так и запись.
zindex
Данное свойство содержит индекс, определяющий порядок расположения слоя
среди дочерних слоев того же родительского слоя. Слой с наименьшим индексом
является самым нижним, слой с наибольшим индексом — самым верхним. Свойст
во z i n d e x предназначено как для чтения, так и для записи.
Методы
l o a d ( s o u r c e S t r i n g , width)
Данный метод одновременно изменяет и источник слоя, и его ширину (см. описа
ние свойства s r c ) .
moveAbove(layer)
Метод moveAbove располагает текущий слой над указанным.
moveBelow(layer)
Метод moveBelow располагает текущий слой под указанным.
m o v e B y ( d x , dy)
Данный метод сдвигает позицию слоя на указанное число пикселей.
m o v e T o ( x , у)
Данный метод размещает слой так, что его верхний левый угол располагается в
указанной позиции включающего слоя или документа. См. свойства l e f t и t o p .
m o v e T o A b s o l u t e ( x , у)
Метод m o v e T o A b s o l u t e размещает слой так, что его верхний левый угол распола
гается в указанной позиции окна (см. описание свойств радеХ и pageY).
resizeBy(dWidth, d H e i g h t )
Данный метод изменяет ширину и высоту слоя на указанное число пикселей
(см. свойства c l i p . w i d t h и c l i p . h e i g h t ) .
1200 Глава 25. Краткое руководство по JavaScript
resizeTo(width, h e i g h t )
Метод r e s i z e T o устанавливает ширину и высоту слоя в пикселях (см. свойства
clip.width и clip.height).
Обработчики событий
onblurO
Этот метод вызывается тогда, когда слой теряет фокус ввода. Для определения
данного метода используется атрибут o n B l u r дескриптора LAYER или ILAYER. Ес
ли слой создается средствами каскадных листов стилей, выполняется непосредст
венное присвоение функции, например:
function blurHandler() { ... }
someLayer.onblur = blurHandler;
onfocus()
Данный метод вызывается при получении слоем фокуса ввода. Для определения
обработчика используется атрибут on F o c u s .
onload()
Метод o n l o a d получает управление по окончании загрузки слоя (это может про
изойти до того, как слой отобразится на экране). Для определения обработчика
используется атрибут o n L o a d .
onmouseout()
Метод o n m o u s e o u t вызывается тогда, когда курсор мыши выходит за пределы
слоя. Данный метод определяется посредством атрибута onMouseOut.
onmouseoverO
Метод o n m o u s e o v e r вызывается тогда, когда курсор мыши попадает в пределы
слоя. Для определения метода используется атрибут o n M o u s e O v e r .
Свойства
hash
Данное свойство представляет часть ссылки, указывающую на позицию внутри до
кумента (включая символ "#"). Свойство h a s h допускает как чтение, так и запись.
host
Указанное свойство предназначено для чтения и записи и содержит строку в фор
мате гсмя_узла: порт.
hostname
Свойство hostname допускает как чтение, так и запись и содержит имя узла.
href
Данное свойство содержит полный URL и доступно как для чтения, так и для записи.
pathname
Свойство pathname содержит часть URL, расположенную после имени узла и но
мера порта. Данное свойство допускает как чтение, так и запись.
port
Данное свойство определяет порт, однако содержит не целое число, а строку сим
волов. Свойство p o r t доступно как для чтения, так и для записи.
protocol
Данное свойство, допускающее как чтение, так и запись, определяет протокол.
Двоеточие входит в состав значения свойства.
search
Свойство s e a r c h содержит информацию, которую принято называть данными
поиска (например, "?х,у" для ISMAP или "?х=1&у=2" при передаче данных фор
мы на сервер). Данное свойство предназначено как для чтения, так и для записи.
target
Свойство t a r g e t содержит имя, указанное в качестве значения атрибута TARGET.
Это свойство доступно как для чтения, так и для записи. Так, например, для того,
чтобы организовать вывод данных, полученных при активизации любой гипер
текстовой ссылки в фрейм с именем framel, можно использовать следующий
фрагмент кода:
for(var i=0; i<document.links.length; i++) {
document.links[i].target = "framel";
}
1202 Глава 25. Краткое руководство по JavaScript
Методы
Методы, отличные от обработчиков событий, отсутствуют.
Обработчики событий
onclickO
Этот обработчик вызывается после щелчка пользователя на гипертекстовой ссылке.
Если данный метод возвращает значение f a l s e , переход по ссылке не происходит.
Для определения метода o n c l i c k используется атрибут onClick, например:
<А H R E F = " . . . " ...
onClick="return(maybeCancel() ) ">
ondblclick()
Данный метод вызывается после двойного щелчка мышью. После первого щелчка
вызывается метод o n c l i c k . Метод o n d b l c l i c k не поддерживается Macintosh и
Netscape 6.
onmouseout()
Этот метод получает управление тогда, когда пользователь убирает курсор мыши с
гипертекстовой ссылки. В сочетании с onmouseover метод onmouseout предос
тавляет возможность подсветки изображения, используемого в качестве гипертек
стовой ссылки, при помещении на него курсора мыши. Соответствующий пример
см. в разделе 24.5. Для определения метода onmouseout используется атрибут
onMouseOut.
onmouseover()
Данный метод вызывается тогда, когда пользователь помещает курсор мыши на
гипертекстовую ссылку. Для определения onmouseover используется атрибут
onMouseOver. Если метод onMouseOver возвращает значение t r u e , броузер не
отображает URL в строке состояния. Эту возможность можно использовать для
вывода в строке состояния произвольных сообщений.
Свойства
hash
Данное свойство содержит часть ссылки, указывающую на позицию внутри доку
мента (включая символ "#"). Свойство hash допускает как чтение, так и запись.
25.17. Объект Location 1203
host
Указанное свойство предназначено для чтения и записи и содержит строку в фор
мате имя_узла: порт.
hostname
Свойство hostname допускает как чтение, так и запись и содержит имя узла.
href
Данное свойство содержит полный URL и доступно как для чтения, так и для записи.
pathname
Свойство pathname содержит часть URL, расположенную после имени узла и но
мера порта. Данное свойство допускает как чтение, так и запись.
port
Данное свойство определяет порт, однако содержит не целое число, а строку сим
волов. Свойство p o r t доступно как для чтения, так и для записи,
protocol
Данное свойство, допускающее как чтение, так и запись, определяет протокол.
Двоеточие входит в состав значения свойства.
search
Свойство s e a r c h содержит информацию, которую принято называть данными
поиска (например, "?х,у" для ISMAP или "?х=1&:у=2" при передаче данных формы
на сервер). Данное свойство предназначено как для чтения, так и для записи.
Свойство s e a r c h можно использовать для реализации карты изображения или
CGI-формы, обеспечивающей навигацию внутри страницы. Для этого надо задать
в качестве целевого URL текущий документ и проверять в начале документа
l o c a t i o n . s e a r c h (функция u n e s c a p e описана в разделе 25.31).
Методы
reloadO
reload(true)
Первый из приведенных методов повторно загружает документ. Загрузка произ
водится только в том случае, если сервер сообщает, что с момента последнего про
смотра документ изменился. Вызов второго метода всегда приводит к перезагрузке
документа.
replace(newURL)
Этот метод замещает текущий документ новым, определенным с помощью пара
метра newURL. При этом новый пункт в списке предыстории не создается.
1204 Глава 25. Краткое руководство по JavaScript
Обработчики событий
Обработчики событий отсутствуют.
Свойства
Н и ж е приведены константы, использовать которые проще, чем каждый раз вы
числять их.
Е
Основание натурального логарифма.
LN10
Данное свойство содержит In(10) или log^(lO).
LN2
Данное свойство содержит 1п(2), или log^(2).
LOG10E
Данное свойство содержит logio(e).
LOG2E
Данное свойство содержит lg(e) или log2(e).
PI
Данное свойство содержит число п.
SQRT1_2
Данное свойство содержит квадратный корень из 1/2.
SQRT2
Данное свойство содержит квадратный корень из 2.
2 5 . 1 8 . Объект Math 1205
Методы
ceil(num)
Метод c e i l возвращает наименьшее целое число, равное или превышающее ука
занное число (num).
exp(num)
^ num
Д
анныи метод возвращает результат вычисления е
floor(num)
Метод c e i l возвращает наибольшее целое число, равное или меньшее, чем ука
занное число (num).
log(num)
Данный метод возвращает натуральный логарифм указанного числа (num).
JavaScript не предоставляет методы для вычисления логарифмов по другим осно
ваниям (например, 10 и 2). Для этого можно воспользоваться соотношением
1оды(п) = 1одь2(п) / 1одь2(Ы)
Функция, предназначенная для преобразования логарифмов, имеет следующий вид:
function log(num, base) {
return(Math.log(num) / Math.log(base));
}
max(numl, num2)
Указанный метод возвращает наибольшее из чисел numl и num2.
min(numl, num2)
Указанный метод возвращает наименьшее из чисел numl и num2.
pow(base, e x p o n e n t )
-. «• , exponent
Метод pow возвращает значение b a s e
random()
Метод r a n d o m возвращает случайное значение в интервале от 0.0 до 1.0 (число 0.0
входит, а число 1.0 не входит в состав интервала).
1206 Глава 2 5 . Краткое руководство по JavaScript
round(num)
Данный метод округляет число, заданное посредством параметра num, до ближайше
го целого числа. Для чисел х х х . 5 производится округление до большего значения.
sqrt(num)
Метод s q r t возвращает квадратный корень из числа num. Если в качестве пара
метра задано отрицательное число, возвращается значение NaN.
Тригонометрические методы
П р и вызове всех приведенных ниже методов параметры задаются не в градусах, а
в радианах. Преобразовать градусы в радианы можно следующим образом:
function degreesToRadians(degrees) {
return(degrees * Math.PI / 180);
}
acos(num)
Д а н н ы й метод возвращает арккосинус числа, указанного посредством параметра
num. Результат представлен в радианах.
asin(num)
Данный метод возвращает арксинус числа, }тсазанного посредством параметра num.
atan(num)
Данньп1 метод возвращает арктангенс указанного числа.
atan2(y, х)
Метод a t a n 2 возвращает компонент 0 полярных координат ( г , Э) точки, соот
ветствующей точке ( х , у) в декартовой системе координат. Это значение равно
арктангенсу у / х и находится в диапазоне от -п до тт.
cos(radians)
Д а н н ы й метод возвращает косинус угла, заданного в радианах.
sin(radians)
Данный метод возвращает синус угла, заданного в радианах.
tan(radians)
Д а н н ы й метод возвращает тангенс угла, заданного в радианах.
Обработчики событий
Обработчики событий отсутствуют.
2 5 . 1 9 . Объект MimeType 1207
2 5 . 1 9 . Объект MimeType
Объект MimeType описывает MIME-тип. В массиве n a v i g a t o r . m i m e T y p e s пере
числены все МШЕ-типы, поддерживаемые броузером, либо посредством встроенных
модулей, либо с помощью внешних приложений. Н а п р и м е р , следующий фрагмент
кода включает в документ ссылку на файл в формате Adobe Acrobat только в том слу
чае, если Acrobat поддерживается броузером. В противном случае в документ поме
щается ссылка, указывающая на о б ы ч н ы й текстовый документ.
d o c u m e n t . w r i t e l n ( ' F o r more i n f o r m a t i o n , s e e ' ) ;
i f ( n a v i g a t o r . m i m e T y p e s [ " a p p l i c a t i o n / p d f " ] != n u l l ) {
document.writeln
('<A H R E F = " m a n u a l . p d f " > t h e w i d g e t m a n u a l < / A > . ' ) ;
} else {
document.writeln
(*<A H R E F = " m a n u a l . t e x t " > t h e w i d g e t m a n u a l < / A > . ' ) ;
}
Список часто используемых MIME-типов см. в табл. 19.1.
Свойства
description
Данное свойство, предназначенное только для чтения, содержит текст, описы
вающий МШЕ-тип.
enabledPlugin
Свойство e n a b l e d P l u g i n ссылается на доступный объект P l u g i n , поддержи
вающий МХМЕ-тип. Если дополнительный модуль для поддержки данного типа не
установлен или использование его запрещено, свойство e n a b l e d P l u g i n содер
жит значение n u l l . Д а н н о е свойство предназначено только для чтения.
suffixes
Данное свойство содержит список расширений файлов, связанных с МШЕ-типом.
Элементы списка разделяются запятыми. Свойство s u f f i x e s доступно только для
чтения.
type
Значением данного свойства является строка, содержащая тип, например
application/postscript.
Методы
Методы отсутствуют.
Обработчики событий
Обработчики событий отсутствуют. Объект MimeType не соответствует ни одному
из HTML-элементов.
1208 Глава 25. Краткое руководство по JavaScript
2 5 . 2 0 . Объект Navigator
Объект N a v i g a t o r предоставляет и н ф о р м а ц и ю о броузере. Для доступа к этому
объекту используется свойство n a v i g a t o r объекта Window, т.е. обращение к объекту
N a v i g a t o r имеет вид w i n d o w . n a v i g a t o r либо n a v i g a t o r .
Свойства
Н и ж е описаны свойства объекта N a v i g a t o r . В листинге 25.2 приведен код доку
мента, который строит таблицу, содержащую некоторые свойства. Представление
документа в различных броузерах показано на рис. 25.2 и 25.3.
appCodeName
Д а н н о е свойство, предназначенное только для чтения, содержит кодовое имя бро
узера. Для Internet Explorer и Netscape это свойство имеет значение M o z i l l a .
appName
Значением этого свойства является имя броузера, например Netscape или Micro
soft Internet Explorer. Свойство appName доступно только для чтения.
appVersion
Свойство a p p V e r s i o n , доступное только для чтения, предоставляет сведения об
используемой операционной системе, включгш номер реализации.
language
Свойство l a n g u a g e , предназначенное только для чтения, содержит сведения о
языке броузера. Для английской версии свойство имеет значение e n .
mimeTypes
Д а н н о е свойство предоставляет доступ к массиву объектов MimeType, поддержи
ваемых броузером, либо посредством встроенных модулей, либо с помощью
внешних приложений (см. раздел 25.19).
platform
Свойство p l a t f o r m предоставляет сведения о типе компьютера, для которого
броузер был скомпилирован. Н а п р и м е р , для Windows 95, 98 и N T данное свойство
имеет значение Win32. Свойство p l a t f o r m предназначено только для чтения.
plugins
Д а н н о е свойство предоставляет массив объектов P l u g i n , поддерживаемых бро
узером. Соответствующие п р и м е р ы см. в разделе 24.4.
2 5 . 2 0 . Объект Navigator 1209
userAgent
Данное свойство содержит строку, передаваемую броузером серверу в поле U s e r -
A g e n t заголовка запроса. Свойство u s e r A g e n t доступно только для чтения.
На рис. 25.2 и 25.3 приведены п р и м е р ы некоторых из этих свойств. Для отобра
жения свойств используется документ, код которого представлен в листинге 25.2.
~3
The Navigator Object
Property Value
appCodeName Mozilla
appName Microsoft Internet Explorer
app Version 4 0 (compatible; MSIE 5 0. Windows 98. DigExt) Рис. 25.3. Свойства объекта
userAgent MoaIIa/4.0 (compatible, MSIE 5 0, Windows 98, DigExt) Navigator, отображаемые в броузере
J Internet Explorer 5.0, который
<Э] Done i-jMyConnpirfef выполняется в среде Windows 98
Листинг 2 5 . 2 . N a v i g a t o r . htшll
"<TD>" + object[propertyName]);
}
document.writeln("</TABLE>");
}
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<SCRIPT TYPE="text/javascript">
<! —
// — >
</SCRIPT>
</BODY>
</HTML>
Методы
javaEnabledO
Данный метод возвращает t r u e , если броузер поддерживает Java и обработка Java-
кода разрешена. В противном случае возвращается значение f a l s e .
taint£nabled()
Данный метод возвращает t r u e , если установлена переменная окружения
NSENABLETAINT. Данная переменная позволяет JavaScript-сценарию в одном
документе обрабатывать привилегированные данные других документов. Netscape
удалила эту возможность в JavaScript 1.2 и заменила ее механизмом подписанных
сценариев. Информацию о защите в JavaScript вы найдете по адресу
h t t p : / / d e v e l o p e r . n e t s c a p e . c o m / d o c s / m a n u a l s / j s / c l i e n t / j sguide/sec.htm.
Обработчики событий
Обработчики событий отсутствуют. Объект N a v i g a t o r не соответствует ни одно
му из HTML-элементов.
2 5 . 2 1 . Объект Number
Объект Number содержит информацию, связанную с использованием чисел в сце
нариях. Для обращения к свойствам нет необходимости создавать объект этого типа.
Доступ осуществляется с помощью выражения Number .propertyName, где p r o p e r t y -
2 5 . 2 1 . Объект Number 1211
Name — имя свойства. Объект Number создается только тогда, когда надо использовать
метод t o S t r i n g , позволяющий задавать основание системы счисления.
Конструкторы
new Number(value)
Данный конструктор создает объект Number для простого значения, заданного с
помощью параметра v a l u e .
Свойства
MAX_VALUE
Свойство MAX_VALUE представляет максимальное число, поддерживаемое JavaScript.
MIN_VALUE
Свойство MIN_VALUE представляет минимальное число, поддерживаемое JavaScript.
NaN
Данное свойство представляет специальное значение NaN (not-a-number — не число).
Для проверки на наличие данного значения используется функция isNaN. Приме
нять для проверки оператор == нельзя, поскольку при сравнении NaN с любым чис
лом (в том числе при выполнении выражения Number. NaN ==-• Number. NaN) воз
вращается значение f a l s e .
NEGATIVE J N F I N I T Y
Данное свойство представляет отрицательное значение, соответствующее пере
полнению. Например, это значение получится, если умножить
Number .MAXVALUE на -2. Если умножить NEGATIVE_INFINITY на любое число,
результат будет равен NEGATIVEINFINITY. В результате деления любого числа на
NEGATIVEINFINITY получается значение 0. Ч а с т н о е от деления двух значений
NEGATIVE_INFINITY равно NaN.
POSITIVE J N F I N I T Y
Данное свойство представляет положительное значение, соответствующее пере
полнению.
Методы
toStringO
Данный метод дает те же результаты, что и вызов t o S t r i n g {10).
toString(radix)
Данный метод преобразует число в строку символов, используя систему счисле
ния, заданную посредством параметра r a d i x . Н а п р и м е р , код, приведенный в лис-
1212 Глава 25. Краткое руководство по JavaScript
<SCRIPT TYPE="text/javascript">
<! —
<BODY BGCOLOR="WHITE">
<Hl>Converting Numbers to Strings</Hl>
<SCRIPT TYPE="text/javascript">
<! —
makeNumberTable(nums, radixes);
// — >
</SCRIPT>
</BODY>
</HTML>
2 5 . 2 2 . Объект Object 1213
1 ^ Л 1 '^ 1
2 2
10
2
4 100 4
5 101 5 ^
'5 11
6 no 6
7 111 7 7^ 11
8 1000 10 8 1
9 ;iooi 11 5 1
10 1010 'l2 a 1
15 nil 17 f 1
100 nooioo 144 64 1
512 ЛООООООООО 1000 200 1
1000 i n n O l O O O 1750 3e8 1 Рис. 25.4. Объект Number позволяет
представлять числа в различных
t^f-^ DocumenJ Done ;^ ; •Ш-.:::.: йjr^:! :Ш.;..:: ^j<^:j:' .ij системах счисления
valueOfO
Данный метод возвращает значение простого типа, соответствующее объекту Number.
Обработчики событий
Обработчики событий отсутствуют. Объект Number не соответствует ни одному из
HTML-элементов.
2 5 . 2 2 . Объект Object
Ob j e c t — это объект, на базе которого созданы все остальные объекты. Свойства и
методы объекта Ob j e c t содержат все объекты JavaScript.
Конструкторы
n e w ObjectO
Данный конструктор создает универсальный объект Ob j e c t .
n e w Object(primitiveValue)
В зависимости от типа параметра данный конструктор создает объект Number,
S t r i n g , B o o l e a n или F u n c t i o n .
Свойства
constructor
Данное свойство, предназначенное только для чтения, ссылается на JavaScript-
функцию, посредством которой был создан экземпляр объекта.
prototype
Свойство p r o t o t y p e по сути не является свойством O b j e c t , а, скорее, свойством,
предназначенным для использования в любом конструкторе. В частности, оно
применяется для инициализации свойств объектов, определенных пользователем.
О данном свойстве см. также в разделе 24.3.
Методы
assign(value)
Данный метод вызывается тогда, когда объект определенного вами типа присутст
вует в левой части о п е р а т о р а прямого присваивания. В большинстве случаев метод
a s s i g n создает новый объект и непосредственно заполняет его поля.
eval(javaScriptCode)
Данный метод получает произвольную строку и вычисляет результат.
toStringO
Метод t o S t r i n g генерирует строку, соответствующую объекту.
valueOfO
Если простое значение, соответствующее объекту, существует, данный метод воз
вращает это значение (см. раздел 15.21).
Обработчики событий
Обработчики событий отсутствуют.
Конструкторы
n e w Option()
new Option(text)
n e w O p t i o n ( t e x t , value)
n e w O p t i o n ( t e x t , value, d e f a u l t S e l e c t e d )
n e w O p t i o n ( t e x t , value, d e f a u l t S e l e c t e d , s e l e c t e d )
Каждый из приведенных конструкторов создает новый объект O p t i o n , который
можно включить в состав объекта S e l e c t , разместив его в конце массива o p t i o n s .
25.24. Объект Password 1215
Свойства
defaultSelected
Данное свойство содержит логическое значение, которое определяет, должен ли
объект O p t i o n быть выбран по умолчанию. Свойство d e f a u l t S e l e c t e d задается
посредством атрибута SELECTED и предназначено только для чтения.
index
Это свойство, предназначенное только для чтения, определяет позицию объекта
O p t i o n в массиве o p t i o n s объекта S e l e c t .
selected
Данное свойство содержит логическое значение, указывающее, выбран ли в дан
ный момент пункт, соответствующий объекту. Свойство s e l e c t e d доступно как
для чтения, так и для записи.
text
Свойство t e x t содержит текст, соответствующий пункту элемента SELECT. Дан
ное свойство допускает как чтение, так и запись.
value
Д а н н о е свойство содержит значение, которое при активизации ф о р м ы вместе с
именем объекта S e l e c t передается программе на стороне сервера. Первоначаль
но это свойство задается посредством атрибута VALUE и доступно как для чтения,
так и для записи.
Методы
Методы отсутствуют.
Обработчики событий
Обработчики событий отсутствуют. Обработчики o n b l u r , o n f o c u s и o n c h a n g e
связываются не с объектами O p t i o n , а с объектом S e l e c t .
Свойства
defaultValue
Данное свойство, предназначенное только для чтения, содержит значение, пер
воначально задаваемое посредством атрибута VALUE.
form
Свойство f o r m предоставляет доступ к объекту Form, содержащему поле ввода па
роля. Это свойство предназначено только для чтения.
name
Свойство name доступно только для чтения и содержит значение атриб)а'а NAME.
type
Данное свойство предназначено только для чтения и содержит значение
password.
value
Значение данного свойства совпадает со строкой текста, содержащейся в поле
ввода пароля. Звездочки, отображаемые в поле в системе UNIX и некоторых дру
гих системах, позволяют определить число символов, введенных пользователем,
но не сами символы.
Методы
blurO
В результате выполнения данного метода элемент теряет фокус ввода.
focus()
в результате выполнения данного метода элемент получает фокус ввода.
select()
Этот метод вызывает выделение текста в составе элемента. Символ, введенный
пользователем, заменяет весь выделенный текст.
Обработчики событий
onblurO
Данный метод вызывается тогда, когда поле ввода пароля т е р я е т фокус ввода.
Этот метод определяется с помощью атрибута o n B l u r .
onchange()
Для того чтобы метод o n c h a n g e получил управление, надо чтобы поле ввода па
роля потеряло фокус после изменения значения, содержащегося в поле. Данный
метод определяется посредством атрибута o n C h a n g e .
25.25. Объею* Plugin 1217
onfocus()
Д а н н ы й метод вызывается тогда, когда поле ввода пароля получает фокус ввода.
Этот метод определяется с помощью атрибута on F o c u s .
onkeydown()
Этот метод вызывается после первого нажатия пользователем клавиши, когда по
ле ввода пароля имеет фокус ввода. Если onkeydown возвращает значение f a l s e ,
символ не вводится.
onkeypress()
П р и первом нажатии клавиши пользователем обработчик o n k e y p r e s s вызывает
ся после onkeydown. П р и последующих нажатиях клавиш o n k e y p r e s s вызывает
ся, а o n k e y d o w n — нет. Если обработчик o n k e y p r e s s возвращает значение f a l s e ,
символ не вводится.
onkeyupO
Обработчик o n k e y u p вызывается тогда, когда пользователь отпускает клавишу.
Свойства
description
Д а н н о е свойство, предназначенное только для чтения, содержит текст, описы
вающий дополнительный модуль.
filename
Значением свойства f i l e n a m e является имя файла, содержащего код дополни
тельного модуля. Данное свойство доступно только для чтения.
, length
Свойство l e n g t h определяет число объектов MimeType в массиве.
name
Д а н н о е свойство содержит краткое имя дополнительного модуля. Такие имена
можно использовать в качестве индексов при обращении к элементам массива
document.plugins.
1218 Глава 25. Краткое руководство по JavaScript
Методы
Методы отсутствуют.
Обработчики событий
Обработчики событий отсутствуют. Объект P l u g i n не соответствует ни одному из
HTML-элементов.
Свойства
checked
Данное свойство, содержит логическое значение, определяющее, выбран ли в
данный момент переключатель опции. Свойство c h e c k e d допускает как чтение,
так и запись.
defaultChecked
Свойство d e f a u l t C h e c k e d содержит логическое значение, определяющее, дол
жен ли переключатель быть выбран первоначально. Данное свойство устанавли
вается с помощью атрибута CHECKED и доступно только для чтения.
form
Данное свойство, предназначенное только для чтения, ссылается на объект Form,
содержащий переключатель опций.
name
Свойство name содержит имя элемента и устанавливается с помощью атрибута
NAME. Заметьте, что группа переключателей опций идентифицируется одним име
нем и в группе может быть выбран только один элемент. Данное свойство предна
значено только для чтения.
type
Данное свойство содержит значение r a d i o . Поскольку все объекты E l e m e n t
имеют свойство t y p e , оно может быть использовано для идентификации типа
элементов, содержащихся в массиве f o r m . e l e m e n t s . Свойство t y p e доступно
только для чтения.
25.27. Объект RegExp 1219
value
Если переключатель выбран, значение свойства v a l u e передается вместе с име
нем элемента CGI-программе на стороне сервера. Данное свойство доступно как
для чтения, так и для записи.
Методы
blurO
В результате выполнения данного метода элемент теряет фокус ввода.
clickO
П р и вызове данного метода выполняются те же действия, что и по щелчку мышью
на переключателе, но событие o n C l i c k не генерируется. Выполнение метода
c l i c k дает те же результаты, что и установка свойства c h e c k e d .
focus()
В результате выполнения данного метода элемент получает фокус ввода.
Обработчики событий
onblurO
Обработчик o n b l u r вызывается тогда, когда переключатель т е р я е т фокус ввода.
Этот метод определяется с помощью атрибута o n B l u r , как показано ниже.
<INPUT TYPE="RADIO" . . .
onBlur="doSomeAction()">
onclickO
Данный метод получает управление после щелчка мышью на переключателе оп
ций, но не в результате выполнения метода c l i c k . Обработчик o n c l i c k опреде
ляется посредством атрибута o n C l i c k .
onfocus()
Обработчик o n f e c u s вызывается тогда, когда переключатель опции получает фо
кус ввода. Этот обработчик устанавливается посредством атрибута o n F o c u s .
Конструкторы
n e w RegExpC'pattern")
Д а н н ы й конструктор создает регулярное выражение. Регулярное выражение — это
строка, содержащая н е к о т о р ы е специальные символы, используемые для обозна-
1220 Глава 25. Краткое руководство по JavaScript
чения фрагментов текста (см. табл. 15.1). Наиболее важными из них являются +
(одно или более вхождений предыдущего символа), * (любое, в том числе нулевое
количество вхождений предыдущего символа) и ? (необязательное вхождение
предыдущего символа). П р и отсутствии специальных символов установление со
ответствия регулярному выражению сводится к обычному сравнению строк. На
пример, представленное ниже регулярное выражение означает следующее:
"символ 'z', за ним следует один либо более символов 'а', далее символ Ъ ' , сопро
вождаемый любым (в том числе нулевым) количеством символов 'с', затем необя
зательный символ 'd', после которого следует символ 'е'".
var re = new RegExp("za+bc*d?e");
В состав объекта RegExp входит метод t e s t , к о т о р ы й читает строку и возвращает
значение t r u e только в том случае, если строка содержит регулярное вырг1жение.
П р и н и м а я во Внимание! приведенное выше определение r e , можно сделать вы
вод, что в результате следующих вызовов метода t e s t будет получено значение
true:
re.test("zabcde");
re.test("xxxxxzabcdexxxxx");
re.test("zaaaabcde") ;
re.test("zaaaabde") ;
re.test("zaaaabe");
re.test("XXzaabcccccdeYY") ;
n e w RegExpC'pattern", "g")
Д а н н ы й конструктор создает регулярное выражение, предназначенное для гло
бального поиска в строке. В объекте S t r i n g определен метод m a t c h , который
возвращает массив, содержащий фрагменты текста, соответствующие регулярно
му выражению. Если параметр "g" не указан, возвращается первый фрагмент, со
ответствующий выражению. Н и ж е приведен фрагмент кода, демонстрирующий
использование рассматриваемого конструктора и метода m a t c h объекта S t r i n g .
П р и первом вызове метода m a t c h возвращается массив, содержащий последова
тельность символов " а Ь с " , при втором вызове — массив, содержащий последова
тельности " а Ь с " и " a b b b b c " .
var str = "abcabbbbcABCABBBBC";
var rel = new RegExp("ab+c");
var re2 = new RegExp ("ab-t-c", " g " ) ;
var resultl = str.match(rel);
var result2 = str.match(re2);
n e w RegExpC'pattern", "i")
Этот конструктор создает регулярное выражение для проверки без учета регистра
символов.
n e w RegExpC'pattern", "gi")
Данный конструктор создает регулярное выражение для глобального поиска без
учета регистра символов. Например, в результате выполнения приведенного ниже
25.27. Объект RegExp 1221
/pattern/
Указанное выражение представляет собой сокращенную запись конструктора new
RegExp ( " p a t t e r n " ). Например, следующие две строки кода создают одинаковые
регулярные выражения:
var rel = /ab+c/;
var ге2 = new RegExp("ab+c");
Соответствующие примеры будут рассмотрены в разделе 25.31.
/pattern/g
Данное выражение представляет собой сокращенную запись конструктора new
RegExp ( " p a t t e r n " , ' ' g " ) .
/pattern/i
Данное выражение представляет собой сокращенную запись конструктора new
RegExp ( ' ' p a t t e r n " , ' ' i " ) .
/pattern/gi
Данное выражение представляет собой сокращенную запись конструктора new
RegExp ( ' ' p a t t e r n " , " g i " ) .
Свойства
Описанные ниже свойства принадлежат объекту RegExp, а не конкретному регу
лярному выражению. Для доступа к свойству используется выражение RegExp.
propertyName, где propertyName — имя свойства. Сокращенные имена свойств ($_,
$* и т.д.) привычны для программистов, имеющих опыт работы на языке Perl.
input
$_
Если метод exec или t e s t регулярного выражения вызывается без указания строки,
используется значение данного свойства. При выполнении обработчиков событий
для объектов Text, TextArea, S e l e c t и Link это свойство автоматически заполня
ется текстом. Рассматриваемое свойство допускает как чтение, так и запись.
lastMatch
$8с
Данное свойство содержит последнюю подстроку, соответствующую регулярному
выражению. Это свойство предназначено только для чтения и получает значение
после вызова метода exec.
1222 Глава 25. Краткое руководство по JavaScript
lastParen
$+
Значением данного свойства, предназначенного только для чтения, является по
следний фрагмент текста, соответствующий регулярному выражению в скобках.
Это свойство заполняется после вызова метода e x e c .
leftContext
$^
Это свойство содержит часть строки, которая предшествует последнему фрагмен
ту, соответствующему регулярному выражению. Сам фрагмент в состав данного
свойства не включается. Свойство l e f t C o n t e x t ($ ) предназначено только для
чтения и заполняется после вызова метода e x e c .
multiline
$*
Данное свойство содержит логическое значение, которое определяет, может ли
проверка на соответствие регулярному выражению продолжаться после появле
ния символа новой строки. Это свойство допускает как чтение, так и запись и
должно быть установлено перед вызовом метода e x e c . П р и вызове обработчиков
событий текстовой области данному свойству автоматически присваивается зна
чение t r u e .
rightcontext
$'
Это свойство содержит правую часть строки, которая следует после последнего
фрагмента, соответствующего регулярному выражению. Данное свойство доступ
но только для чтения и заполняется после вызова метода e x e c .
$1
$2
$9
Указанные свойства содержат первые девять фрагментов, соответствующих регу
л я р н ы м выражениям в скобках. О н и предназначены только для чтения и запол
няются после вызова метода e x e c .
Методы
Д а н н ы е методы принадлежат не объекту RegExp, а конкретным регулярным вы
ражениям.
compile(pattern, flags)
Д а н н ы й метод компилирует регулярное выражение для повышения эффективно
сти работы.
2 5 . 2 7 . Объект RegExp 1223
exec(string)
Метод e x e c п р о в е р я е т указанную строку (параметр s t r i n g ) на соответствие регу
лярному выражению и заполняет описанные ранее свойства объекта RegExp. П р и
написании сценария вы можете не указывать имя метода, т.е. вызывать
s o m e R e g E x p ( s t r i n g ) вместо s o m e R e g E x p . e x e c ( s t r i n g ) .
exec()
Этот метод выполняет те же действия, что и вызов e x e c ( R e g E x p . i n p u t ) .
test(string)
Данный метод определяет, содержит ли заданная строка (параметр s t r i n g ) регу
л я р н о е выражение и, в зависимости от результатов проверки, возвращает значе
ние t r u e или f a l s e . Вызов s o m e R e g E x p . t e s t ( s t r i n g ) дает те же результаты,
что и вызов метода s t r i n g , s e a r c h ( s o m e R e g E x p ) .
Обработчики событий
Обработчики событий отсутствуют. Объект RegExp не соответствует ни одному из
HTML-элементов.
\ S;, \ S Обозначает пробел или символ, используемый вместо него для раз
деления слов ( \ s ) , и символ, не являющийся таковым. (\S). Конст
рукция \ s эквивалентна [ \ f \ n \ r \ t \ v ] , a \ S - - [^\f \ n \ r \ t \ v ]
Свойства
form
Данное свойство, предназначенное только для чтения, обеспечивает доступ к объ
екту Form, содержащему кнопку RESET.
type
Данное свойство имеет значение r e s e t . Свойство t y p e содержат все объекты
E l e m e n t , поэтому о н о может быть использовано для идентификации типа объек
та. Данное свойство предназначено только для чтения.
value
Значение свойства v a l u e определяет надпись на кнопке. Свойство v a l u e допус
кает как чтение, так и запись.
Методы
blurO
В результате выполнения данного метода кнопка RESET теряет фокус ввода.
clickO
В результате вызова данного метода выполняются те же действия, что и после
щелчка на кнопке RESET, однако событие o n C l i c k не генерируется. Вместо мето
да c l i c k можно вызвать метод r e s e t ф о р м ы .
1226 Глава 25. Краткое руководство по JavaScript
Обработчики событий
onblur()
Д а н н ы й метод вызывается тогда, когда кнопка RESET т е р я е т фокус ввода. Обра
ботчик o n b l u r задается посредством атрибута o n B l u r .
<INPUT TYPE="RESET" . . .
onBlur="doSomeAction()">
onclick()
Обработчик o n c l i c k вызывается тогда, когда пользователь щелкает мышью на кнопке
RESET. При вызове метода c l i c k обработчик не получает управления. Обычно дан
ный метод определяется с помощью атрибута o n C l i c k , как показано ниже.
<INPUT TYPE="RESET" . . .
onClick="doSomeAction()">
Если метод o n c l i c k возвращает значение f a l s e , сброс ф о р м ы не производится.
Например:
<INPUT TYPE="RESET" . . .
onClick="return(maybeReset())">
ondblclickO
Этот метод вызывается после двойного щелчка мышью на кнопке. После первого
щелчка вызывается метод o n c l i c k . Обработчик задается посредством атрибута
o n D b l C l i c k . Д а н н ы й обработчик не поддерживается Macintosh и Netscape 6.
onfocus()
Метод on f o c u s вызывается тогда, когда кнопка RESET получает фокус ввода. Для
определения данного метода используется атрибут on F o c u s .
Свойства
availHeight
Данное свойство, предназначенное только для чтения, содержит высоту экрана (в
пикселях) за вычетом области, занимаемой постоянными и н т е р ф е й с н ы м и эле
ментами, такими как панель задач Windows 98.
2 5 . 3 0 . Объект Select 1227
availWidth
Данное свойство, предназначенное только для чтения, содержит ширину экрана
(в пикселях) за вычетом области, занимаемой постоянными интерфейсными эле
ментами.
colorDepth
Свойство c o l o r D e p t h содержит число цветов, которые могут отображаться одно
временно. Д а н н о е свойство доступно только для чтения.
height
Свойство h e i g h t , доступное только для чтения, содержит высоту экрана в пикселях.
width
Свойство w i d t h , доступное только для чтения, содержит ширину экрана в пикселях.
pixelDepth
Данное свойство определяет число битов, используемых для отображения цвета
одного пикселя. Свойство p i x e l D e p t h предназначено только для чтения.
Методы
Методы отсутствуют.
Обработчики событий
Обработчики событий отсутствуют. Объект S c r e e n не соответствует ни одному из
HTML-элементов.
Листинг 25.4.SelectColor.html
function setBackgroundColor() {
var selection = document.colorForm.colorSelection;
document.bgColor =
selection.options[selection.selectedlndex].value;
}
// — >
</SCRIPT>
</HEAD>
<BODY BGCOLOR="WHITE">
<Hl>Changing the Background Color</Hl>
<FORM NAME="colorForm">
<SELECT NAME="colorSelection"
onChange="setBackgroundColor ()">
<OPTION VALUE="#FFFFFF" SELECTED>White
<OPTION VALUE="#COCOCO">Gray
<OPTION VALUE="#FFOOOO">Red
.<OPTION VALUE="#OOFFOO">Green
<OPTION VALUE="#OOOOFF">Blue
</SELECT>
</FORM>
</BODY>
</HTML>
Свойства
form
Данное свойство ссылается на объект Form, содержащий элемент SELECT. Свойст
во f o r m доступно только для чтения.
length
Свойство l e n g t h , предназначенное только для чтения, содержит данные о числе
элементов O p t i o n , находящихся в составе объекта SELECT. З н а ч е н и е l e n g t h сов
падает со значением свойства o p t i o n s . l e n g t h .
name
Свойство name содержит имя, определяемое посредством атрибута NAME. Данное
свойство доступно только для чтения.
2 5 . 3 0 . Объект Select 1229
options
Свойство o p t i o n s предоставляет доступ к массиву объектов Option, содержащихся
в объекте S e l e c t . Новые объекты Option можно помещать в конец массива.
selectedlndex
Свойство s e l e c t e d l n d e x содержит индекс выбранного пункта. Если ни один из
пунктов не выбран, значение свойства равно -1. Если при создании элемента
SELECT был указан атрибут MULTIPLE, значением данного свойства является ин
декс первого из выбранных пунктов. Свойство s e l e c t e d l n d e x допускает как чте
ние, так и запись.
type
В зависимости от того, был ли указан при создании элемента атрибут MULTIPLE,
свойство t y p e содержит либо значение s e l e c t - o n e , либо значение s e l e c t -
m u l t i p l e . Это свойство доступно только для чтения.
Методы
blurO
В результате выполнения данного метода элемент SELECT теряет фокус ввода.
focus()
в результате выполнения метода focus элемент SELECT получает фокус ввода.
Обработчики событий
onblurO
Данный обработчик получает управление тогда, когда элемент теряет фокус ввода.
Обычно метод o n b l u r определяется посредством атрибута onBlur, как показано
ниже.
<SELECT . . . onBlur="doSomeAction()">
onchange()
Метод onchange получает управление, если элемент теряет фокус ввода после из
менения его значения. Пример использования данного обработчика приведен в
листинге 25.4.
onfocus()
Метод onf OCUS вызывается тогда, когда элемент получает фокус ввода. Для опре
деления данного обработчика используется атрибут onFocus.
1230 Глава 25. Краткое руководство по JavaScript
2 5 . 3 1 . Объект String
Объект S t r i n g чрезвычайно важен. Он не соответствует ни одному из HTML-
элементов, но очень часто используется в JavaScript-сценариях.
Конструктор
new String(value)
Данный конструктор создает новый объект S t r i n g .
Свойства
length
Данное свойство, предназначенное только для чтения, определяет число симво
лов в строке.
Методы
anchor(name)
Метод anchor возвращает копию текущей строки, помещенную между дескрипто
рами <А NAME="name"> и </А>. Например, выражение
"Chapter One".anchor("Chi")
эквивалентно следующему:
'<А NAME="Chl">Chapter One</A>'
bigO
Данный метод возвращает копию текущей строки, помещенную между дескрипто
рами <BIG> и </BIG>.
blinkO
Данный метод возвращает копию текущей строки, помещенную между дескрипто
рами <BLINK> и </BLINK>.
boldO
Метод b o l d возвращает копию текущей строки, помещенную между дескриптора
ми <В> и </В>. Например, выражение
"Wow".italics () . b o l d O
эквивалентно следующему:
"<B><I>Wow</I></B>"
charAt(index)
Метод c h a r At возвращает строку, состоящую из одного символа, расположенного
в указанной позиции текущей строки. Подобно большинству типов данных в
JavaScript, отсчет символов начинается с нуля.
2 5 . 3 1 . Объект String 1231
charCodeAt()
charCodeAt(index)
Вызов первого метода эквивалентен вызову charCodeAt (О). Второй метод воз
вращает код ISO Latin-1 символа, находящегося в указанной позиции строки. Пер
вые 127 значений соответствуют ASCII-кодам.
concat(suffixString)
Данный метод предназначен для конкатенации двух строк. Следующие два выра
жения эквивалентны:
var newString = stringl.concat(string2);
var newString = stringl + string2;
escape(stri]ig)
Ha самом деле e s c a p e не метод S t r i n g , a функция верхнего уровня. Однако, по
скольку e s c a p e используется при работе со строками, ее описание приведено
здесь. Эта функция выполняет URL-кодирование строки символов. В результате
строка приобретает формат, в котором она может быть передана на сервер в со
ставе URL. Заметьте, что в данном случае пробел заменяется не символом "+", а
последовательностью "%20". На рис. 25.5 показан результат выполнения приве
денного ниже выражения.
alert(escape("Hello, world!"));
fixedO
Данный метод возвращает копию строки, помещенную между дескрипторами
<ТТ>и</ТТ>.
fontcolor(colorName)
Метод f o n t c o l o r возвращает копию строки, помещенную между дескрипторами
<FONT COLOR="colorName"> и </FONT>.
fontsize(size)
Данный метод возвращает копию строки, помещенную между дескрипторами
<FONT SIZE=/?^^^>H</FONT>.
1232 Глава 25. Краткое руководство по JavaScript
fromCharCode(codeO, c o d e l , . . . , c o d e N )
Д а н н ы й метод создает строку, содержащую заданные символы ISO Latin-1. Этот
метод скорее можно отнести к конструкторам объекта S t r i n g . О н вызывается с
помощью выражения S t r i n g . f r o m C h a r C o d e ( . . . ) . Н а п р и м е р , приведенный
ниже код присваивает переменной h e l l o S t r i n g значение HELLO.
var helloString =
String.fromCharCode(72, 69, 76, 76, 79);
indexOf(substring)
indexOf(substring, startlndex)
Если заданная подстрока содержится в составе строки, первый из приведенных
методов возвращает индекс первого символа подстроки в строке. Если подстрока в
строке отсутствует, возвращается значение -1. Например, следующая функция воз
вращает t r u e в случае, если вторая строка содержится в первой:
function contains(string, possibleSubstring) {
return(string.substring(possibleSubstring) != - 1 ) ;
}
Второй метод отличается от первого тем, что поиск указанной подстроки начина
ется с заданного индекса. В результате выполнения метода возвращается индекс
первого вхождения относительно начала строки, а не относительно позиции
startlndex.
italics()
Данный метод возвращает копию строки, помещенную между дескрипторами <1>
и</1>.
lastIndexOf(substring)
lastIndexOf(substring, startlndex)
Если заданная строка входит в состав текущей строки, первый из указанных мето
дов возвращает индекс начала последнего вхождения, в противном случае возвра
щается значение -1. Второй метод отличается от первого тем, что поиск вхожде
ния строки начинается с индекса, заданного с помощью второго параметра.
link(url)
Данный метод возвращает копию строки, помещенную между дескрипторами <А
HREF="url">H</A>.
match(regExp)
Данный метод возвращает массив, элементами которого являются фрагменты те
кущей строки, соответствующие регулярному выражению, указанному в качестве
параметра m a t c h . Н а п р и м е р , в результате выполнения следующего кода будет
сформирован массив, содержащий строки "аЬс", " a b b b b c " , "ABC" и "АВВВВС".
v a r s t r = "abcabbbbcABCABBBBC";
var re = /ab+c/gi;
var r e s u l t = s t r . m a t c h ( r e ) ;
2 5 . 3 1 . Объект String 1233
Поскольку символ "g" в r e означает поиск по всей строке, а " i " — поиск без учета
регистра, регулярное выражение интерпретируется таким образом: "найти все
вхождения подстроки, состоящей из символа 'а' или 'А', за которым следует один
или более символов Ъ ' или *В', а затем расположен символ 'с' или ' С ". Подробно
о регулярных выражениях см, в разделе 25.27.
replace(regExp5 replacementString)
Метод r e p l a c e возвращает новую строку, сформированную путем замены всех
фрагментов, соответствующих регулярному выражению, указанной строкой. Если
при создании регулярного выражения был задан символ "д", то замене подлежат
все последовательности, соответствующие этому выражению. Например, в резуль
тате выполнения приведенного ниже фрагмента кода будет сгенерирована строка
"We will use Java, Java, and Java".
var str = "We will use C, C++, and Java.";
var re = /C\+*/g;
var r e s u l t = s t r . r e p l a c e ( r e , "Java");
search(regExp)
Д а н н ы й метод возвращает значение t r u e или f a l s e , в зависимости от того, со
держится ли в текущей строке подстрока, соответствующая регулярному выраже
нию г е д Е х р . Если вас интересует только сам факт соответствия регулярному вы
ражению, метод s e a r c h предпочтительнее метода m a t c h .
slice(startlndex, endlndex)
Если второй параметр представляет собой положительное число, метод s l i c e ра
ботает т о ч н о так же, как и метод s u b s t r i n g . Однако в качестве второго парамет
ра вы можете задать отрицательное число. Такое значение будет интерпретиро
ваться как смещение от конца строки. Н и ж е приведено несколько примеров ис
пользования метода s l i c e .
var s t r = "0123456789";
var str2 = str.sliced, 5 ) ; // "1234"
var str3 = str.substring(1, 5 ) ; // "1234"
var str4 = str.sliced, - 2 ) ; // "1234567"
small()
Данный метод возвращает копию строки, помещенную между дескрипторами
<SMALL> и </SMALL>.
splitO
Метод s p l i t возвращает массив, содержащий текущую строку. В таком виде метод
вряд ли пригоден. Ч т о б ы метод s p l i t выполнял полезные действия, надо при его
вызове указывать символ-ограничитель.
1234 Глава 25. Краткое руководство по JavaScript
split(delimChar)
Данный метод возвращает массив, сформированный путем разбиения текущей
строки на подстроки. Признаком окончания очередной подстроки является сим
вол-разделитель delimChar в составе текущей строки. Например, в результате
выполнения следующего выражения будет сформирован массив, содержащий
строки "f со", "bar" и "baz" (в указанном порядке):
var t e s t = " f o o , b a r , b a z " . s p l i t ( " , " ) ;
Если в качестве символа-разделителя указан пробел, то подстроки могут разде
ляться любым числом пробелов, символов табуляции и перевода строки. Метод
s p l i t выполняет действия, обратные методу j o i n объекта Array.
split(regExp)
В этом варианте метода s p l i t используется подстрока-разделитель, заданная с
помощью регулярного выражения. Например, при выполнении приведенного
ниже фрагмента кода будет создан массив из трех элементов, содержащий строки
"f со", "bar" и "baz" (в указанном порядке).
var s t r = " f o o , b a r , , , , , , b a z " ;
var re = / , + / ;
var r e s u l t = s t r . s p l i t ( r e ) ;
split(separator, limit)
Данный метод создает массив, число элементов которого не превышает значения
l i m i t . В качестве первого параметра может быть задан символ-разделитель либо
объект RegExp.
strike()
Данный метод возвращает копию строки, помещенную между дескрипторами
<STRIKE> и </STRIKE>.
sub()
Данный метод возвращает копию строки, помещенную между дескрипторами
<SUB>H</SUB>.
substr(startlndex, numChars)
Метод s u b s t г возвращает подстроку текущей строки длиной numChars, начи
нающуюся с индекса s t a r t Index.
substring(startlndex, endlndex)
Данный метод возвращает новую строку, в которую входят символы текущей стро
ки, начиная с индекса s t a r t Index и заканчивая индексом e n d l n d e x (символ, на
который указывает s t a r t Index, принадлежит, а символ, на который указывает
endlndex, — не принадлежит подстроке). В следующем примере переменной t e s t
присваивается строка " i s " :
var t e s t = " t h i s i s a t e s t " . s u b s t r i n g ( 5 , 7);
2 5 . 3 2 . Объект Submit 1235
supO
Данный метод возвращает копию строки, помещенную между дескрипторами <SUP>
H</SUP>.
toLowerCase()
Метод t o L o w e r C a s e возвращает копию текущей строки, символы которой преоб
разованы в нижний регистр.
toUpperCase()
Метод t o U p p e r C a s e возвращает копию текущей строки, символы которой преоб
разованы в верхний регистр.
unescape(string)
В действительности u n e s c a p e — не метод объекта S t r i n g , а функция верхнего
уровня. Однако, поскольку u n e s c a p e используется для работы со строками, мы
рассматриваем ее здесь. Функция u n e s c a p e выполняет URL-декодирование стро
ки. Данная функция имеет недостаток: она не преобразует символ "+" в пробел.
Обработчики событий
Обработчики событий отсутствуют. Объект S t r i n g не соответствует ни одному из
HTML-элементов.
Свойства
form
Данное свойство, предназначенное только для чтения, обеспечивает доступ к объ
екту Form, содержащему кнопку SUBMIT.
name
Если п р и создании кнопки SUBMIT был задан атрибут NAME, значение атрибута
присваивается данному свойству. Свойство name доступно только для чтения.
type
Данное свойство имеет значение s u b m i t . Поскольку свойство t y p e принадлежит
всем объектам E l e m e n t , OHQ может использоваться для идентификации типа эле
мента. Свойство t y p e предназначено только для чтения.
1236 Глава 25. Краткое руководство по JavaScript
value
Значение свойства v a l u e определяет надпись на кнопке. Д а н н о е свойство допус
кает как чтение, так и запись.
Методы
blurO
В результате выполнения данного метода кнопка SUBMIT т е р я е т фокус ввода.
clickO
П р и вызове данного метода выполняются те же действия, что и после щелчка на
кнопке SUBMIT, но событие o n C l i c k не генерируется. Вместо метода c l i c k мож
но вызывать метод s u b m i t ф о р м ы .
focus()
в результате выполнения данного метода кнопка SUBMIT получает фокус ввода.
Обработчики событий
onblur()
Данный метод вызывается тогда, когда кнопка SUBMIT т е р я е т фокус ввода. Обра
ботчик o n b l u r определяется посредством атрибута o n B l u r , как показано ниже.
<INPUT TYPE="SUBMIT" ... onBlur="doSomeAction()">
onclick()
Метод o n c l i c k вызывается тогда, когда пользователь щелкает мышью на кнопке
SUBMIT. П р и вызове метода c l i c k метод o n c l i c k управления не получает. Дан
ный обработчик определяется с помощью атрибута o n C l i c k .
<INPUT TYPE="SUBMIT" ... onClick="doSomeAction()">
Если метод o n c l i c k возвращает значение f a l s e , данные ф о р м ы не передаются
программе на стороне сервера. Например:
<INPUT TYPE="SUBMIT" . . . onClick="return(maybeSubmit())">
Аналогичный результат можно получить с помощью обработчика o n S u b m i t фор
мы, содержащей кнопку.
ondblclick()
Данный метод вызывается после двойного щелчка мышью на кнопке. После пер
вого щелчка вызывается метод o n c l i c k . Обработчик o n d b l c l i c k задается по
средством атрибута o n D b l C l i c k . Этот обработчик не поддерживается Macintosh и
Netscape 6.
25.33. Объект Text 1237
onfocus()
Данный обработчик вызывается тогда, когда кнопка SUBMIT получает фокус ввода.
Он определяется посредством атрибута on F o c u s .
Свойства
defaultValue
Свойство d e f a u l t V a l u e содержит исходное содержимое поля редактирования,
заданное посредством атриб)п^а VALUE.
form
Данное свойство, предназначенное только для чтения, обеспечивает доступ к объ
екту Form, содержащем)' поле редактирования.
name
Значение данного свойства соответствует значению атрибута NAME элемента. Это
свойство доступно только для чтения.
type
Свойство t y p e , предназначенное только для чтения, содержит значение t e x t .
value
Значение данного свойства соответствует тексту, содержащемуся в поле редакти
рования. Свойство v a l u e допускает как чтение, так и запись.
Методы
blurO
В результате выполнения данного метода поле редактирования теряет фокус ввода.
focus()
в результате выполнения метода f o c u s поле редактирования получает фок)'с ввода.
selectO
Д а н н ы й метод выделяет текст в поле редактирования. Любой символ, введенный
пользователем, замещает выделенный текст.
1238 Глава 25. Краткое руководство по JavaScript
Обработчики событий
onblurO
Данный метод получает управление тогда, когда поле редактирования теряет фо
кус ввода. О н определяется посредством атрибу1^а o n B l u r .
onchange()
Для того чтобы метод o n c h a n g e получил управление, надо чтобы поле редактиро
вания потеряло фокус ввода после изменения его содержимого. Д а н н ы й обработ
чик определяется посредством атрибута o n C h a n g e .
onfocus()
Данный обработчик вызывается тогда, когда поле редактирования получает фокус
ввода. Метод o n f e c u s определяется с помощью атрибута o n F o c u s .
onkeydownO
Этот метод вызывается после первого нажатия клавиши в тот момент, когда поле
редактирования имеет фокус ввода. Если o n k e y d o w n возвращает значение f a l s e ,
символ не вводится. Наличие обработчика o n k e y d o w n позволяет контролировать
вводимый текст.
onkeypress()
П р и первом нажатии клавиши пользователем обработчик o n k e y p r e s s вызывает
ся после o n k e y d o w n . П р и последующих нажатиях клавиш o n k e y p r e s s вызывает
ся, а o n k e y d o w n — нет. Если обработчик o n k e y p r e s s возвращает значение f a l s e ,
символ не вводится.
onkeyupO
Обработчик o n k e y u p вызывается тогда, когда пользователь отпускает клавишу.
Свойства
defaultValue
Свойство d e f a u l t V a l u e соответствует начальному значению текстовой области,
т.е. содержит текст, находящийся между дескрипторами <TEXTAREA> и
</TEXT ARE А>. Это свойство доступно только для чтения.
25.34. Объект Textarea 1239
form
Данное свойство, предназначенное только для чтения, обеспечивает доступ к объ
екту Form, содержащему текстовую область.
name
Свойство name соответствует значению атрибута NAME. Это свойство доступно
только для чтения.
type
Свойство t y p e предназначено только для чтения и содержит значение t e x t a r e a .
value
Значением свойства v a l u e является текст, содержащийся в данный момент в со
ставе элемента. Это свойство допускает как чтение, так и запись, но поскольку оп
ределить число строк и столбцов рассматриваемого элемента невозможно, помес
тить в текстовую область корректно сформированный текст достаточно сложно.
Методы
blurO
В результате выполнения данного метода текстовая область теряет фокус ввода.
focus()
в результате выполнения метода focus текстовая область получает фокус ввода.
select()
Данный метод выделяет текст в области. Любой символ, введенный пользовате
лем, замещает выделенный текст.
Обработчики событий
onblur()
Данный метод получает управление тогда, когда текстовая область теряет фокус
ввода. Он определяется посредством атрибута onBlur.
onchange()
Метод onchange получает управление при потере текстовой областью фокуса
ввода после изменения ее содержимого. Данный обработчик определяется по
средством атрибута onChange.
onfocus()
Данный обработчик вызывается тогда, когда текстовая область получает фокус
ввода. Метод on focus определяется с помощью атрибута on Focus.
1240 Глава 25. Краткое руководство по JavaScript
onkeydown()
Этот метод вызывается после первого нажатия клавиши в тот момент, когда тексто
вая область имеет фокус ввода. Если onkeydown возвращает значение f a l s e , символ
не вводится. Обработчик onkeydown позволяет контролировать вводимый текст.
onkeypress()
П р и первом нажатии клавиши пользователем обработчик on k e y p r e s s вызывает
ся после o n k e y d o w n . П р и последующих нажатиях клавиш o n k e y p r e s s вызывает
ся, а o n k e y d o w n не вызывается. Если обработчик o n k e y p r e s s возвращает значе
ние f a l s e , символ не вводится.
onkeyupO
Обработчик o n k e y u p вызывается тогда, когда пользователь отпускает клавишу.
Свойства
closed
Данное свойство содержит логическое значение, определяющее, было ли закрыто
окно. Свойство c l o s e d доступно только для чтения.
defaultStatus
Свойство d e f a u l t S t a t u s определяет строку, которая должна по умолчанию ото
бражаться в строке состояния. Это свойство допускает как чтение, так и запись.
document
Данное свойство ссылается на объект D o c u m e n t , содержащийся в окне. Подробно
об объекте Document см. в разделе 25.5. Свойство d o c u m e n t предназначено толь
ко для чтения.
frames
Свойство f r a m e s обеспечивает доступ к массиву, состоящему из элементов
Window. Каждый из элементов массива соответствует фрейм)' текущего документа.
25.35. Объект Window 1241
history
Данное свойство содержит объект H i s t o r y , связанный с текущим окном. Свойст
во h i s t o r y доступно только для чтения.
innerHeight
Свойство i n n e r H e i g h t соответствует вертикальной составляющей внутреннего
размера окна. Это свойство допускает как чтение, так и запись. Изменение значе
ния свойства приводит к изменению размеров окна.
innerWidth
Свойство innerWidth соответствует горизонтальной составляющей внутреннего
размера окна. Это свойство допускает как чтение, так и запись. Изменение значе
ния свойства приводит к изменению размеров окна. Пример использования дан
ного свойства см. в разделе 24.4.
Java
Данное свойство ссылается на объект Java Package, соответствующий верхнему
уровню иерархии пакетов j ava . *. Используя это свойство, вы можете, например,
обращаться к генератору псевдослучайных чисел посредством выражения
J a v a . l a n g . M a t h , random() или выводить данные в окно Java Console с помо
щью выражения Java . l a n g . System, o u t . p r i n t l n . Свойство Java предназначе
но только для чтения.
length
Данное свойство доступно только для чтения и означает то же, что и frames . l e n g t h .
location
Свойство l o c a t i o n ссылается на объект L o c a t i o n , содержащий URL, указанный
в составе запроса. Вследствие перенаправления он может отличаться от реального
URL, который является значением свойства document. URL. Свойство l o c a t i o n
допускает как чтение, так и запись. Изменение его значения приводит к отобра
жению нового документа.
locationbar
В броузере Netscape подписанные сценарии могут устанавливать свойство
v i s i b l e l o c a t i o n b a r , что позволяет скрыть или отобразить поле L o c a t i o n .
Допустимыми значениями являются t r u e (либо 1) и f a l s e (либо 0).
Math
Данное свойство ссылается на объект Math.
menubar
В броузере Netscape подписанные сценарии могут устанавливать свойство
v i s i b l e menubar, что позволяет скрыть или отобразить полосу меню. Допусти
мыми значениями являются t r u e (либо 1) и f a l s e (либо 0).
1242 Глава 25. Краткое руководство по JavaScript
name
П р и создании окна вы можете задать его имя. Имя окна является значением свой
ства name. Это свойство предназначено как для чтения, так и для записи.
navigator
Данное свойство, предназначенное как для чтения, так и для записи, содержит
ссылку на объект N a v i g a t o r .
netscape
Свойство n e t s c a p e содержит ссылку на объект J a v a P a c k a g e , соответствующих
пакету n e t s c a p e . *. Д а н н о е свойство допускает как чтение, так и запись.
opener
Если текущее окно было создано из другого окна (родительского), свойство
o p e n e r содержит ссылку на родительское окно. Д а н н о е свойство допускает как
чтение, так и запись.
outerHeight
Свойство o u t e r H e i g h t соответствует вертикальной составляющей внешнего
размера окна. Это свойство допускает как чтение, так и запись. Изменение значе
ния свойства приводит к изменению размеров окна. Окна размером менее 100x100
пикселей могут создаваться только защищенными (подписанными) сценариями.
outerWidth
Свойство o u t e r W i d t h соответствует горизонтальной составляющей внешнего
размера окна. Это свойство допускает как чтение, так и запись.
Packages
Данное свойство содержит ссылку на объект J a v a P a c k a g e , представляющий верх
ний уровень иерархии пакетов. Свойство P a c k a g e s доступно только для чтения.
pageXOffset
Данное свойство содержит смещение по координате х страницы, соответствую
щей области содержимого окна. Это свойство оказывается удобным при организа
ции прокрутки. Свойство p a g e X O f f s e t предназначено только для чтения, чтобы
изменить его значение, надо использовать s c r o l l T o или s c r o l l B y .
pageYOffset
Данное свойство содержит смещение по координате у страницы, соответствующей
области содержимого окна. Свойство p a g e Y O f f s e t предназначено только для чте
ния, чтобы изменить его значение, надо использовать s c r o l l T o или s c r o l l B y .
parent
Данное свойство, предназначенное только для чтения, ссылается на родительское
окно или ф р е й м . Для окна верхнего уровня w i n свойство w i n . p a r e n t содержит
значение w i n .
25.35. Объект Window 1243
personalbar
В броузере Netscape подписанные сценарии могут устанавливать свойство
v i s i b l e p e r s o n a l b a r , что позволяет скрыть или отобразить персональную па
нель инструментов (панель каталогов). Допустимыми значениями являются t r u e
(либо 1) и f a l s e (либо 0).
screen
Данное свойство на самом деле является не свойством Window, а глобальной пере
менной. Однако эта переменная рассматривается здесь, поскольку связана с текущим
окном. Об объекте Screen, на который ссылается s c r e e n , см. в разделе 25.29.
scrollbars
Подписанные сценарии могут устанавливать свойство v i s i b l e s c r o l l b a r s , что
позволяет скрыть или отобразить полосы прокрутки. Допустимыми значениями
являются t r u e (либо 1) и f a l s e (либо 0).
self
Данное свойство содержит ссылку на текущее окно и является синонимом window.
Свойство s e l f доступно только для чтения.
status
Значением данного свойства является строка, представляющая содержимое стро
ки состояния. Свойство s t a t u s допускает как чтение, так и .запись. В первых
JavaScript-сценариях данное свойство использовалось для организации бегущей
строки, но, как выяснилось впоследствии, бегущая строка скорее мешает, чем спо
собствует работе пользователя.
statusbar
Подписанные сценарии могут устанавливать свойство v i s i b l e s t a t u s b a r , что
позволяет скрыть или отобразить строку состояния. Допустимыми значениями
являются t r u e (либо 1) и f a l s e (либо 0).
sun
Данное свойство содержит ссылку на объект JavaPackage, соответствующий
верхнему уровню иерархии пакетов s u n . *. Свойство sun предназначено только
для чтения.
tags
Свойство t a g s может использоваться для установки свойств листов стилей.
toolbar
Подписанные сценарии могут устанавливать свойство v i s i b l e t o o l b a r , что по
зволяет скрыть или отобразить панель инструментов Netscape. Допустимыми зна
чениями являются t r u e (либо 1) и f a l s e (либо 0).
1244 Глава 25. Краткое руководство по JavaScript
top
Данное свойство ссылается на окно верхнего уровня, в состав которого входит те
кущее окно. Если ф р е й м ы не используются, текущее окно является окном верхнего
уровня. Свойство t o p доступно только для чтения.
window
Свойство window, предназначенное только для чтения, ссылается на текущее окно
и является синонимом свойства s e l f .
Методы
alert(message)
Метод a l e r t отображает диалоговое окно с сообщением.
ЬаскО
Данный метод вызывает переход к предыдущему пункту списка предыстории, т.е.
производит те же действия, которые выполняются после щелчка мышью на кноп
ке Back панели инструментов.
blurO
Метод b l u r приводит к потере фокуса ввода текущим окном; обычно при этом ок
но переводится на задний план.
captureEvents(eventType)
Данный метод переводит окно в режим захвата событий указанного типа.
clear Interval(intervallD)
Метод s e t I n t e r v a l возвращает идентификатор. Передавая этот идентификатор
( i n t e r v a l l D ) методу c l e a r I n t e r v a l , можно завершить выполняющуюся процедуру.
clear T i m e o u t ( t i m e o u t l D )
Метод s e t T i m e o u t возвращает идентификатор. Передавая этот и д е н т и ф и к а т о р
( t i m e o u t I D ) методу c l e a r T i m e o u t , можно отменить выполнение запланирован
ной процедуры.
close()
Данный метод закрывает окно. Вряд ли вы надеетесь, что вам будет разрешено за
крывать окна, которые вы не создавали, однако из-за ошибок в реализации языка
вы можете сделать это.
confirm(questionString)
Данный метод выводит диалоговое окно, отображающее строку с сообщением, за
данную в качестве параметра. Если пользователь щелкнет на кнопке ОК, возвраща
ется значение t r u e . П р и активизации кнопки C a n c e l возвращается значение
25.35. Объект Window 1245
f a l s e . Если вы включите в состав сообщения символы перевода строки ' \ п ' , со
общение будет отображаться в нескольких строках.
enableExternalCapture()
disableExternalCapture()
Подписанные сценарии имеют возможность перехватывать сообщения во внеш
них страницах. Указанные два метода соответственно разрешают и запрещают де
лать это.
findO
£ind(searchString)
find(searchString, caseSensitivityFlag, backwardFlag)
Метод f i n d выполняет поиск строки в текущем документе. Если метод вызван без
параметров, отображается диалоговое окно Find, посредством которого пользова
тель может ввести строку для поиска. Помимо строки, при вызове метода можно за
дать два логических значения. Второй параметр указывает, должен ли при поиске
учитываться регистр символов (если параметр имеет значение t r u e , осуществляется
поиск с учетом регистра), а третий параметр задает направление поиска (значение
t r u e предполагает поиск в обратном направлении). Если строка найдена, метод воз
вращает значение t r u e , в противном случае возвращается значение f a l s e .
focus()
в результате выполнения метода f o c u s окно получает фокус ввода. На большин
стве платформ при получении фокуса ввода окно перемещается на передний план.
forwardO
Выполнение данного метода вызывает переход вперед по списку предыстории.
handleEvent(event)
Если свойство c a p t u r e E v e n t s установлено, события указанного типа передаются
для обработки методу h a n d l e E v e n t .
home()
Данный метод вызывает о т о б р а ж е н и е в окне исходной страницы, т.е. при вызове
данного метода выполняются те же действия, что и после щелчка на кнопке Ногпе
панели инструментов.
m o v e B y ( x , у)
Метод moveBy вызывает перемещение окна на указанное число пикселей. В
Netscape перемещение окна за пределы экрана разрешено выполнять только под
писанным сценариям, но даже в этом случае вызов данного метода может привес
ти к нежелательным последствиям.
1246 Глава 2 5 . К р а т к о е руководство по JavaScript
m o v e T o ( x , у)
Метод moveBy размещает окно в указанной позиции. В Netscape размещение окна
за пределами экрана разрешено выполнять только подписанным сценариям, но
даже в этом случае вызов данного метода может привести к нежелательным по
следствиям.
open(url, name)
o p e n ( u r l , n a m e , features)
o p e n ( u r l , n a m e , features, replaceFlag)
Д а н н ы й метод может быть использован для поиска существующего окна или для
открытия нового. Для того чтобы лучше различать методы w i n d o w . o p e n и
d o c u m e n t . o p e n , при вызове данного метода свойство window п р и н я т о указывать
явно. Если вместо URL задана пустая строка, открывается пустое окно. В него
можно записать данные, пользуясь свойством d o c u m e n t окна. Параметр name мо
жет быть использован другими методами JavaScript либо указан в качестве значе
ния атрибута TARGET элементов А, BASE, AREA и FORM. Параметр r e p l a c e F l a g
указывает, должен ли быть замещен имеющийся пункт списка предыстории ( t r u e )
либо создан новый ( f a l s e ) . Строка f e a t u r e s содержит список характеристик в
виде характеристикам значение (пробелы недопустимы!) и задает характеристики
окна броузера. Если параметр f e a t u r e s не задан, все характеристики считаются
разрешенными. Характеристика без указания значения эквивалентна выражению
характеристика^уез. Допустимые имена характеристик и их описания приведены
в табл. 25.2. В листинге 25.5 содержатся п р и м е р ы использования метода
w i n d o w , o p e n ; результаты показаны на рис. 25.6-25.9. Кроме того, см. п р и м е р соз
дания окна был в разделе 24.10.
Внимсние!
print()
В результате выполнения данного метода документ выводится на печать, т.е. про
изводятся те же действия, что и после щелчка на кнопке Print. Заметьте, что вызов
метода приводит к отображению диалогового окна, поэтому автор JavaScript-
сценария не может вывести данные на п р и н т е р без согласия пользователя.
prompt(message)
p r o m p t ( m e s s a g e , defaultText)
Д а н н ы й метод выводит диалоговое окно с полем редактирования. После закрытия
окна метод возвращает значение, введенное в поле. Параметр d e f a u l t T e x t по
зволяет инициализировать поле редактирования заданным значением.
releaseEvents(eventType)
Данный метод отменяет режим перехвата событий указанного типа.
resizeBy(x, у)
Метод r e s i z e B y позволяет изменять размеры окна броузера на указанную вели
чину.
r e s i z e T o ( x , у)
Метод r e s i z e T o дает возможность задавать размеры окна броузера.
routeEvent(event)
Д а н н ы й метод используется в методе h a n d l e E v e n t для передачи события по на
значению.
scrollBy(x, у)
Данный метод выполняет прокрутку на )тсазанное число пикселей.
s c r o l l T o ( x , у)
Д а н н ы й метод выполняет прокрутку так, что указанная точка документа размеща
ется в левом верхнем углу окна.
s e t I n t e r v a l ( c o d e , delay)
Данный метод постоянно выполняет заданный код до тех пор, пока окно не будет
закрыто либо пока не будет вызван метод c l e a r l n t e r v a l .
s e t T i m e o u t ( c o d e , delay)
Методу s e t T i m e o u t передается строка, содержащая JavaScript-код и время задержки
в миллисекундах. По истечении заданного интервала код выполняется. Чтобы отме
нить выполнение кода, надо до окончания интервала вызвать метод c l e a r T i m e o u t ,
передав ему идентификатор, возвращенный методом s e t T i m e o u t . Заметьте, что
ме'год s e t T i m e o u t лишь планирует выполнение кода и возвращает управление, не
дожидаясь окончания времени задержки.
25.35. Объект Window 1249
stopO
Метод s t o p останавливает загрузку текущего документа, т.е. выполняет те же дей
ствия, которые производятся после щелчка на кнопке Stop.
Обработчики событий
onblurO
Данный метод вызывается при потере окном фокуса ввода. Обработчик o n b l u r ,
как показано ниже, задается посредством атрибута o n B l u r дескриптора <BODY>
или <FRAMESET>.
<BODY o n B l u r = " a l e r t ( ' W e w i l l m i s s you')">
</BLUR>
Часто данный обработчик применяется для того, чтобы остановить выполняю
щуюся процедуру в тот момент, когда пользователь переходит к другому окну. Вы
полнение процедуры затем возобновляется обработчиком o n f o c u s .
ondragdropO
В броузере Netscape данный метод выполняется при перетаскивании в окно бро
узера файла или ярлыка и последующем отпускании кнопки мыши. Указанный ме
тод устанавливается посредством атрибута o n D r a g D r o p .
onerrorO
Данный метод вызывается при возникновении ошибки. Данному обработчику не
соответствуют атрибуты, поэтому его надо задавать непосредственно.
function reportError() {
return(!confirm("An error occurred.\n" +
"Please report i t to\n" +
"gates@microsoft.com.\n\n" +
"See more d e t a i l s ? " ) ) ;
}
onerror = reportError;
Если обработчик возвращает значение t r u e , броузер не сообщает об ошибке. Так,
в приведенном выше примере, если пользователь щелкнет на кнопке ОК, он уви
дит лишь стандартное сообщение об ошибке. Установив значение o n e r r o r , рав
ное n u l l , можно полностью подавить вывод сообщения об ошибке.
onfocus()
Данный метод вызывается при получении окном фокуса ввода. Обработчик
o n f o c u s задается посредством атрибута o n F o c u s дескриптора <BODY> или
<FRAMESET>. П р и м е р установки обработчика приведен ниже.
<FRAMESET ROWS=...
onFocus="alert('Welcome back')">
</FRAMESET>
1250 Глава 25. Краткое руководство по JavaScript
onload()
Метод o n l o a d вызывается по окончании загрузки документа броузером. Для уста
новки данного обработчика используется атрибут о n L o a d дескриптора <BODY>
или <FRAMESET>. Д а н н ы й обработчик позволяет убедиться, что документ полно
стью загружен и функции, зависящие от различных частей документа, будут рабо
тать корректно.
onmove()
Метод onmove вызывается при перемещении окна (либо по инициативе пользова
теля, либо программными средствами). Д а н н ы й обработчик устанавливается по
средством атрибута onMove.
<BODY o n M o v e = " a l e r t ( ' H e y , move me b a c k ! ' ) " ...>
</BODY>
onresize()
Метод o n r e s i z e вызывается тогда, когда в результате действий пользователя или
выполнения JavaScript-кода размеры окна изменяются. Для установки данного об
работчика используется атрибут o n R e s i z e .
onunloadO
Метод onunload вызывается тогда, когда отображение страницы прекращается.
Для установки данного обработчика используется атрибут onUnload дескрипто
ров <BODY> или <FRAMESET>.
<SCRIPT TYPE="text/javascript">
function openSmallWindow() {
window.open("http://home.netscape.com/",
"smallWindow",
"width=375,height=125");
function openMediumWindow() {
window.open("http://home.netscape.com/",
"mediumWindow",
"width=550,height=225," +
"menubar,scrollbars,status,toolbar");
}
function openBigWindow() {
window.open("http://home.netscape.com/",
25.35. Объект Window 1251
"bigWindow",
"width=850,height=450," +
"directories, location,meniibar, " -l-
"scrollbars,status,toolbar");
}
// — >
</SCRIPT>
</HEAD>
<BODY>
<Hl>Opening Windows with JavaScript</Hl>
<FORM>
<INPUT TYPE="BUTTON" VALUE="Open Small Window"
onClick="openSmallWindow()">
<INPUT TYPE="BUTTON" VALUE="Open Medium Window"
onClick="openMediumWindow()">
<INPUT TYPE="BUTTON" VALUE="Open Big Window"
onClick="openBigWindow()">
</FORM>
</BODY>
</HTML>
^^ -ii^ # 3 ^ ^ a ^:»rfe a;
Opening Windows with Java^icript
'ш^~^^^1^ШШЩ
Рис. 25.6. Так выглядит документ OpenWindows.html до акти
визации одной из кнопок
Ш |ШШШШШВШ
Netscape £
^itturdoy, r-ebrudty 24, 2001
(№«v«w<t<»t< Vt^fivai Screen Klnas To>
1ж
Fte
Netscape.com - Netscape
Edit View 60 Communicatof Help
33
- d f.r ^. ,МУ1 :„J Ш
я
Satut<}ay. F e b r u a r v 24, 2 0 0 1
ШСБШЭгЖПШ!
:' •.' 4 -'Л .^ si i 'S Ъ 1; SI
^ Bookmafks .^' NetsSe jhUp /'/home netscape com/ ' What's Related
^imtentMrnage ? WebMa* ^ i Contact ^ 1 Poopte g i Ye8owP«ges S i Download J ^ Chanrwfe ^ ReaiPlajjw
ШЕ£-':с^ ^^I^J.^,^^^^!^^^
.iSQ.OOQ
business tBaasi d
(йГ' '^'^'^ Doc^nent Don« ..ШЙЩ.-..;::.^...;:
Рис. 25.9. Указав все характеристики, вы можете отобразить окно броузера в привычном
виде. (Приведено с разрешения Netscape Communications Corp.)
25.35. Объект Window 1253
25.36. Резюме
Итак, книга прочитана. П р и м и т е наши поздравления. Мы надеемся, что вы освои
ли основы HTML, Java и JavaScript настолько, что сможете разработать Web-
приложение от начала и до конца. Теперь самое время вернуться к тем главам, кото
рые вы лишь бегло просмотрели, и прочитать их внимательно. Если вы уже знаете
стандартные средства HTML, может быть, вас заинтересуют листы стилей или меха
низм слоев. Владея основами Java, наверное, следует подумать о более глубоком изу
чении механизма потоков, RMI или JDBC. Возможно, вы имеете опыт создания CGL
программ. В этом случае стоит разобраться в том, как работают сервлеты. Вы увиди
те, что сервлеты позволяют добиться тех же результатов, затрачивая намного мень
шие усилия. В некоторых случаях регулярные выражения упрощают работу над соз
данием JavaScript-сценария. П о н я т н о , что вы не можете блестяще разобраться с абсо
лютно всеми вопросами, но, независимо от того, какое направление вы выберете для
дальнейшего изучения, базовые знания у вас уже есть.
Перед тем как продолжать работу, советуем вам день-два отдохнуть. И не забудьте
сказать начальнику, что ему следует подумать о вашем повышении.
Ж е л а е м успехов!
1254 Предметный указатель
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ
M
MDI, 575 Tomcat, 821
М1МЕ-ТИП, 50; 93; 1207 Transformation API for XML, 1079
Model view controller architecture, 978 TrAX, 1079
Multiple Document Interface, 575
и
N UI-представитель, 544; 546
Netscape, 37 Unicode, 48; 85; 255
Uniform Resource Locator, 39
URL, 39
PHP, 903
POP3, 193 V
VBScript, 903
VRML, 101
QuickTime, 94
w
World Wide Web Consortium, 37
R
Remote Method Invocation, 192; 719; 756
Resin, 821 X
RMI, 192; 719; 756 XML, 193; 1051
RMI-IIOP, 193 XPath, 1078
RMI-клиент, 757 XSL, 1077; 1078
RMI-сервер, 757 XSLT, 1051; 1078
RPC, 756 XSLT-конвертирование, 1079
RSA, 681
1256 Предметный указатель
Metal, 547
Motif, 547
Ф
Windows, 547 Файл описания, 246
о ф о р м л е н и я конца отрезка, 381 Файл описания библиотеки дескрип
рисования, 364 торов, 946; 947
соединения линий, 381 Физический стиль, 83
Строгая декларация HTML, 43 Фильтрация данных, 839
Строка, 284; 1230 Флаг завершения, 688
комментариев, 253 Флажок опции, 501; 595; 799; 1178
параметров, 781; 836 Фокус, 93; 117
состояния,853 Форма, 78; 1190
таблицы, 66; 71 Формирование запроса аплетом, 991
Структура данных DOM, 1053 Фрейм, 37; 111; 1144; 1240
Суперкласс, 230 Функция JavaScript, 1110; 1191
Сценарий, 1101
Ц
Цвет пера, 381
Таблица, 66 Целочисленные типы, 256
Таймер, 712 Централизованная обработка
Текст шаблона, 904 событий, 495
Текстовая область, 523; 589; 792; 1238 Цикл, 258; 265
Текстовый блок, 55 Цитирование, 60; 85
Тело пользовательского дескриптора, 956 Ц и ф р о в а я подпись, 311
Т е р м и н ы определений, 65
Толщина
линии,359
ч,ш
пера, 381 Число, 1210
Тяжеловесный компонент, 544 с плаваюш,ей точкой, 256
Ч т е н и е из стандартного входно
го потока, 274
Шаблон, 359; 381
Удаленный вызов процедур, 756
объект, 757
Указатель, 186; 280
Управление аплетами из JavaScript-сце- Экземпляр класса, 207
нариев, 1148; 1153 Элемент блокового уровня, 50; 55
Усечение, 257 массива, 291
Условный сценария, 902; 904
запрос, 857 текстового уровня, 50; 83
о п е р а т о р , 2 5 8 ; 259 ф о р м ы , 1186
Научно-популярное издание
Марти Холл, Лэрри Браун