Интерфейс HttpSession содержится в пакете javax.sevlet.http. В табл. 4.1 перечислены методы этого интерфейса согласно версии API 2.2 сервлетов.
Заполнение корзины покупателя
Вы наверняка хотели бы, чтобы посетители вашего web-сайта могли легко находить интересующие их товары, добавлять их в корзину и производить оплату, в соответствии со своим интуитивным представлением об этих действиях как о неразрывно связанных этапах покупки товара. К сожалению, основные используемые в настоящее время HTTP- и web-протоколы не позволяют обеспечить эту неразрывность. В настоящей главе исследуется закулисная работа, необходимая для того, чтобы пользователи могли без затруднений приобретать товары в вашем электронном магазине.
Как видно из листинга 4.4, в классе CatalogServ имеется некоторое количество статических переменных, которые определяют различные ресурсы Мы приводим типичные значения этих переменных В реальном сервлете эти значения заменяются специфичными для системы значениями, хранящимися в файле catalog.properties, откуда они считываются методом imt Мы будем использовать класс Properties — расширение класса Hashtable из пакета java.util, где содержатся очень удобные методы для загрузки текстовых параметров из файла
Как вспомогательное средство для управления системными ресурсами, которые могут быть задействованы в сеансах, и как средство отладки в API сервлетов предусмотрены интерфейс HttpSessionBindingListener и класс HttpSessionBinding- Event. В этом интерфейсе определены два метода.
void valueBoundCHttpSessionBindingEvent event). Когда объект, реализующий интерфейс HttpSessionBindingListener, присоединяется к сеансу HttpSession, вызывается данный метод. Параметр этого метода event передает двоякую информацию — имя, которое было использовано для присоединения объекта к сеансу, и идентификатор сеанса (объект типа String).
void valueUnbound(HttpSessionBindingEvent event). Этот метод вызывается, когда объект должен быть удален из сеанса. Обычно это происходит, когда в результате простоя выполняется метод invalidate класса HttpSession и сеанс становится недействительным.
В сервлете catalogServ мы демонстрируем использование этого интерфейса для выполнения простых операций по отладке.
Поскольку процессор сервлетов во многом определяет поведение объекта HttpSession, решение проблем отладки, связанных с сеансами, может оказаться непростым делом. API сервлетов предоставляет интерфейс HttpSessionBindingListener и класс HttpSessionBindingEvent для решения проблем отладки и для управления ресурсами, которые могут быть присоединены к объекту HttpSession.
В листинге 4.13 показан простой пример использования этого интерфейса в классе CartLi stener, который является внутренним по отношению к классу Catalog- Serv. В этом примере мы просто записываем системное время присоединения объекта к объекту HttpSession, и затем, когда сеанс закрывается, печатаем время жизни объекта. Объект CartLi stener присоединяется к объекту ShoppigCart, когда он создается в первый раз методом doPost (см. листинг 4.5).
Как показано в листинге 4.14, CatalogBean создает объект Cartltem для некоторого товара на основе информации, содержащейся в экземпляре cat класса TheCatalog.
Метод doCartLnst, приведенный в листинге 4 14, контролирует вывод всех объектов Cartltem, содержащихся в экземпляре класса ShoppingCart Форматирование таблицы осуществляется методом doShowCart класса CatalogServ Метод doCartList обеспечивает отображение каждого заказанного товара в отдельной строке таблицы HTML, а также отображение количества заказанных экземпляров (numeberOrdered) для каждого из них Типичная страница, показывающая содержимое корзины покупателя, представлена на рис 4 6
Процессор сервлетов Java (который иногда называют контейнером сервлетов) управляет коллекцией объектов, реализующих интерфейс HttpSession. Наша программа может использовать один из этих объектов для хранения любой информации, необходимой при создании корзины покупателя. Каждый объект HttpSession имеет идентификатор (id), представляющий собой строку, которая создается одновременно с объектом и гарантированно является уникальной. Этот уникальный идентификатор создается одним из двух возможных методов.
Мониторинг файлов cookie. Значение идентификатора отсылается на web- браузер пользователя как заголовок файла cookie, сгенерированного объектом HttpServl etResponse. Стандартное имя такого файла cookie — jsessionid, а значением может быть строка, подобная следующей: "97187996250188366", то есть просто случайное число, генерируемое процессором сервлетов. Это значение автоматически считывается при поступлении следующего запроса от того же пользователя, так что наша программа просто запрашивает объект HttpSession, принадлежащий данному пользователю.
Перезапись URL. Значение идентификатора присоединяется к каждому URL-адресу, который посетитель сайта может использовать для отправки запроса на сервер. Поскольку сюда входят также URL-адреса, которые являются частью статических шаблонов или динамически генерируемого текста, программист должен приложить дополнительные усилия, чтобы гарантировать, что все URL-адреса будут переписаны.
Чтобы не усложнять наш пример, в сервлете, реализующем корзину покупателя, мы будем использовать подход с мониторингом файлов cookie:
HttpSession session = req.getSession(true); if( session.isNew() ){ System.out.print("Session is new " + session.getld() ); }Этот простой фрагмент кода метода doPost формирует объект HttpSession для данного пользователя. Переменная req является объектом класса HttpServl etRequest. Булева постоянная true в вызове метода getSession указывает процессору сервлетов, что нужно создать новый объект сеанса, если в пользовательском запросе отсутствует соответствующий идентификатор. Вторая строка содержит метод isNew, позволяющий определить, является ли данный сеанс новым или клиент (браузер) уже участвовал в сеансе.
В интерфейсе API для JSP-страниц переменная класса HttpSession называется session, поэтому желательно и в сервлетах для таких переменных использовать именно это имя. Теперь можно перейти к краткому обзору интерфейса API, который используется при работе с объектом HttpSession.
Как вы уже, вероятно, заметили при обсуждении методов класса CatalogServ, вся основная работа по созданию форматированного отображения информации о товарах выполняется методами класса CatalogBean. Эти методы форматирования выделены из сервлета в отдельный класс для того, чтобы упростить реализацию функций каталога в технологии JavaServer Pages. В этой главе мы за недостатком места не приводим JSP-версию каталога, а технологии JSP посвящена глава 5.
Большинство методов класса CatalogBean, используемых в этой главе, остались такими же, как в главе 3. Наиболее значительные изменения касаются объектов ShoppingCart и Cartltem. Напомним, что в CatalogBean имеется статическая переменная для объекта TheCatalog, который управляет объектной моделью документа, созданной на основе каталога (файла XML). В обновленной версии CatalogBean мы сделали эту переменную закрытой (private) и предложили следующий метод доступа:
private static TheCatalog cat ; static void setTheCatalog( String path, String name ){ File f = new File( path, name ); cat = new TheCatalog( f, null, null ); cat.scanCatalog(); } static TheCatalog getCat(){ return cat ; }Мы также добавили статическую переменную resoursePath и метод setResourse- Path, который задает значение этой переменной при инициализации сервлета:
private static String resourcePath ; // используется для // изображений, звуковых // файлов и т.д. static void setResourcePath( String s ){ resourcePath = s ; }
Класс, который мы написали для отображения элементов каталога и манипулирования корзиной покупателя (классом ShoppingCart), называется CatalogServ. Здесь мы используем усовершенствованные версии классов для представления каталога сети, описанных в главе 3, и добавляем функции для организации корзины покупателя и мониторинга сеанса. Возможности сервлета CatalogServ перечислены ниже.
Отображение компактных списков товаров каталога с использованием критерия отбора, в частности: полный каталог; товары одной серии; товары, связанные с определенным ключевым словом (результат поиска по ключевому слову). Отображение детальной информации о товаре, дополненное следующими функциями: добавление данного товара в корзину; изменение количества заказанных экземпляров. Отображение списка выбранных на текущий момент товаров.Для простоты будем считать, что заказ товара (добавление его в корзину и изменение количества заказанных экземпляров) может происходить только на странице с подробной информацией о данном товаре.
Кроме того, наш сервлет не будет выполнять никаких других функций, свойственных обычному коммерческому сайту. Как показано на рис. 4.1, наш сервлет просто размещает текст «Your site navigation could go here» [Здесь может быть расположен интерфейс для навигации по вашему сайту. — Примеч. перев. ], в то время как в этом месте обычного коммерческого сайта, как правило, находятся логотипы и навигационный интерфейс.
Мы добавили множество методов в класс ProductFormatter, описанный в главе 3. Вообще говоря, эти методы просто расширяют те возможности, которыми уже обладал этот класс. В листинге 4.16 показаны статические переменные, которые определяют два различных стиля. «Краткий» (short) стиль используется для отображения списков товаров (всего каталога или одной серии), а полный (full) стиль используется в методе doFullItem класса CatalogBean для отображения полной информации об одном товаре. Также мы создали коллекцию fieldHash, которая связывает названия товаров с целочисленными константами.
Минимальным требованием к объекту, представляющему товар в корзине покупателя, является наличие идентификатора данного товара и количества заказанных экземпляров. Название товара, его цену и другие сведения можно найти в каталоге — документе XML. Но мы решили не ограничиваться минимальными требованиями и добавили в Cartltem название товара, цену и информацию по доставке, как показано в листинге 4.1.
Следует отметить несколько важных моментов, касающихся класса Cartltem. Во-первых, конструктор работает непосредственно с объектом El ement структуры DOM, представляющим данный товар. Это упрощает добавление различных дополнительных переменных в XML-каталог. Во-вторых, класс Cartltem реализует интерфейс Serializable. Это позволяет посылать коллекцию объектов Cartltem, представляющую собой список заказанных товаров, другой программе Java, используя сериализацию данных. Сериализация также требуется, если процессору сервлетов приходится хранить сеанс или пересылать его на другой сервер. Наконец, названия методов доступа, например getld и setNumberOrdered, соответствуют соглашению об именах, принятому в JavaBeans, чтобы упростить использование объекта Cartltem в коде JSP-страницы.
В этой главе мы создадим сервлет, функции которого ограничены отображением каталога и оформлением заказа на товары. В реальном коммерческом сайте эти функции составили бы лишь небольшую часть всех возможностей, предложенных пользователю. В нашем примере новый объект класса HttpSession создается, когда сервлет CatalogServ в первый раз получает запрос от данного пользователя. В реальном виртуальном магазине сеанс может быть создан в другой части сайта.
Возможной «точкой входа» посетителя может быть просмотр всего каталога или списка товаров какой-либо одной серии или просмотр результатов поиска по ключевому слову. В любом случае, мы не создаем объект ShoppingCart до тех пор, пока пользователь не проявит достаточного интереса к товару, чтобы просмотреть его полное описание. В этот момент мы создаем объект Cartltem для просматриваемого товара непосредственно из его описания в документе XML и добавляем объект Cartltem в ShoppingCart, то есть в корзину.
Пока пользователь просматривает информацию о различных товарах, мы создаем объекты Cartltem для каждого выбранного товара и удаляем из корзины те товары, которые он раздумал покупать. На любой странице пользователь имеет возможность вернуться к полному каталогу, найти товар по ключевому слову, просмотреть содержимое корзины или перейти к оплате товара. Теперь рассмотрим детали реализации описанной функциональности.
Класс ShoppingCart достаточно прост, так как все, что от него требуется, — манипулирование объектами класса Cartltem. Как показано в листинге 4.2, мы храним ссылки на объекты Cartltem в двух местах — Vector и HashTable. Причина этого заключается в том, что порядок размещения ссылок в объекте HashTable непредсказуем и может меняться по мере добавления новых товаров. Представляется разумным хранить эти ссылки в предсказуемой и воспроизводимой последовательности в объекте Vector и в то же время иметь возможность доступа к товарам по их идентификаторам через хэш-таблицу.
Заметим, что класс ShoppingCart реализует интерфейс Serializable, так что вся корзина (то есть объект класса Shoppi ngCart) может пересылаться между программами Java или записываться в файл посредством сериализации.
В листинге 4.3 показаны остальные методы класса ShoppingCart. Поскольку мы храним ссылки на объекты Cartltem в двух коллекциях, для удаления элемента из объекта HashTable применяется метод removeByld с указанием идентификатора товара и затем вызывается метод removeEl eraent вектора items.
Заметим, что метод init вызывает два статических метода из класса CatalogBean. Вызов метода setTheCatal од необходим для считывания данных из файла XML, а метод setTheResoursePath устанавливает путь, который будет использоваться для нахождения таких ресурсов, как изображения товаров. Определения класса Gala- togBean вы найдете далее в этой главе в разделе «Класс CalatogBean».
В этом примере метод doPageTop очень прост, но в реальном коммерческом сайте этот метод можно использовать для отображения средств навигации по сайту и выполнения других функций.
В методах completeCatalog (листинг 4.8) и productLineCatalog (листинг 4.9) используется один и тот же подход к генерированию таблицы, содержащей соответствующий список товаров (либо полный, либо одну серию). Основное различие заключается в том, что в методе completeCatalog, как видно на рис. 4.1, в таблице имеются три столбца — по одному на каждую серию товаров. Для выбора одной из этих серий следует вызвать метод setlnitialSelect класса CatalogBean. В случае если у вас имеется более четырех серий товаров, следует искать какой- нибудь другой метод отображения каталога, так как таблица с пятью и более столбцами будет выглядеть не слишком хорошо.
Текст HTML, относящийся к конкретному товару, будет иметь вид, подобный следующему:
<а class="ch3" href="http://localhost/serviet/catalog?асtion= showproduct&id=bk0022">Этот код делает название товара активной ссылкой, которая отсылает параметры action и id сервлету, что ведет к отображению полной информации о данном товаре. Атрибут class контролирует тип, размер и цвет шрифта различных фрагментов текста путем выбора той или иной таблицы стилей из файла catalog.css.
Метод productLineCatalog, как показано в листинге 4.9, формирует таблицу, содержащую только один столбец. После того как внешний вид таблицы HTML определен, переменная line используется для вызова метода setlnitialSelect, который выбирает одну из серий товаров. Затем мы просто совершаем итерации по выбранному списку товаров и используем метод doListOutput для отображения форматированного текста HTML по каждому товару. Затем мы закрываем таблицу. Типичный результат представлен на рис. 4.3.
Если action = showcart, то вызывается метод doShowCart. Как показано в листинге 4.12, этот метод переписывает теги HTML, которые задают начало и конец таблицы. Строки таблицы заполняются с помощью метода doCartList класса CatalogBean.
В листинге 4.17 показано начало кода для методов и переменных экземпляра и конструктора ProductFormatter. Заметим, что конструктор задает формат в соответствии с переданной ему переменной frmt, которая может принимать значение "short" или "full".
Различные методы, вызываемые методом addText, приведены в листингах 4.21 и 4.22. Эти методы извлекают тот или иной текст из элемента product и добавляют его в Stri ngBuffer.
Служебный метод getChildrenText, приведенный в листинге 4.22, собирает вместе текст всех дочерних узлов данного элемента.
Метод addlmageTag, приведенный в листинге 4.23, использует информацию из тега XML <iraage>
. Ниже приводится пример из файла catalog.xml:
Помимо создания тега <img>
, который вставляет в HTML-страницу изображение, этот метод также проводит анализ и отображает подпись к изображению.
Формат нашего XML-каталога допускает использование стиля running_text в подписях и описаниях товаров. Методы addExtendedText и doExtendedTextEl ement, показанные в листинге 4.24, могут объединить весь текст описания или подписи с соответствующей разметкой HTML, чтобы создать абзац или назначить начертание этого текста (курсив или полужирный шрифт).
Метод addText, приведенный в листинге 4.20, вызывается некоторыми другими методами из класса ProductFormatter. Ему передается объект StringBuffer, в который добавляется текст. Параметр name определяет, какой именно текст требуется добавить, а элемент Element соответствует некоторому товару в каталоге. Целое число, являющееся значением параметра name, управляет точками перехода в инструкции switch.
Метод doListOutput (листинг 4.19) вызывается из CatalogBean для создания объекта типа String, содержащего форматированные данные по отдельному товару. Этот метод используется при конструировании таблицы, подобной приведенной на рис. 4.3. Обратите внимание, что мы создаем объект StringBuffer для построения строки (объекта String), поскольку добавление новых фрагментов в StringBuffer гораздо эффективнее, чем конкатенация (объединение) объектов String. Также заметим, что если методу передается переменная aLink, то текст, соответствующий элементу с индексом linkN, отображается в виде гипертекстовой ссылки.
В этом примере метод doPageEnd (листинг 4.6) просто создает набор активных ссылок в нижней части страницы. Ссылки на различные варианты представления каталога присутствуют всегда, но некоторые ссылки, связанные с корзиной покупателя, появляются, только если в корзину добавлены какие-либо товары. Обратите внимание, мы используем метод removeEmptyElements, чтобы гарантировать, что переменная nitem правильно отражает содержимое корзины.
Метод doPageMid управляет ответом сервлета на запрос пользователя. Значение параметра action определяет выбор метода представления, который, в свою очередь, генерирует требуемое представление. Как показано в листинге 4.7, последовательность инструкций if определяет, какой из методов вызывается.
Все запросы, выполняющиеся методом GET, просто перенаправляются методу doPost, как показано в листинге 4.5. Метод doPost объединяет стандартный раздел HEAD файла HTML и результаты выполнения трех методов — doPageTop, doPage- Mid и doPageEnd. Заметим, что обращение к методу getSession с параметром true приводит к созданию нового сеанса, то есть объекта HttpSession, если он еще не существует для данного пользователя.
Для того чтобы продемонстрировать методику отладки, мы проверим, является ли данный сеанс новым. Если сеанс окажется новым, мы присоединим объект CartListener и напечатаем идентификатор нового сеанса. Функции объекта CartLis- tener мы обсудим позже. Все инструкции, связанные с отладкой, будут удалены из финальной версии приложения, так как конструирование и вывод на печать объекта Date требуют больших затрат времени.
Теперь рассмотрим методы, которые используются для полного описания товара. Эти методы, приведенные в листинге 4.18, вызываются методом doFullItem класса CatalogBean.
Метод doShowProduct класса Catal ogServ отвечает за отображение полной информации об одном конкретном товаре. Существует несколько вариантов формата этого отображения в зависимости от наличия в X ML-каталoгe ссылки на изображение этого товара и от того, находится ли уже данный товар в корзине покупателя.
На рис. 4.4 приведено типичное представление, сгенерированное для товара, которого еще нет в корзине покупателя и для которого имеется изображение. Кнопка, расположенная в правом нижнем углу, предназначена для добавления в корзину этого товара. При щелчке на этой кнопке генерируется запрос к сервле- ту, параметр action принимает значение setcart, а параметр itemct — значение 1, в результате в корзине оказывается один экземпляр данного товара.
Для посетителей виртуального магазина интуитивно понятна аналогия «корзины покупателя» (shopping cart). Поэтому им кажется, что все должно происходить так же, как и в реальном магазине, где корзина, в которую они складывают выбранные товары, остается с ними в течение всего времени посещения магазина, пока они не подошли к кассе и не заплатили за покупки. К сожалению, то, что посетителю виртуального магазина представляется как протяженный во времени единый процесс просматривания информации, для web-сервера является последовательностью не связанных друг с другом запросов, поступающих от браузера, и высылаемых ему ответов. Так получается потому, что основные HTTP- протоколы неустойчивы, то есть не позволяют определить, что очередной запрос должен быть связан с предыдущим, поскольку оба запроса поступают от одного пользователя.
Задача сохранения информации в течение одного сеанса (то есть в течение времени посещения данным пользователем данного сайта) обычно называется задачей сеансового мониторинга (session-tracking). Существуют три способа решения этой задачи: файлы cookie, скрытые поля (переменные) формы и перезапись URL.
Файл cookie — это фрагмент текстовой информации, который ассоциируется браузером с адресом конкретного web-сайта Web-сервер посылает данные (cookie) вместе с ответом, а web-браузер хранит полученный текст. Каждый раз, когда web-браузер посылает запрос этому же web-серверу, файл cookie присоединяется к одному из заголовков сообщения, а сервер отыскивает и интерпретирует cookie. Текст файла cookie имеет хорошо знакомую вам форму атрибут = значение, похожую на имена и значения атрибутов XML.
Очень полезное свойство файла cookie заключается в том, что программист имеет возможность контролировать время жизни этого фрагмента данных. Вы можете создать файл cookie, который будет существовать только в течение одного посещения сайта пользователем, в течение фиксированного промежутка времени или иметь неограниченный срок действия. Коммерческие web-сайты часто используют файлы cookie с длительным сроком действия для того, чтобы запоминать пользователей, часто посещающих данный сайт.
Интерфейс прикладных программ (API) сервлетов Java предоставляет средства для того, чтобы посылать и принимать данные файлы cookie, и тем самым решает многие задачи мониторинга сеанса. Тем не менее здесь имеются определенные ограничения, связанные с тем, что web-браузер лимитирует объем текста, содержащегося в файле cookie, и общее число таких файлов, связанных с одним сайтом. Поэтому хранение всей информации о корзине пользователя в виде файла cookie непрактично, так что обычно в файле cookie хранится только уникальный идентификатор, который присваивается данному пользователю и используется как ключ для поиска на сервере требуемой информации об этом пользователе.
При использовании скрытых полей формы для мониторинга сеанса ваша программа должна заносить скрытые данные в каждую форму или ссылку на каждой HTML-странице. Например, если нам нужно отследить значение переменной customer Id, в каждой форме должен содержаться следующий элемент:
<input type="hidden" name="customerid" value="124c41">Кроме того, каждая ссылка должна включать в себя соответствующий фрагмент:
href= "http://Iocalhost/servlet/catalog?customerid=124c41"Здесь символ ? разделяет URL и строку запроса.
Значение customer id затем извлекается в методе сервлета doPost или doGet с помощью кода, подобного следующему:
String customerid = req.getParameter("customerid")В технологии, известной под названием перезаписи URL (rewriting URL), к каждому URL-адресу, идентифицирующему данный сеанс, добавляется дополнительная информация. Выбранный для этого формат не должен мешать web- серверу пересылать запрос на правильный сервлет, но сервлет должен иметь возможность обнаружить эту дополнительную информацию. В языке Java перезапись URL осуществляется с помощью точки с запятой (;). Таким образом, в результате URL выглядит так:
href= "http://Tocalhost/servlet/catalog;jsessiornd=124c41"Для мониторинга сеанса в сервлете ShoppingCart мы используем интерфейс API класса HttpSession. Этот класс позволяет процессору сервлетов детально управлять мониторингом сеанса с минимальным участием программиста.
Перед тем как углубляться в изучение исходного кода CatalogServ, рассмотрим некоторые другие представления, которые он генерирует. На рис. 4.2 показана страница с раскрывающимся списком ключевых слов. Это тот же самый список, который представлен на рис. 3.1 в главе 3, но сервлет CatalogServ добавляет в нижнюю часть страницы дополнительные ссылки:
Full Catalog (Весь каталог);
Books (Книги);
CDs (Компакт-диски):
Widgets (Приборы и устройства);
Search (Поиск).
В табл. 4 2 представлен перечень команд отображения (значений параметра action), которые определяют ответ сервлета CatalogServ Команды, управляющие отображением, обычно модифицируются дополнительными параметрами
В методе keywordCatal og (листинг 4.10) применяется тот же принцип, но выбор происходит на основе переменной keyword, которая передается в качестве параметра методу setKeywordSel ect класса CalatogBean.
Если товар уже был заказан покупателем и находится в корзине, то страница с информацией о нем включает поле текущего количества заказанных экземпляров товара и позволяет его изменять. Пример такой страницы показан на рис. 4.5, причем для данного товара не предусмотрено изображения. Если пользователь щеллкает на кнопке Change (Изменить), в запросе к сервлету значение параметра action будет равно setcart, а значение itemct — введенному числу.
Теперь рассмотрим подробно, как устроен метод doShowProduct, код которого приведен в листинге 4.11. Этот метод отображает подробную информацию о данном товаре и позволяет добавлять товар в корзину. В первую очередь этот метод должен получить экземпляр класса Choppi ngCart. В приведенном коде используется метод getAttribute класса HttpSession, который является предпочтительным по отношению в устаревшему методу getValue. Закомментированная строка показывает, как использовать метод getValue, если в вашем случае процессор сервлетов ориентирован на версию 2.1 API.
Когда вызывается метод doShowProduct, в объекте HttpServletRequest всегда будет содержаться параметр id, который однозначно идентифицирует отображаемый товар.
Когда пользователь щелкает на кнопке (такой, как на рис. 4.4 или 4.5), вызывается метод doShowProduct со значением параметра action, равным setcart. В этом случае значение параметра itemct интерпретируется как новое количество заказанных экземпляров данного товара.
Когда вызывается метод doShowProduct с параметром action, равным showproduct, количество заказанных товаров (numberOrdered) не изменяется.
Сложное форматирование при представлении полной информации о товаре (как показано на рис. 4 4 и 4 5) контролируется методом doFuTIItem, код которого приведен в листинге 4 15 Исходно мы строим таблицу с четырьмя или тремя ячейками в зависимости от наличия или отсутствия изображения товара В этой таблице содержатся сведения о товаре, его изображение (если оно есть), название и цена, а также количество заказанных экземпляров (если покупатель решил приобрести этот товар) Создается объект ProductFormatter, задающий стиль отображения всей этой информации о товаре, то есть стиль всех фрагментов текста, которые содержатся в документе XML, описывающем данный товар
Обычно объект Cartltem, соответствующий идентификатору товара, в этот момент уже добавлен к корзине Но если это не так, то создается новый объект Cartltem
Наличие или отсутствие ссылки на изображение товара в XML-каталоге влияет на форматирование верхней строки таблицы Если изображение отсутствует, то название товара вместе с его описанием занимает всю верхнюю строку
Метод |
Возвращаемое значение |
Описание |
getAttribute (String name) |
Object |
Возвращает подключенный к сеансу объект с заданным именем name или null, если не найдено объекта с таким именем |
setAttribute (String name.Object obj) |
void |
Подключает к сеансу объект obj с именем name. Если к сеансу ранее был подключен другой объект с этим именем, прежняя связь теряется |
getAttribute Names() |
Enumeration |
Перечень объектов типа String, содержащий имена всех объектов, подключенных к сеансу |
removeAttri bute (String name) |
void |
Удаляет объект с указанным именем из сеанса |
getCreationTime() |
long |
Системное время (GMT) создания объекта такое же, как в System. currentTimeMillisO |
getLastAccessed Time() |
long |
Системное время последнего обращения клиента к сеансу. Формат такой же, как в getCreationTime |
getMaxInactive Interval() |
int |
Максимальный интервал времени (в секундах), в течение которого контейнер сервлета поддерживает сеанс открытым между обращениями к нему клиента |
setMaxInactive Interval (int interval) |
void |
Устанавливает интервал времени (в секундах) между обращениями клиента, по истечении которого контейнер сервлетов сделает данный сеанс недействительным |
invalidate() |
void |
Делает данный сеанс недействительным и прекращает все связи с объектами |
isNew() |
boolean |
Возвращает значение true, если клиент еще не знает о сеансе или клиент предпочел не присоединяться к сеансу. Обычно этот метод вызывается сразу после вызова метода getSession объекта HttpServlrtRequest |
getId() |
String |
Возвращает уникальный идентификатор, присвоенный данному сеансу |
В этой версии произошли некоторые изменения по сравнению с версией 2.1, которые необходимо указать, так как в некоторых процессорах сервлетов используется старая версия.
Методы getAttribute и setAttribute заменили прежние методы getValue и setValue. Метод getAttributeNames заменил прежний метод getVal ueNames. Эти изменения были проделаны в процессе общей модернизации спецификаций классов сервлетов.
Для хранения ссылки на объект сеанса в классе HttpSession и ее извлечения используется имя типа String, как в следующем примере, где session — это переменная класса HttpSession:
ShoppingCart cart = (ShoppingCart)session.getAttribute("cart"); if( cart == null ){ // предположительно первый проход cart = new ShoppingCart(); session.setAttribute( "cart",cart ); }Некоторые дополнительные изменения в API по сравнению с предыдущими версиями обусловлены соображениями безопасности. В версии API 2.1 можно было использовать метод getSessionContext для получения связанного объекта HttpSessionContext. Этот метод и интерфейс HttpSessionContext в нынешней версии отнесены к нерекомендуемым (deprecated), и они будут удалены из последующих версий этой библиотеки (иногда такие методы называются устаревшими).
В версии API 2.2 особое внимание уделено тому, чтобы существенная информация web-приложения оставалась в рамках этого приложения. В интерфейсе Servl etContext определены методы, которые сервлет может использовать для взаимодействия с контейнером и совместного использования одного и того же объекта с другими сервлетами этого приложения. Конкретный объект класса HttpSession может задействоваться более чем одним сервлетом, но только в случае, если эти сервлеты принадлежат тому же приложению. Участие сервлета или JSP-страни- цы в определенном приложении устанавливается с помощью параметров инициализации, которые использует процессор сервлетов.
Если механизм HttpSession только создавал бы атрибуты и не обеспечивал бы никакого способа избавления от них, процессор сервлетов вскоре исчерпал бы все ресурсы памяти. К счастью, имеется несколько методов организации приложения таким образом, чтобы избежать проблем с памятью.
Те процессоры сервлетов, с которыми мы работаем в наших примерах (JRun и Tomcat), по умолчанию удаляют объекты HttpSession, если они не использовались в течение 30 минут. Нужный интервал времени допустимого простоя можно установить для каждого приложения, задавая параметры инициализации в ядре сервлетов. В табл. 4.1 указан метод setMaxInactivelntarval, с помощью которого можно задать величину этого интервала. Установка отрицательного значения -1 означает, что для сеанса не задано время простоя, и в этом случае программист должен явным образом удалить объект с помощью метода invalidate.
Также можно явным образом удалить определенные объекты из класса HttpSession с помощью метода RemoveAttribute (в API 2.1 этот метод назывался remove Value). Программисту следует очень внимательно относиться к выбору объектов, которые он собирается хранить как объекты сеанса. Помните, что вы не можете предсказать, когда пользователь вернется к данному сеансу. Поэтому не рекомендуется хранение таких объектов, как, например, объекты соединения с базами данных, которые требуют значительных системных ресурсов.
Команда (параметр action) |
Дополнительные параметры |
Отображение |
showcatalog |
Параметр select = "all" |
Таблица со списком всех товаров (см. рис. 4.1) |
showcatalog |
Параметр select =одна из серий товаров (books, CDs, widgets) |
Таблица со списком товаров определенной серии (см. рис. 4.3) |
selectkeyword |
Параметр select = "all" |
Раскрывающийся список ключевых слов (см. рис. 4.2) |
showproduct |
Параметр id из формы |
Полная информация о товаре (см. рис. 4 4) |
keywdsearch |
Параметр keyword из формы |
Список товаров с этим ключевым словом |
setcart |
Параметры id и itemct из формы |
Полная информация о товаре с измененным количеством заказанных экземпляров (см. рис. 4.5) |
showcart |
Параметры отсутствуют |
Список всех товаров в корзине покупателя с указанием количества заказанных экземпляров (см. рис. 4.6) |