Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
6 8 Часть II. Библиотека строке, используется " M H P r o f e s s i o n a l c o m " . Строка преобразуется в байтовый массив и отправляется в сокет. После этого ответ читается из сокета, и результат отображается на экране. И наконец, сокет закрывается, что в результате приводит к закрытию потоков ввода-вывода. В приведенном примере сокет был закрыт вручную при вызове метода c l o s e () . Если вы используете комплект 7, то можете использовать блок t r y -с-ресурсамидля автоматического закрытия сокета. Вот, например, еще один способ написать метод m a i n () предыдущей программы Использование блока try-с-ресурсами для закрытия сокета, public static void main(String a r g s []) throws Exception { int с ; // Создает сокетное соединение спорт Этим сокетом управляет блок try-с-ресурсами. try ( Socket s = new Socket("whois.internic.n e t ", 43) ) { // Получает входной и выходной потоки in = s .getlnputStream(); OutputStream out = s .getOutputStream(); // Создать строку запроса str = (args.length == 0 ? "MHProfessional.com" : args[0]) + " \ n "; // Преобразует в байты byte buf[] = s t r .getBytes(); // Посылает запрос out.write(buf); // Читает и отображает ответ while (с = in.readO) != -1) { System.out.print((char) c ) ; } } // Теперь сокет закрыт. } В этой версии сокет автоматически закрывается в конце блока Таким образом, пример не будет работать с версиями Java до JDK 7, а чтобы четко проиллюстрировать, когда сетевой ресурс может быть закрыт, в последующих примерах будет продолжено использование явного вызова метода c l o s e (). Однако в собственном коде следует обратить внимание на использование автоматического управления ресурсами, так как это обеспечивает более гибкий подход. Еще один момент в этой версии исключения все еще передаются из функции m a i n ( ) , но они могли бы быть обработаны при добавлении директивы c a t c h вконец блока t r y -с-ресурсами. На заметку Для простоты в примерах этой главы все исключения передаются из функции m a i n (). Это позволяет проще проиллюстрировать логику сетевого кода. Однако в реальном коде вы обычно будете должны обработать исключения соответствующим способом. Класс u r Предыдущий пример не очень вразумителен, поскольку в настоящее время Интернет не ассоциируется со старыми протоколами, такими как whois, finger и FTP. Здесь царствует WWW — всемирная паутина (World Wide Web). Веб — это ела Глава 21. Сеть 6 8 5 бо связанная коллекция высокоуровневых протоколов и форматов файлов, унифицированным образом используемых веб-браузерами. Одним из наиболее важных аспектов веб является то, что Тим Бернерс-Ли (Tim Bemers-Lea) предложил масштабируемый способ нахождения всех ресурсов в Интернете. Как только вы можете однозначно именовать что-либо, это становится очень мощной парадигмой. Именно это и делает унифицированный локатор ресурсов (Uniform Resource Locator — URL). URL обеспечивает довольно четкую форму уникальной идентификации адресной информации в веб. Внутри библиотеки классов Java класс URL представляет простой согласованный программный интерфейс для доступа к информации по всей сети при помощи Все URL совместно используют один и тот же базовый формат, хотя и допускающий некоторые вариации. Приведем два примера h t t p : / / w w w .M H P ro fessio n al. соти. сот. Спецификация URL основана на четырех компонентах. Первый — используемый протокол, отделяемый от остальной части локатора двоеточием (:). Распространенными протоколами являются HTTP, FTP, gopher и file, хотя в наши дни почти все осуществляется через протокол HTTP (фактически большинство браузеров корректно работает, даже если вы исключите из спецификации URL фрагмент " h t t p : / / " ) . Второй компонент — имя хоста или адрес, используемый хостом; он отделяется слева двойным слешем (/ /), а справа — слешем (/) или, что необязательно, двоеточием (:). Третий компонент — номер порта это необязательный параметр, отделяемый слева от имени хоста двоеточием, а справа — слешем (/). (Если порт 80 является портом по умолчанию для протокола HTTP, то указывать " : 80" излишне) Четвертый компонент — действительный путь к файлу. Большинство серверов HTTP добавляет имя файла i n d e x . h tm l или i n d e x . htm к URL, которые указывают непосредственно на какой-то каталог. Таким образом, h t t p : / / w w w .M H P ro fessio n al. сот это тоже самое, что и адрес h t t p : / /www. M H P r o f e s s io n a l. c o m /in d e x . Класс Java URL имеет несколько конструкторов, и каждый из них может передать исключение Malf ormedURLException. Одна из часто используемых форм определяет URL в виде строки, идентичной тому, что вы видите в браузере. URL(String спецификаторияь) throws Следующие две формы конструктора позволяют вам разделить URL на части- компоненты имяПротокола, String имяХоста, int порт String путь) throws MalformedURLException URL(String имяПротокола, String имяХоста, String путь) throws Другой часто используемый конструктор позволяет указать существующий URL в качестве ссылочного контекста, а затем создать из этого контекста новый URL. Хотя это звучит несколько запутано, на самом деле это очень простои удобно o6beKTURL, String спецификаторЦКЬ) throws Следующий пример создает URL страницы статей HerbSchildt. com, а затем просматривает его свойства Демонстрация применения URL. import java.net.*; class URLDemo { public static void main(String a r g s []) throws MalformedURLException { URL hp = new U R L (Протокол " + h p Порт " + h p .getPort()); System.out.println("Хост: " + h p .getHost()); Часть II. Библиотека Файл " + Целиком " + h p Запустив это, вы получите следующее http Port: -1 Host: www.HerbSchildt.com File: Обратите внимание на порт -1 ; это означает, что порт явно не установлен. Передав объект URL, вы можете извлечь ассоциированные с ним данные. Чтобы получить доступ к действительным битам или информации по URL, создайте из него объект класса URLConnect ion, используя его метод openConnect ion () , как показано ниже = u r l Метод openaConnection () имеет следующую общую форму openConnection() throws Он возвращает объект класса URLConnection, ассоциированный с вызывающим объектом класса URL. Обратите внимание он может передать исключение IOException. Класс Класс URLConnection — это класс общего назначения, предназначенный для доступа к атрибутам удаленного ресурса. Однажды установив соединение суда ленным сервером, вы можете использовать класс URLConnection для просмотра свойств удаленного объекта, прежде чем транспортировать его локально. Эти атрибуты представлены в спецификации протокола HTTP и, как таковые, имеют смысл только для объектов URL, использующих протокол Класс URLConnection определяет несколько методов. Некоторые из них перечислены в табл. Таблица 21.5. Некоторые методы класса Описание . t . » ____-J Возвращает размер в байтах содержимого, связанного с ресурсом. Если размер недоступен, возвращает значение -Возвращает размер в байтах содержимого, связанного с ресурсом. Если размер недоступен, возвращает значение -1 (Добавлено в JDK Возвращает тип содержимого, найденного в ресурсе. Это значение поля заголовка content-type. Возвращает значение null, если тип содержимого не доступен Возвращает время и дату ответа, представленное в миллисекундах, прошедших с 1 января 1970 г. Возвращает время и дату устаревания ресурса, представленное в миллисекундах, прошедших с 1 января 1970 г. Если дата устаревания недоступна, возвращается нуль getContentLength() long getContentLengthLong() String getContentType() long g e t D a t e () long getExpiration() Глава 21. Сеть 6 8 Окончание табл. метод ?- • -■ - -Описание имяПоля) String getHeaderFieldKey(int индекс getHeaderField(int индекс) Возвращает значение заголовочного поля по индексу индекс. (Индексы полей заголовка нумеруются начиная с 0.) Возвращает значение null, если значение индекс превышает количество полей Возвращает значение заголовочного поля, имя которого указано в имяПоля. Возвращает значение null, если указанное полене найдено, List getHeaderFields() long Возвращает ключ заголовочного поля по индексу индекс. (Индексы полей заголовка нумеруются начиная с 0.) Возвращает значение null, если значение индекс превышает количество полей Возвращает карту, содержащую все заголовочные поля вместе сих значениями Возвращает время и дату последней модификации ресурса, представленные в миллисекундах, прошедших после 1 января 1970 г. Если эта информация недоступна, возвращается нуль throws Возвращает объект класса Inputstream, привязанный к ресурсу. Данный поток может использоваться для получения содержимого ресурса_____________________ Обратите внимание на то, что класс URLConnection определяет несколько методов, управляющих заголовочной информацией. Заголовок состоит из пар ключей и значений, представленных в виде строк. Используя метод ge t Header - Field () , вы можете получить значение, ассоциированное с ключом заголовка. Вызывая метод getHeaderField () , можно получить карту, содержащую все заголовки. Несколько стандартных заголовочных полей доступны непосредственно через такие методы, как getDate () и getContentType ( Следующий пример создает объект класса URLConnection, используя метод openConnection () объекта класса URL, а затем применяет его для проверки свойств и содержимого документа Демонстрация применения URLConnection. import java.net.*; import java.io.*; import java.util.Date; class UCDemo { public static void main(String a r g s []) throws Exception { int c; URL hp = new U R L ("h t t p ://www.internic.n e t "); URLConnection hpCon = h p .openConnection(); // получить дату d = hp C o n Нет информации о дате."); else System.out.println("Дата: " + new Date(d)); // получить тип содержимого System.out.println("Тип содержимого " + hpC o n .getContentType()); // получить дату устаревания d = hpCon.getExpiration(); Часть II. Библиотека Нет информации о сроке действия."); else System.out.println("Устареет: " + new Date(d)); // получить дату последней модификации d = hpCon.getLastModified(); Нет информации о дате последней модификации."); else System.out.println( "Дата последней модификации " + new Date(d)); // получить длину содержимого len = h p C o n .getContentLengthLong(); i f (len == -Длина содержимого недоступна."); else System.out.println("Длина содержимого " + len); i f (len != 0) { System.out.println("=== Содержимое ==="); InputStream input = hp C o n .getlnputStream(); while (((c = input.r e a d ()) != -1)) { System.out.print((char) c ) ; } input.c l o s e (); } else { System.o u t .p r Содержимое недоступно."); } } } Эта программа устанавливает соединение HTTP с сервером www. internic . net через порт 80. Затем она отображает несколько заголовочных значений и извлекает содержимое. Приведем первые строки вывода (точное их содержание будет меняться со временем). Дата: Mon Oct 04 15:53:24 CDT Тип содержимого text/html; Нет информации о сроке действия. Дата последней модификации. Thu Sep 24 15:22:52 CDT 2009 Длина содержимого 7316 === Содержимое Класс HttpURLConnection Java предлагает подкласс класса URLConnection, обеспечивающий поддержку соединений HTTP. Этот класс называется HttpURLConnection. Вы получаете объект класса HttpURLConnection точно также, как было показано, — вызовом метода openConnection () объекта класса URL, но результат следует приводить к классу HttpURLConnection. Конечно, необходимо убедиться в том, что вы Глава 21. Сеть 6 8 действительно открыли соединение HTTP.) Получив ссылку на объект класса HttpURLConnection, вы можете вызывать любые его методы, унаследованные от класса URLConnec t ion. Вы также можете использовать любые методы, определенные в классе HttpURLConnection. Некоторые методы перечислены в табл. Таблица 21.6. Некоторые методы класса H t t p U R L C o n n e c t i o n Метод Описание static boolean getFollowRedirects() String getRequestMethod() int getResponseCode() throws IOException String getResponseMessage() throws IOException static void setFollowRedirects(boolean как setRequestMethod(String как Возвращает значение true, если автоматически следует перенаправление, и значение false — в противном случае Возвращает строковое представление метода выполнения запроса. По умолчанию используется метод GET. Доступны другие методы, такие как Возвращает код ответа HTTP. Если код ответа не может быть получен, возвращается значение -1. При разрыве соединения передается исключение IOException Возвращает сообщение ответа, ассоциированное с кодом ответа. Если никакого сообщения недоступно, возвращает значение Если параметр как содержит значение true, значит, перенаправление осуществляется автоматически. Если же он содержит значение f a l s e , значит, этого не происходит. По умолчанию перенаправле ние осуществляется автоматически Устанавливает метод, которым выполняются запросы HTTP, в соответствии с указанным в параметре как По умолчанию принят метод GET, но доступны также другие варианты, такие как POST. Если в параметре как указано неправильное значение, передается исключение ProtocolException BcлeдyющeйпpoгpaммeдeмoнcтpиpyeтcяpaбoтacклaccoмHttpURLConnection. Сначала она устанавливает соединение с сайтом w ww . g o o g l e . com. Затем отображает метод запроса, код ответа и сообщение ответа. И наконец, отображает ключи и значения в заголовке ответа Демонстрация применения HttpURLConnection. import java.net.*; import java.io.*; import java.util.*; class HttpURLDemo { public static void main(String a r g s []) throws Exception { URL hp = new U R L ("h t t p ://www.google.com"); HttpURLConnection hpCon = (HttpURLConnection) h p .openConnection(); // Отображение метода запроса. System.out.println("Метод запроса " + hp C o n .getRequestMethod()); // Отображение кода ответа. System.out.println("Код ответа " + h p C o n .getResponseCode()); // Отображение сообщения ответа. System.out.println("Сообщение ответа " + 6 9 Часть II. Библиотека Java hpCon.getResponseMessage()); // Получить список полей заголовка и набор его ключей, List Set System.out.println("ХпЗдесь следует заголовок Отобразить все ключи и значения заголовка for(String k : hdrField) Ключ " + k + " Значение " + Вывод этой программы показан ниже (разумеется, точный ответ, возвращенный сайтом w w w . google. com, будет меняться стечением времени). Метод запроса GET Код ответа 2 00 Сообщение ответа ОК Здесь следует заголовок: Ключ: null Value: [HTTP/1.1 200 Ключ Date Value: [Mon, 04 Oct 2010 21:11:53 Ключ Transfer-Encoding Value: Ключ Expires Value: Ключ X-XSS-Protection Value: [1; Ключ Set-Cookie Value: [NID=39=uASl- DdTfLelHcxkEiRy7xNtExX3zJaKS9mjdTy8_Xej jBkpjWvcqyMXgC4Ha4VT_5IZN2pnxsl oo-NlGHvcK0AIqXPhFcnCdlRlWw4WgbiY7KrthNXCQxfXbHJwNgue; expires=Tue, 05-Apr-201121:11:53 GMT; path=/; domain=.google.com; HttpOnly, PREF=ID=6644372blf9612 0 c :TM= 12 8 62 2 6713:LM=1286226713:S= iNeZU0xRTrGPxg2K;expires=Wed, 03-0ct-2012 21:11:53 GMT; path=/; Ключ Content-Type Value: [text/html; Ключ Server Value: Ключ Cache-Control Value: [private, Обратите внимание на то, как отображаются ключи и значения заголовка. Карта ключей и заголовков получается вызовом метода getHeaderFields () (который унаследован от класса URLConnection). Затем набор ключей заголовка извлекается вызовом метода keySet () карты. Далее осуществляется перебор всего набора при помощи стиля “for-each” цикла for. Значение, ассоциированное с каждым ключом, получается из карты вызовом метода get (Класс u r Класс URI инкапсулирует универсальный идентификатор ресурса (Uniform Resource Identifier — URI). URI очень похож на URL. На самом деле URL представляет собой подмножество URL URI предоставляет стандартный способ идентификации ресурсов. URL также описывает доступ к ресурсу. Файлы Пакет j ava. net включает классы и интерфейсы, помогающие управлять файлами cookie, которые могут использоваться для создания сеансов HTTP с поддержкой состояния (в противоположность таковым без поддержки состояния. К таким классам относятся CookieHandler, CookieManager и Ht tpCookie, а к интерфейсам — Глава 21. Сеть 6 9 1 CookiePolicy и CookieStore. Все, кроме класса CookieHandler, были добавлены в Java SE 6. (Класс CookieHandler появился в JDK 5.) Создание сеанса HTTP с поддержкой состояния выходит за рамки настоящей книги. На заметку Информацию о применении файлов cookie с сервлетами см. в главе 32. Серверные сокеты Как уже упоминалось, в языке Java имеются различные классы сокетов, которые должны применяться для создания серверных приложений. Класс ServerSocket используется для создания серверов, которые прослушивают обращения как локальных, таки удаленных клиентских программ, желающих установить соединения сними через открытые порты. Класс ServerSocket довольно-таки сильно отличается от обычных классов Socket. Когда вы создаете объект класса ServerSocket, он регистрирует себя в системе в качестве заинтересованного в клиентских соединениях. Конструкторы класса ServerSocket отражают номер порта, через который вы хотите принимать соединения, а также (необязательно) длину очереди для данного порта. Длина очереди сообщает системе о том, сколько клиентских соединений можно удерживать, прежде чем начать просто отклонять попытки подключения. По умолчанию установлено 50. При определенных условиях конструкторы могут передать исключение IOException. Конструкторы этого класса описаны в табл. Таблица 21.7. Конструкторы класса ServerSocket Конструктор Описание S e r v e r S o c k e t (int порт throws IOException S e r v e r S o c k e t (int порт int м аксО чередь) throws IOException S e r v e r S o c k e t (int порт м аксО ч ередь, InetAddress локальныйАдрес) throws Создает серверный сокет на указанном порте с длиной очереди Создает серверный сокет на указанном порте с максимальной длиной очереди в параметре м аксО чередь Создает серверный сокет на указанном порте с максимальной длиной очереди в параметре м аксО чередь. На групповом хосте локальны йА дрес указывает IP- адрес, к которому привязан сокет Класс ServerSocket включает метод по имени accept ( ), представляющий собой блокирующий вызов, который будет ожидать от клиента инициации соединений, а затем возвратит обычный объект класса Socket, который далее может служить для взаимодействия с клиентом. Дейтаграммы Сетевое взаимодействие в стиле T C P /IP подходит для большинства сетевых нужд. Оно обеспечивает сериализуемые, предсказуемые и надежные потоки пакетов данных. Тем не менее это обходится далеко недаром. Протокол TCP включает множество сложных алгоритмов управления потоками в нагруженных сетях, атак же самые пессимистические предположения относительно утери пакетов. Это порождает в некоторой степени неэффективный способ транспортировки данных. В качестве альтернативы можно использовать дейтаграммы. Дейтаграммы (datagramms) — это порции информации, передаваемые между машинами. В некотором отношении они подобны сильным броскам тренированного, но подслеповатого кетчера в сторону третьего бейсмена. Как только дейта 6 9 Часть II. Библиотека грамма запущена в нужном направлении, нет никаких гарантий, что она достигнет цели или кто-нибудь окажется на месте, чтобы ее подхватить. Точно также, когда дейтаграмма принимается, нет никакой гарантии, что она не была повреждена в пути или что ее отправитель все еще ожидает ответа реализует дейтаграммы поверх протокола UDP, используя для этого два класса DatagramPacket контейнер данных) и класс DatagramSocket механизм, используемый для обслуживания класса DatagramPacket). Рассмотрим их более подробно. Класс Класс DatagramSocket определяет четыре открытых конструктора) throws SocketException DatagramSocket(int порт SocketException DatagramSocket(int порт 1рАдрес) throws SocketException DatagramSocket(SocketAddress адрес Первый конструктор создает объект класса DatagramSocket, связанный с любым незанятым портом локального компьютера. Второй — объект класса Data gramSocket, связанный спортом, указанным в port. Третий создает объект класса DatagramSocket, связанный с указанным портом и объектом класса InetAddress. Четвертый—объект класса Dat agr amS ос, связанный с заданным S осе Класс SocketAddress — это абстрактный класс, реализуемый конкретным классом InetSocketAddress, который инкапсулирует адрес с номером порта. Все конструкторы могут передать исключение SocketException в случае возникновения ошибок вовремя создания сокета. Класс DatagramSocket определяет множество методов. Два наиболее важных из них — это методы send () и receive ( ), которые представлены ниже send(DatagramPacket пакет throws IOException void receive(DatagramPacket пакет Метод send () отправляет порту пакет, указанный в параметре пакет Метод receive () ожидает приема через порт пакета, указанного в параметре пакет , и возвращает результат. Класс DatagramSocket определяет также метод close ( ), который закрывает сокет. Начиная с JDK 7 класс DatagramSocket реализует интерфейс AutoCloseable, что позволяет управлять им блоку try с ресурсами Другие методы предоставляют вам доступ к различным атрибутам, связанным с классом DatagramSocket. Эти методы перечислены в табл. Таблица 21.8. Методы класса DatagramSocket Метод Описание Если сокет подключен, возвращается адрес. В противном InetAddress () случае возвращается значение null int get Local Port () Возвращает номер локального порта get Port () Возвращает номер порта, к которому подключен сокет. Возвращает значение -1, если сокет не подключен ник какому порту is Bound () Возвращает значение true, если сокет привязан к адресу, в противном случае — значение f a l s e boolean isConnected () Возвращает значение true, если сокет подключен к серверу, в противном случае — значение false void setSoTimeout (int Устанавливает период ожидания в миллисекундах, перем иллисекунд) throws данный параметром миллисекунд Глава 21. Сеть 6 9 Класс D a t a g r a m P a c k e Класс DatagramPacket определяет множество конструкторов. Вот четыре из них (byte данные ], int размер (byte данные [ ], int смещение int размер данные ], int размер InetAddress ipAddress, int порт данные ] , int смещение int размер InetAddress ipAzjpec, int порт) Первый конструктор определяет буфер, который будет принимать данные, и размер пакета. Он используется для приема данных через класс Da t agr amSocke Второй конструктор позволяет вам указать смещение в буфере, куда должны быть помещены данные. Третий указывает целевой адрес и порт, используемые классом DatagramSocket для определения того, куда данные пакета будут отправлены. Четвертый передает пакеты, начиная с указанного смещения в данных. Первые два конструктора следует воспринимать как построение ящика, а вторые два — как начинку и адрес на конверте. Класс DatagramPacket определяет несколько методов, включая представленные здесь, которые предоставляют доступ к адресу и номеру порта пакета, наряду с базовыми данными и их длиной (табл. 21.9). В общем случае методы get используются в принимаемых пакетах, а методы set — в отправляемых. Таблица 21.9. Методы класса D a t a g r a m P a c k e t Метал Описание InetAddress g e t A d d r e s s (] byte[] g e t D a t a () int getLength() int g e t O f f s e t O int g e t P o r t () void s e t A d d r e s s (InetAddress 1рА д рес) void s e t D a t a ( b y t e [] данные s e t D a t a ( b y t e [] данные индекс размер размер порт Возвращает адрес источника (для принимаемых дейтаграмм) или места назначения (для отправляемых дейтаграмм) Возвращает байтовый массив данных, содержащихся в дейтаграмме. В основном, используется для извлечения данных из дейтаграммы после ее приема Возвращает длину корректных данных, содержащихся в байтовом массиве, который должен быть возвращен из метода getData (). Это может не совпадать с полной длиной байтового массива Возвращает начальный индекс данных Возвращает номер порта Устанавливает адрес, по которому отправляется пакет. Адрес указывается параметром р Адрес Устанавливает данные в данные, смещение — в нуль, а длину — в количество байтов данные Устанавливает данные в данные, смещение — в индекса длину — в размер Устанавливает длину пакета враз мер Устанавливает порт в порт bbbПример работы с дейтаграммами В следующем примере реализуется очень простое сетевое взаимодействие клиент и сервер. Сообщения вводятся в окне на сервере и передаются посети на сторону клиента, где и отображаются 6 9 Часть II. Библиотека Java // Демонстрация применения дейтаграмм import java.net.*; class WriteServer { public static int serverPort = 998; public static int clientPort = 999; public static int buffer_size = 1024; public static DatagramSocket ds; public static byte b u ffer[] = new byte[buffer_size]; public static void TheServer() throws Exception { int pos=0; while (true) { int с = System.in.r e a d (); switch (c) { case -Сервер завершил работу d s .cl o s e (); return; case '\ r 1: break; case 1\ n ': d s .send(new DatagramPacket(buffer,pos, InetAddress.getLocalHost(), clientPort)); p os=0; break; default: buffer[pos++] = (byte) c; } } } public static void TheClientO throws Exception { while(true) { DatagramPacket p = new DatagramPacket(buffer, buffer.length); d s .receive(p); System.out.println(new String(p.getData(), 0, p.getLength()) ) ; } } public static void main(String a r g s []) throws Exception { if(args.length == 1) { ds = new DatagramSocket(serverPort); TheServer(); } else { ds = new Этот пример программы ограничен конструктором класса DtagramSocket для запуска между портами локальной машины. Чтобы использовать программы, выполните водном окне такую команду, java Это будет клиент. Затем в другом окне запустите следующую команду, java WriteServer Это будет сервер. Все, что вы введете в окне сервера, после получения символа перевода строки будет отправлено в клиентское окно ГЛАВА Класс A p p le В настоящей главе рассматривается класс. Applet, который обеспечивает основу для создания аплетов. Этот класс содержится в пакете java. applet. Он включает несколько методов, обеспечивающих подробный контроль над выполнением аплета. Кроме того, пакет java.applet определяет три интерфейса — AppletContext, AudioClip и Важно подчеркнуть, что существует два типа аплетов. Первый основан непосредственно на классе Applet, описанном в настоящей главе. Эти аплеты используют библиотеку Abstract Window Toolkit (AWT) для предоставления пользовательского графического интерфейса (если вообще его используют. Этот тип аплетов доступен с самого начала существования Второй тип аплетов основан на классе J Applet библиотеки Swing. Аплеты Swing используют классы библиотеки Swing для построения графического интерфейса пользователя. Библиотека Swing предлагает более богатый и зачастую более легкий в применении пользовательский интерфейс, чем библиотека AWT. Поэтому аплеты на основе библиотеки Swing в настоящее время наиболее популярны. Однако традиционные аплеты на основе библиотеки AWT все еще применяются, особенно когда требуется построить очень простой пользовательский интерфейс. А потому и аплеты на основе библиотеки AWT, и аплеты на основе библиотеки Swing совершенно законны. Поскольку класс J Applet происходит от класса Applet, все его средства также доступны в классе JApplet, и большая часть материала этой главы относится к обоим типам аплетов. А потому, даже если вас интересуют только аплеты Swing, приведенная в этой главе информация все равно будет полезна и необходима. Однако следует понимать, что при создании аплетов на основе библиотеки Swing существуют некоторые дополнительные ограничения, которые будут описаны далее в книге, когда пойдет речь о библиотеке Наз ам етку ! Информация о построении аплетов с использованием библиотеки Swing приведена в главе Два типа аплетов Основы аплетов В главе 13 были рассмотрены общая форма аплета, а также действия, необходимые для его компиляции и запуска. Начнем с пересмотра этой информации 6 9 Часть II. Библиотека Все классы аплетов являются подклассами (прямыми или непрямыми) класса Applet. Аплеты не являются самостоятельными программами, они выполняются либо внутри веб-браузера, либо при помощи средства просмотра аплетов. Иллюстрации, которые приведены в этой главе, были созданы с применением стандартного средства просмотра аплетов под названием appletviewer, входящего в комплект JDK. Однако вы можете использовать любой другой браузер или средство просмотра по своему вкусу. Выполнение аплета начинается нес метода m ain (). На самом деле лишь немногие аплеты имеют методы m ain (). Вместо этого выполнение аплета запускается и управляется при помощи совершенно другого механизма, который будет описан ниже. Вывод окна вашего аплета осуществляется не при помощи метода S y stem , o u t . p r i n t I n (). Вместо этого в аплетах не на базе библиотеки Swing вывод осуществляется различными методами библиотеки AWT, такими как метод d r a w s t r i n g (), который направляет строку в точку с указанными координатами X,Y. Ввод также осуществляется иначе, чем в консольных приложениях. (Помните, что аплеты на основе библиотеки Swing используют классы библиотеки Swing для обработки взаимодействия с пользователем, и они также будут описаны далее в настоящей книге.) Прежде чем использовать аплет, следует выбрать стратегию его развертывания. Есть два основных подхода. Первый подразумевает использование протокола запуска сети Java (Java Network Launch Protocol —JNLP). Этот подход обеспечивает больше гибкости, особенно в отношении улучшенных приложений Интернета. Для реальных аплетов, которые вы создаете, протокол JNLP зачастую является наилучшим выбором. Однако подробное обсуждение протокола JNLP выходит за рамки данной книги. (Более подробная информация о протоколе JNLP приведена в документации KOMmieKTaJDK.) К счастью, протокол JNLP необязателен для примеров аплетов, представленных здесь. Второй подход развертывания аплета подразумевает его определение непосредственно в файле HTML, без использования протокола. Это первоначальный способ запуска аплетов, который использовался Java с момента создания и до сих пор применяется для простых аплетов. Кроме того, благодаря унаследованной простоте, этот подход применяется для примеров аплетов, описанных в данной книге. На момент написания книги корпорация Oracle рекомендовала дескриптор APPLET, поэтому в данной книге используется именно этот дескриптор. (В настоящее время применение дескриптора APPLET не рекомендуется спецификацией HTML. Альтернатива — дескриптор OBJECT. За последними рекомендациями в этом отношении имеет смысл обратиться к документации комплекта JDK.) Когда в файле HTML встречается дескриптор APPLET, веб-браузер с поддержкой Java выполняет указанный аплет. Использование дескриптора APPLET предоставляет еще одно преимущество при разработке аплетов, поскольку он позволяет легко просматривать и проверять аплет. Для этого просто включите комментарий в заголовок файла вашего исходного кода Java, который содержит дескриптор APPLET. Таким образом, код будет документирован конструкциями HTML, необходимыми вашему аплету, ивы сможете проверить скомпилированный аплет, запустив средство просмотра апле тов с заданным файлом исходного кода Java. Вот пример такого комментария code="myapplet" width=2 00 Этот комментарий включает дескриптор APPLET, который запустит аплет по имени My Applet в окне размером 200 пикселей в ширину и 60 пикселей в высоту Глава 22. Класс Applet 6 9 Поскольку включение команды APPLET облегчает проверку аплетов, все аплеты, показанные в этой книге, будут содержать соответствующий дескриптор APPLET, помещенный в комментарий. Класс A p p l e Этот класс определяет методы, показанные в табл. 22.1. Класс Applet обеспечивает всю необходимую поддержку для выполнения аплета, такую как его запуски останов. Кроме того, он предоставляет методы для загрузки и отображения графических образов, а также для загрузки и воспроизведения аудиоклипов. Класс Applet расширяет класс Panel библиотеки AWT. В свою очередь, класс Panel расширяет класс Container, который расширяет класс Component. Все эти классы обеспечивают поддержку графического оконного интерфейса на базе Таблица 22.1. Методы, определенные в классе A p p l e t Метод Описание void d e s t r o y () AccessibleContext g e t A c c e s s i b l e C o n t e x t () AppletContext g e t A p p l e t C o n t e x t () String g e t A p о () AudioClip getAudioClip(URL u r i ) AudioClip getAudioClip(URL u r i , String имяКлипа) URL g e t C o d e B a s e () URL g e t D o c u m e n t B a s e () Image getImage(URL u r i ) Image getImage(URL u r i , String имяИзображ ения) Locale getLocale(] String getParameter(String имя Параметра b)bВызывается браузером непосредственно перед уничтожением аплета. Ваш аплет переопределяет этот метод, если нуждается в выполнении некоторых действий по очистке перед уничтожением Возвращает контекст доступности для вызывающего объекта Возвращает контекст, ассоциированный с аплетом Переопределенные версии этого метода должны возвращать строку, которая описывает аплет. Реализация по умолчанию возвращает значение Возвращает объект интерфейса AudioClip, инкапсули рующий аудиоклип, находящийся вместе, заданном u r Возвращает объект интерфейса AudioClip, инкапсули рующий аудиоклип, находящийся вместе, заданном uri, и имеющий имя, указанное имяКлипа Возвращает URL, ассоциированный с вызывающим аплетом Возвращает URL документа HTML, вызвавшего аплет Возвращает объект класса Image, инкапсулирующий графическое изображение, найденное вместе, указанном параметром u r Возвращает объект класса Image, инкапсулирующий графическое изображение, найденное вместе, указанном параметром u r i , и имеющий имя, указанное параметром им яИ зображ ени я Возвращает объект класса Locale, используемый различными классами и методами, чувствительными к региональным данным Возвращает параметр имяПараметра. Если указанный параметр не найден, возвращается значение null 6 9 Часть II. Библиотека Окончание табл. 22.1 Метод Описание S t r i n g [] [] g e t P a r a m e t e r l n f o () v o i d init() b o o l e a n isA cti v e( ) b o o l e a n i s V a l i d a t e R o o t () s t a t i c fina l A u d i o C l i p n e w A u d i o C l i p ( U R L u r l ) v o i d p l a y ( U R L u r l ) v o i d p l a y ( U R L u r l , S t r i n g им яК липа раз м ) v o i d r e s i z e ( i n t ширина высота e t S t u b объект Загл g строка Метод, переопределяющий данный метод, должен возвращать строковую таблицу, описывающую параметры, распознаваемые аплетом. Каждое вхождение в таблице должно состоять из трех строк, содержащих имя параметра, описание его типа и или диапазона также все необходимые пояснения. Реализация по умолчанию возвращает значение nul Вызывается при запуске выполнения аплета. Это — первый метод, вызываемый аплетом Возвращает значение true, если аплет запущен. Возвращает значение false, если аплет был остановлен Возврат значения t r u e указывает, что аплет проверяет корень. (Добавлено в JDK Возвращает объект интерфейса AudioC l i p , инкапсу лирующий аудиоклип, который расположен вместе, указанном параметром u r l Этот метод подобен методу get A u d i o C l i p () , за исключением того, что является статическими может быть выполнен без объекта класса A p p l e Если аудиоклип найден вместе, указанном u r l он вы полняется Если аудиоклип по имении м яК липа найден вместе, указанном u r l он выполняется Изменяет размер аплета согласно измерениям, указанным враз м . D i m e n s i o n — это класс, находящийся внутри файла j a v a . awt. Он содержит два целочисленных поля — w i d t h и h e i g h Изменяет размер аплета согласно размерностям, указанным параметрами ширина ивы сот а Делает объект Загл заглушкой (stub) для аплета. Этот метод применяется исполняющей системой и никогда не вызывается непосредственно вашим аплетом. Заглушка — это небольшой фрагмент кода, который обеспечивает связь вашего аплета с браузером Отображает строка в строке состояния окна браузера или средства просмотра аплетов. Если браузер не поддерживает окна состояния, то ничего не происходит Вызывается браузером, когда аплет должен начать (или возобновить) выполнение. Автоматически вызывается после метода init () вначале работы аплета Вызывается браузером для приостановки выполнения аплета. Будучи остановленным, аплет перезапускается вызовом метода s t a r t Таким образом, класс A p p le t обеспечивает всю необходимую поддержку деятельности на основе окон. (Библиотека AWT будет подробно рассматриваться в последующих главах Архитектура аплетов Как правило, аплет (applet) — это оконная программа с графическим интерфейсом, и потому его архитектура отличается от архитектуры консольных программ, показанных в части I нашей книги. Если вы уже знакомы с программированием графического интерфейса, то при написании аплетов почувствуете себя буквально, как дома. Если же нетто вы должны понимать некоторые концепции, которые будут описаны ниже. Во-первых, аплеты управляются событиями. Хотя мы не будем рассматривать обработку событий до следующей главы, важно понимать в общем, как управляемая событиями архитектура влияет на дизайн аплетов. Аплет включает в себя набор служебных процедур, обрабатывающих прерывания. Вот как это работает. Аплет ожидает, пока не произойдет событие. Исполняющая система извещает аплет о событии, вызывая обработчик события, предоставленный аплетом. Как только это случилось, аплет должен предпринять соответствующие действия и немедленно возвратить управление. Это — важнейший момент. Большей частью, ваш аплет не должен входить в режим операций, в которых он будет удерживать управление в течение длительного периода. Вместо этого он должен выполнить определенные действия в ответ на события, а затем вернуть управление исполняющей системе. В тех ситуациях, когда вашему аплету нужно выполнять какое-то повторяющееся действие (например, отображать в окне прокручивающееся сообщение, следует запустить дополнительный поток выполнения. (Далее в настоящей главе вы увидите соответствующий пример.) Во-вторых, пользователь инициирует взаимодействие с аплетом — и никакого пути в обход Как вызнаете, в неоконных консольных программах, когда программе необходим ввод, она выводит приглашение пользователю, а затем вызывает некоторый метод ввода, например метод readLine () . В аплетах все работает не так. Вместо этого пользователь взаимодействует с аплетом, как он желает и когда хочет. Эти взаимодействия отсылаются аплету в виде событий, на которые тот должен отреагировать. Например, когда пользователь щелкает кнопкой мыши внутри окна аплета, передается событие щелчка. Если пользователь нажимает клавишу, когда окно аплета имеет фокус ввода, передается событие нажатия клавиши. Как вы увидите в последующих главах, аплеты могут содержать различные элементы управления, такие как экранные кнопки и флажки. Всякий раз, когда пользователь взаимодействует с одним из этих элементов управления, происходят события. Архитектуру аплетов понять не так просто, как архитектуру консольных программ, однако Java облегчает это, насколько возможно. Если выписали консольные программы под Windows (или другие операционные системы с графическим интерфейсом, то знаете, насколько устрашающе может выглядеть эта среда. К счастью, Java предоставляет в ваше распоряжение намного более ясный подход, которым можно овладеть гораздо быстрее. Шаблон аплета Все аплеты, кроме наиболее тривиальных, переопределяют методы, обеспечивающие базовые механизмы взаимодействия браузера или средства просмотра аплетов с самим аплетом и управляющие его выполнением. Четыре из этих методов — init ( ) , start ( ) , stop () и destroy () — применимы ко всем аплетам; они определены в классе Applet. Предусмотрены реализации по умолчанию всех этих методов. Однако в их переопределении не нуждаются лишь очень простые аплеты. |