Эта завершающая лекция содержит рекомендации по установке web-приложений, написанных на языке Java, в соответствии с последними выпущенными SUN интерфейсами API для сервлетов Java и JSP-страниц.
Ниже перечислены ресурсы, согласованная работа которых требуется, чтобы запустить на web-сервере сервлет Java или JSP-приложение:
HTML-страницы;
ресурсы мультимедиа;
файлы классов сервлетов Java;
совместно используемые библиотечные файлы Java;
файлы JSP;
параметры инициализации сервлетов;
параметры безопасности;
доступ к базам данных.
В ранних реализациях API для сервлетов Java не было указано, как организовать все эти ресурсы, поэтому производители создавали собственные системы. По мере того как сложность web-приложений возрастала, пользовательские интерфейсы для установки и управления приложениями становились весьма запутанными. Например, старая версия процессора сервлетов JRun, на одно поколение опередившая версию API 2.2, содержала 259 файлов с расширением .properties, разбросанных по системе папок, с трудом поддававшейся пониманию и напоминающей лабиринт.
Компания Sun вынуждена была разобраться с этой проблемой, работая над пользовательскими и программными интерфейсами J2EE (Java 2 Enterprise Edition — редакция Java 2 для корпоративных программных систем на базе Java) и EJB (Enterprise JavaBean — JavaBean для корпоративных систем). Первые выпуски этих технологий требовали создания дескриптора развертывания (deployment descriptor) для каждого интерфейса EJB. Такой механизм был неудобным и трудным для понимания.
Следующая версия EJB была полностью изменена компанией Sun по сравнению с предыдущей. В версии EJB 1.1 за передачу параметров установки при запуске отвечает специальный документ XML. Тот факт, что компания Sun проявила готовность полностью отказаться от существовавшего интерфейса API и предпочла решение, основанное на XML, еще раз подчеркивает значимость языка XML.
Спецификация 2.2 сервлетов Java достаточно подробно развивает концепцию web-приложений. Web-приложение — это совокупность сервлетов, классов Java, JSP-страниц, HTML-страниц и других ресурсов, которые могут объединяться в единое целое и выполняться в различных контейнерах. Чтобы это стало возможным, web-серверы не должны, как прежде, применять свои собственные схемы создания папок и инициализации; напротив, они должны выполнять определенные соглашения по установке, утвержденные Sun.
Изменения в API для сервлетов ясно говорят о том, что разработчики Java серьезно задумались о вопросах обеспечения безопасности как в отношении ограничения доступа извне, так и в отношении установки барьеров между различными web-приложениями, а также внутри самих приложений. Например, в более ранних версиях API метод getServletNames из класса ServletConext позволил бы одному сервлету определить имена всех сервлетов, выполняющихся в конкретной папке приложения. Метод getServlet затем мог бы получить ссылку на фактический объект сервлета. Также имелся метод getServlets, который возвращал перечень всех экземпляров сервлетов.
Все эти методы в версии API 2.2 считаются устаревшими и больше не возвращают полезную информацию. Все программисты, разрабатывающие сервле- ты, теперь должны специально заботиться о том, чтобы обеспечить их взаимодействие. Если, например, какой-либо объект требуется всем сервлетам данного приложения, его следует присоединить к объекту ServletContext с помощью метода setAttribute, поскольку именно объект ServletContext совместно используется всеми сервлетами приложения.
Если вы привыкли задействовать статические методы и переменные класса, чтобы обеспечить совместное использование приложениями определенных ресурсов, вы должны учитывать, что в версии API 2.2 у каждого web-приложения на сервере имеется собственный загрузчик классов. Это означает, что невозможно организовать с помощью статических методов и переменных совместное использование web-приложенями каких бы то ни было ресурсов.
На этап определения web-приложения API сервлетов не накладывает никаких ограничений. Производители имеют полную свободу в создании собственных систем для определения контекста приложения на сервере. Сервер Tomcat использует файл server.xml для определения элемента ContextManager, содержащего многочисленные элементы Context. Многие из основных серверных функций определены в элементах Context, и они также задействуются для определения web- приложений. Например, ниже мы приводим элемент Context, который мы использовали для данной книги:
<Context path="/XMLbook" docBase="webapps/XMLbook" debug="0"
reload,able="true" > </Context>
Таким образом, относительно исходной папки сервера устанавливается корневая папка в физической структуре файлов, которую web-сервер использует для приложения XMLbook. Папки, входящие в корневую папку, требуются серверу для хранения HTML-страниц, JSP-страниц и других ресурсов, связанных с этим приложением, как будет показано в следующем разделе.
Также вы можете определить параметры, которые будут доступны всем серв- летам или JSP-страницам данного приложения через объект ServletContext. Ниже приводится пример применения элемента Parameter:
<Context path="/XMLbook" docBase= "webapps/XMLbook" debug="0"
reloadable="true" >
<Parameter name="workdir" value="e \\scnpts\\XMLgifts" /> </Context>
В Tomcat используется соглашение о том, что корневая папка вашего приложения и ее вложенные папки по умолчанию содержатся во вложенной папке ROOT, как указано в следующем объявлении Context:
<Context path="" docBase="webapps/ROOT" debug="0"
reloadable="true" > </Context>
Папка ROOT содержит файл index.html, который автоматически отображается при вводе URL-адреса, например такого: http://localcost:8080/.
Атрибут doBase определяет базовое расположение файлов приложения относительно установочной папки Tomcat. Предположим, что установочная папка — c:\tomcat, тогда сервер предоставляет по умолчанию папку webapps для установки ваших web-приложений и полный путь к файлам приложения выглядит следующим образом:
с: \tomcat\webapps\XM Lbook
Поступающие на web-сервер запросы, в которых используются URL-адреса типа hhtp://localhost/XMLbook, будут обслуживаться в физической структуре папок относительно указанного пути. Например, пусть пользователь запрашивает файл, указывая следующий URL-адрес:
http://localhost/XMLbook/catalog/index.html
Тогда web-сервер направит этот запрос в физический файл по адресу:
c:\tomcat\webapps\XMLbookcatalog\index.html
Естественно, все запросы на таблицы стилей, файлы изображений и другие ресурсы будут выполняться подобным образом Здесь мы подходим к рассмотрению файла класса (class file), который используется апплетами Java и часто является причиной непонимания. Поскольку файл класса должен быть отправлен web-браузеру, как любой другой ресурс, класс апплета, или JAR-файл, должен храниться с простыми HTML-файлами, а не с файлами классов, используемыми сервлетами.
Чтобы отделить файлы классов и библиотеки классов, используемые приложением, от простых HTML-страниц, файлов изображений, файлов классов апп- летов и других ресурсов, в версии API 2.2 для сервлетов требуется, чтобы в папке приложения имелась вложенная папка WEB-IN F. Web-серверу запрещается посылать любые ресурсы из этой папки в ответ на запрос пользователя.
Если приложение было разработано как WAR-файл (более подробно мы поговорим об этих файлах позже), то должна присутствовать папка с именем МЕТА- INF. Смысл здесь в том, что данная папка будет содержать дополнительную информацию о приложении. Как и в отношении папки WEB-INF, web-сервер не имеет права отправлять пользователю любые содержащиеся в этой папке ресурсы.
В папке WEB-INF для web-приложения должен содержаться дескриптор развертывания в виде файла с именем web.xml. Этот файл должен быть согласован с опубликованным компанией Sun определением DTD для дескриптора развертывания web-приложения.
Все файлы классов сервлетов Java, уникальные для данного web-приложения, включая классы, используемые JSP-страницами, должны развертываться во вложенной папке classes, если они получены в виде отдельных файлов классов. В этой папке сохраняется обычная иерархия пакетов, так что, например, файл класса для сервлета QanalysnsServ из пакета com.XmlEcomBook.Chap()? будет содержаться в следующей вложенной папке основной папки приложения:
WEB-INF/classes/com/XmIBook/QanalysisServ.class
Альтернативой хранению отдельных файлов классов во вложенной папке classes является создание библиотеки файлов .jar. Файлы .jar, расположенные в папке WEB-INF/lib, доступны виртуальной машине Java при загрузке классов и других ресурсов для web-приложения. Заметим, что файлы .zip в этой папке будут игнорироваться, поэтому следует использовать файлы с расширением .jar.
Общие классы и наборы инструментальных средств, которые должны быть доступны для всего web-сайта, могут развертываться обычным для Java способом с использованием стандартных настроек путей классов. Не существует способа разрешить совместное использование какого-либо класса только избранным приложениям; доступ к классу разрешен либо только одному приложению, либо всем.
Дескриптор развертывания web-приложения
В API сервлетов имеются спецификации, которые на основе составленного компанией Sun определения DTD идентифицируют сведения, содержащиеся в дескрипторе развертывания приложения. В листинге 10.1 показана часть файла web.xml, который использовался для некоторых сервлетов, описанных в этой книге.
Листинг 10.1. Часть файла web.xml для web-приложения (web.xml)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc. //DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app> <servlet><servlet-name>cattest</servlet-name> <servlet-class>com.XmlEcomBook.catalog.CatalogTestServ </servlet-class> </servlet> <servlet><servlet-name>catalog</servlet-name> <servlet-class>com.XmlEcomBook.catalog.CatalogServ </servlet-class> <init-param> <param-name>workdir</param-name> <param-value>e:\\scripts\\XMLgifts</param-value> </init-param> </servlet>
В листинге 10.2 показана начальная часть файла web.dtd из версии 2.2 API сервлетов. Полная копия файла, содержащая более 400 строк, имеется на прилагаемом к книге компакт-диске.
Листинг 10.2. Часть DTD для web-приложений, в которой показаны элементы первого уровня (web.dtd)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- The web-app element is the root of the deployment descriptor for a web application -->
<!ELEMENT web-app (icon?, display-name?, description?, distributable?, context-param*, servlet*, servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?, error-page*, taglib*, resource-ref*, security-constraint*, login-config?, security-role*, env-entry*, ejb-ref*)>
Как видно по именам элементов в листинге 10.2, большое количество параметров конфигурации web-приложения можно устанавливать из файла web.xml. Эти параметры удобно разделить на следующие категории:
параметры инициализации ServletContext;
конфигурация HttpSession;
определение и отображение сервлетов и JSP-страниц;
отображение типов MIME;
стандартные страницы с приветствием;
страницы ошибок;
параметры безопасности.
Использование параметров каждой из этих категорий подробно описано в официальном руководстве по API сервлетов, поэтому здесь мы не будем рассказывать обо всех параметрах.) Наиболее вероятно, что из всех этих параметров вам потребуются только параметры для определения и отображения сервлетов и JSP-страниц. Например, рассмотрим следующий фрагмент листинга 10.1:
<servlet><servlet-name>catalog</servlet-name>
<servlet-class>com.XmlEcomBook.catalog .CatalogServ</servlet-class> <init-param> <param-name>workch r</param-name> <param-value>e:\\scMpts\\XMLgTfts</param-val.ue> </init-param> </servlet>
Этот фрагмент отображает класс сервлета в папку имен и создает один параметр инициализации с именем workdir и значением е: \\scripts\\XMLgifts. Здесь используется символ \\, так как одна косая черта \ играет роль управляющего символа для строк Java.
Правила организации папок для web-приложений, заданные в API сервлетов, позволяют определить формат архивного файла, в котором будут содержаться все ресурсы, необходимые для работы приложения. Согласно терминологии Sun, такой формат называется WAR, или Web Application Archive (архив web-приложения). Фактически это такой же формат, как хорошо знакомый формат JAR. Идея заключается в том, что созданный поставщиком программного обеспечения WAR-файл, содержащий web-приложение, можно поместить в файловую систему любого подходящего сервера, и он автоматически распакуется, образуя определенную структуру папок приложения.
Эта автоматическая распаковка происходит тогда, когда при запуске сервера обнаруживается появление нового WAR-файла. За распаковку архива отвечает web-сервер.
Сейчас, когда пишется эта книга, уже выпущена следующая версия API сервлетов, под номером 2.3. Пока она проходит стадию проверки, но к моменту, когда наша книга будет опубликована, эта версия, вероятно, получит официальный статус. Организация Apache работает над версией 4 сервера Tomcat, в котором будут реализованы и API 2.3 для сервлетов, и API 1.2 для JavaServer Pages. Эта новая версия потребует поддержки пакета JDK 1.2 или более поздней его версии.
К добавленным новым средствам относятся фильтры (filters) и слушатели событий (event listeners). Фильтры — это классы Java, которые могут модифицировать содержание запроса перед тем, как он будет передан сервлету, или содержимое ответа, сгенерированного сервлетом. Например, фильтры могут расшифровать запрос или зашифровать ответ. Другой возможностью является применение XSLT-трансформации к данным XML, сгенерированным сервлетом.
Слушатели событий предназначены для того, чтобы дать программисту больше возможностей для контроля над приложением как над единым целым. Например, слушатель событий может получать извещения каждый раз, когда какой-нибудь сервлет меняет атрибут в объекте Servl etContext.
Следующее поколение спецификации JavaServer Pages предлагает пользователям XML некоторые замечательные нововведения. Этот стандарт определяет, как компилятор JSP будет создавать для каждого документа JSP в точности эквивалентный ему документ XML. Более того, компилятор JSP будет способен принимать входные данные как в виде разметки JSP, так и в виде документа XML. Ожидается, что это изменение будет способствовать развитию современных инструментальных средств создания и поддержки JSP.
В плане обеспечения безопасности также произошли некоторые усовершенствования. Ее реализация в версии API 2.3 сервлетов основана на архитектуре платформы Java 2, поэтому в ней возможно очень тонкое разграничение функций обеспечения безопасности.
В версии API 2.3 сервлетов рекомендуется, но не требуется, поддержка HTTP 1.1. Это означает, что методы сервлетов должны поддерживать запросы PUT, DELETE, OPTIONS и TRACE. Тем не менее предполагается, что эти нововведения в API сервлетов и JSP не нарушат работу приложений, написанных согласно стандартам API 2.2 сервлетов и API 1.1 JSP.
Версия Tomcat 3.1, которую мы здесь используем, работает с анализатором Sun JAXP 1.0, реализующим только интерфейсы SAX 1.0 и API первого уровня DOM. Версия 1.1 анализатора JAXP будет поддерживать второй уровень DOM и версию 2.0 SAX. Многие изменения всего лишь упрощают настройку характеристик анализатора, но некоторые из них добавляют существенно новые возможности.
В JAXP 1.1 будет включен новый пакет javax.xml .transform для определения интерфейсов, поддерживающих трансформацию данных XML на основе таблиц стилей. В числе других свойств можно выделить создание более обобщенных анализаторов, манипулирование пространствами имен и упрощение настройки многих параметров анализатора.
Если вас интересуют эксперименты с последними новшествами, связанными с поддержкой XML в Java, то в процессе подготовки проекта анализатора Xerces организация Apache продолжает рассматривать новые предложения. Многие из предложенных дополнений находятся в различных стадиях разработки, так что анализатор Xerces является не законченным продуктом, а скорее рабочим проектом. Подробную информацию вы найдете на сайте http:// xml.apache.org/xerces-j/.
Протокол SOAP (Simple Object Access Protocol) — это важный для web-приложений протокол, к которому проявляют огромный интерес программисты, работающие с XML. SOAP определяет стандарты для кодирования различных типов данных и соглашений о представлении вызывающих методов в удаленных объектах. Это «легкий» (light-weight) протокол для обмена сообщениями между объектами в распределенной среде. С использованием XML и передачи простого (plain) текста через стандартный порт HTTP сообщения SOAP могут передаваться через брандмауэры.
SOAP пользуется широкой поддержкой в компьютерной промышленности и считается главной частью оболочки .NET для распределенных вычислений корпорации Microsoft. Поддержка этого стандарта была возложена на консорциум W3C.
О каком бы приложении ни шла речь в нашей книге, всегда предполагалось, что имеется только один компьютер, на котором работает один процессор сервлетов Java. Учитывая, что тактовая частота типичного центрального процессора и объем памяти серверов растут почти так же быстро, как и сам Интернет, упомянутое предположение является разумным для серверов, обслуживающих до нескольких тысяч запросов в секунду, в частности еще и потому, что Java хорошо работает в серверных конфигурациях с несколькими центральными процессорами.
Однако в случае головокружительного успеха вашего сайта вам, возможно, придется предусмотреть возможность нехватки ресурсов одного сервера для того, чтобы справиться с возросшей нагрузкой. Помимо увеличения нагрузки есть и еще одна причина, по которой стоит использовать больше одного сервера, — это повышает надежность вашей системы.
Использование двух или более различных машин в сети для одного и того же сайта часто называется объединением в кластеры, или кластеризацией (clustering). В такой системе имеется один препроцессор, который переадресует запросы одному из серверов в зависимости от некоторого критерия.
Сохранность информации о сеансе
Самая большая проблема при разделении нагрузки между несколькими машинами связана с приложениями, которые должны отслеживать состояние пользователя. В приложении «корзина покупателя» мы использовали объект HttpSession, управляемый контейнером сервлетов, чтобы сохранять объект ShoppingCart в промежутках между циклами запрос-ответ. К сожалению, управление объектом HttpSession осуществляется целиком внутри одного объекта ServletContext в одной виртуальной машине Java. Чтобы в условиях кластеризации данные корзины покупателя оставались актуальными в течение всего времени, пока пользователь находится на вашем сайте, в системе должна применяться одна из приведенных ниже технологий.
Каждый запрос данного пользователя нужно направлять на одну и ту же машину, для этого в каждом запросе нужно отслеживать специальные данные, например файл cookie, содержащий идентификатор сеанса в строках заголовка, или IP-адрес пользователя. Недостаток данного способа заключается в том, что он неустойчив к сбоям, так как информация о сеансе хранится только на одной машине.
Можно направлять запрос каждого пользователя в определенную машину, как и в первом способе, но создавать запасную копию каждого сеанса для того, чтобы, если сбой происходит на одной машине, информация о сеансе могла быть восстановлена.
Можно распределять информацию о сеансе по всем системам, входящим в кластер, — тогда будет безразлично, какая система получит запрос.
Другое соображение, говорящее в пользу кластеризации, — балансировка нагрузки, так что все машины примерно поровну задействуют свои ресурсы. Отдельные машины должны иметь возможность сообщать распределителю запросов насколько они заняты.
Система J2EE (Java 2 Enterprise Edition), включающая библиотеки, наборы инструментальных средств и интерфейсов API, — это редакция среды разработки Java, ориентированная на создание многоуровневых крупномасштабных web-приложений. Как показано на рис. 10.1, в подобных web-приложениях действия сер- влетов Java и JSP-страниц сводятся к созданию пользовательского интерфейса, в то время как «конечными» процессами, связанными с бизнес-логикой и доступом к базам данных, управляет Enterprise JavaBean (EJB) — интерфейс API, основанный на Java.
EJB работает в специализированной среде — контейнере EJB, аналогично тому, как сервлеты работают в контейнере сервлетов. Но контейнер EJB может выполнять и многие другие функции для вашего приложения. К этим функциям относятся сохранение данных сеанса и осуществление транзакций в базах данных. Теоретически контейнер EJB отвечает за все вопросы масштабирования.
Альтернативное решение — Spaces
В отличие от жестко структурированной среды J2EE в концепции Spaces web- приложение создается как слабосвязанная система. Эта концепция несколько лет обсуждалась в академических кругах, а недавно было найдено новое ее применение. Проект JINI, разработанный Sun для связи между распределенными приложениями, использует новый интерфейс API JavaSpaces.
Приложения, взаимодействующие через JavaSpaces, обмениваются сообщениями не напрямую, а посредством специального приложения, которое управляет пространством сообщений. Сообщения содержат данные (объекты Java) и идентифицирующие пометки, которые требуются, чтобы сопоставить заданию соответствующее приложение, способное это задание выполнить. Приложение, отправившее сообщение в пространство сообщений, может быть проинформировано о том, что посланный им объект прошел требуемую обработку. Сравнивая эту ситуацию с той, в которой имеется специальный диспетчер, назначающий задания приложениям, мы видим, что взаимодействие, основанное на использовании пространства сообщений, автоматически распределяет нагрузку между различными системами более равномерно.
Например, программа «корзина покупателя» может отправить сообщение, представляющее содержимое корзины, с меткой, которая означает запрос о подсчете стоимости доставки заказа покупателю. Программа подсчета стоимости доставки, ожидающая очередного запроса, получает этот объект, выполняет необходимые вычисления и возвращает заполненный объект в пространство сообщений.
Тем, кто ищет подробную информацию о программировании в соответствии с концепцией пространства сообщений JavaSpace, можно предложить в качестве исходного пункта следующий адрес:
http://java.sun.com/products/javaspaces/