JavaServer Pages
Как упоминалось ранее, свободно распространяемый Tomcat, реализация от jakarta.apache.org, автоматически поддерживает JSP.
JSP позволяет вам комбинировать HTML Web страницы с кусочками кода Java в одном документе. Java код обрамляется специальными тегами, которые говорят JSP контейнеру, что он должен использовать код для генерации единого документа или его части. Выгода JSP состоит втом, что вы можете содержать единый документ, которые представляет и страницу, и Java код, который в нее включен. Недостаток состоит в том, что тот, кто поддерживает работоспособность JSP страницы, должен иметь опыт и HTML, и в Java (однако, со временем ожидается появление визуальных построителей JSP страницы).
При первой загрузке JSP загружается JSP контейнером (который обычно ассоциирован, или является частью Web сервера), далее сервлетный код, который обязательно выделяется JSP тегами, автоматически генерируется, компилируется и загружается в контейнер сервлетов. Статическая часть HTML страницы производится посредством посылки статического объекта типа String в метод write( ). Динамическая часть включается прямо в сервлет.
С этого момента, пока исходная JSP страница не будет изменена, она будет вести себа так, как будто бы это была статическая HTML страница, ассоциированная с сервлетом (однако весь HTML код на самом деле генерируется сервлетом). Если вы измените исходный код для JSP, он автоматически перекомпилируется и перезагрузится при следующем запросе этой страницы. Конечно, по причине такого динамизма, вы увидите замедленный ответ для первого доступа к JSP. Однако, так как JSP обычно используется гораздо чаще, чем меняется, вы обычно не будете чувствовать влияние этой задержки.
За лидирующим знаком процента могут следовать другие символы, которые определяют точный тип JSP кода в тэге.
Вот чрезвычайно простой JSP пример, который использует стандартный библиотечный Java вызов для получения текущего времени в миллисекундах, которое затем делится на 1000, чтобы получить время в секундах. Так как используется JSP выражение ( @ directive < attr = "value" >* %>
Директивы ничего не посылают в выходной поток, но они важны для настройки атрибутов вашей JSP страницы и зависимостей JSP контейнера. Например, строка:
сообщает, что скриптовой язык, используемый внутри JSP страницы, это Java. Фактически, JSP спецификация только описывает семантику скриптов для языковых атрибутов, эквивалентных «Java». Смысл этой директивы состоит во встраивании гибкости в JSP технологию. В будущем, если вы выберите другой язык, скажем Python (хороший выбор для скриптов), то такой язык должен иметь поддержку Java Run-time Environment, выставляя наружу объектную модель Java технологии для скриптового окружения, особенно для неявных переменных, определенных выше, свойств JavaBeans и публичных методов.
Наиболее важными директивами являются директивы страницы. Они определяют несколько атрибутов страницы и взаимодействие этих атрибутов с JSP контейнером. Эти атрибуты включают: language, extends, import, session, buffer, autoFlush, isThreadSafe, info и errorPage. Например:
Эта строка, прежде всего, указывает, что эта страница требует участие в HTTP сессии. Так как мы не установили директиву языка, JSP контейнер по умолчанию использует Java и неявную переменную скриптового языка с названием session типа javax.servlet.http.HttpSession. Если бы директива использовала false, то неявная переменная session будет недоступна. Если переменная session не определена, то по умолчанию считается «true».
Атрибут import описывает типы, которые доступны для скриптовой среды. Этот атрибут используется так же, как и в языке программирования Java, т. е., разделенный запятыми обычный список выражений import. Этот список импортируется транслируемой реализацией JSP страницы и доступен для скриптового окружения. Скажем еще раз, что в настоящее время это определено, только если значением директивы языка является «java».
Скриптовые элементы JSP
Все эти теги основываются на XML; вы даже можете сказать, что JSP страница может быть отражена на XML документ. Эквивалентный синтаксис для скриптовых элементов, приведенных выше, может быть:
Кроме тоге, есть два типа комментариев:
Декларации используются для объявления переменных и методов в скриптовом языке (в настоящее время только в Java), используемых на JSP странице. Декларация должна быть законченным Java выражением и не может производить никакого вывода в выходной поток. В приведенном ниже примере Hello.jsp декларации для переменных loadTime, loadDate и hitCount являются законченными Java выражениями, которые объявляют и инициализируют новые переменные.
Когда вы запустите эту программу, вы увидите, что переменные loadTime, loadDate и hitCount содержат свои значения между обращениями к странице, так что они явно являются полями, а не локальными переменными.
В конце примера помещен скриплет, который пишет «Goodbye» на консоль Web сервера и «Cheerio» в неявный объект вывода JspWriter. Скриплет может содержать любые фрагменты кода, которые являются имеющими силу инструкциями Java. Скриплеты выполняются во время обработки запроса. Когда все фрагменты скриплета в данном JSP будут скомбинированы по порядку своего появления в JSP странице, они должны дать имеющую силу инструкцию, определенную для языка программирования Java. Будет ли скриплет производить вывод в выходной поток или нет, зависит только от кода скриплета. Вы должны знать, что скриплет может воздействовать на объекты, которые видимы для него.
JSP выражения можно найти вперемешку с HTML в среднем разделе Hello.jsp. Выражения должны быть законченными Java инструкциями, которые вычисляются, переводятся в строку и посылаются в вывод. Если результат инструкции не может быть переведен в строку (String), будет выброшено исключение ClassCastException.
Извлечение полей и значений
Следующий пример похож на приведенный ранее в разделе о сервлетах. При первом показе страницы она определяет, что у вас нет полей и возвращает страницу, содержащую форму с помощью того же самого кода, что и в примере с сервлетом, но в формате JSP. Когда вы отправляете форму с заполненными полями по тому же самому JSP URL’у, страница обнаруживает поля и отображает их. Это прелестная техника, поскольку она позволяет вам получить две страницы, одна из которых содержит форму для заполнения пользователем, а вторая содержит код ответа на эту страницу, в едином файле, таким образом, облегчается создание и поддержка.
Более интересное свойство этого примера заключается в том, что он демонстрирует, как код скриплета может быть перемешан с HTML кодом даже в том месте, где генерируется HTML внутри Java цикла. Это особенно удобно для построения форм любого рода, в противном случае необходимо было бы вставлять повторяющийся HTML код.
Атрибуты JSP страницы и область видимости
Просматривая документацию в HTML для сервлетов и JSP, вы найдете возможность, которая сообщает информацию о текущем запущенном сервлете или JSP. Следующий пример отображает некоторую часть этих данных.
Этот пример также показывает использование встроенного HTML и записи в out, чтобы в результате получить HTML страницу.
Манипуляция сессиями в JSP
Сессии были введены в предыдущем разделе, посвященном сервлетам и также доступны в JSP. Следующие примеры исследуют сессионные объекты и позволяют вам манипулировать промежутком времени, прежде, чем сессия станет недействительной.
Объект сессии предоставляется по умолчанию, так что он доступен без дополнительного кода. Вызов getID( ), getCreationTime( ) и getMaxInactiveInterval( ) используются для отображения информации об этом сессионном объекте.
Когда вы в первый раз получите эту сессию, вы увидите, что MaxInactiveInterval составляет, например, 1800 секунд (30 минут). Это зависит от конфигурации вашего контейнера JSP/сервлетов. MaxInactiveInterval сокращается до 5 секунд, чтобы сделать вещи интереснее. Если вы перегрузите страницу до того, как истекут 5 секунд, то вы увидите:
Но если вы подождете больший интервал, то «Ralph» станет null.
Чтобы посмотреть, как сессионная информация переносится на другие страницы, а также, чтобы посмотреть эффект становления объекта сессии недействительным по сравнению с простым вариантом, когда вы дали ему устареть, созданы две новые страницы. Первая (доступна при нажатии кнопки «invalidate» в SessionObject.jsp) читает сессионную информацию, а затем явно делает сессию недействительной:
Чтобы экспериментировать с этим, обновите SessionObject.jsp, затем сразу же кликните на кнопку «invalidate», чтобы перейти к странице SessionObject2.jsp. В этом месте вы все еще будете видеть «Ralph» и сразу после этого (прежде, чем пойдет интервал в 5 секунд), обновите SessionObject2.jsp, чтобы увидеть, что сессия была успешно сделана недействительной и «Ralph» исчез.
Если вы вернетесь на SessionObject.jsp, обновите страницу так, чтобы вы снова имели 5-ти секундный интервал, затем нажмете кнопку «Keep Around», то вы попадете на следующую страницу SessionObject3.jsp, которая не делает сессию недействительной:
Создание и изменение cookies
Cookie были введены в предыдущем разделе о сервлетах. Опять таки, краткость JSP делает обращение с cookies более простым, чем при использовании сервлетов. Следующий пример показывает это с помощью получения cookie, которые пришли в запросе, чтения и изменения максимального возраста (дата устаревания) и присоединения нового cookie в ответный запрос:
Так как каждый браузер хранит cookie по-своему, вы можете видеть разное поведение в разных браузерах (не убежден, но это может быть некоторой ошибкой, которая может быть исправлена в то время, когда вы читаете это). Также вы можете получить разные результаты, если вы выгрузите браузер и запустите его, по сравнению с тем, если вы посетите другую страницу, а затем вернетесь на Cookies.jsp. Обратите внимание, что использование объекта сессии выглядит более уместным, чем прямое использование cookies.
После отображения идентификатора сессии каждый cookie в массиве cookies, пришедший с объектом запроса, отображается на странице наряду с его максимальным возрастом. Максимальный возраст изменяется и отображается снова, чтобы проверить новое значение, затем новый cookie добавляется в ответ. Однако ваш браузер может проигнорировать этот максимальный возраст; стоит поиграть с этой программой и поизменять значение максимального возраста, чтобы посмотреть поведение под различными браузерами.
Заключение о JSP
Этот раздел является только кратким обзором JSP, и даже с тем, что рассмотрено здесь (наряду с тем, что вы выучите о Java в остальной части книги, и вместе с вашим знанием HTML), вы можете начать писать замысловатые web страницы с помощью JSP. Синтаксис JSP не предназначен быть таинственным или сложным, так что если вы понимаете что было представлено в этом разделе, вы готовы к продуктивной работе с JSP. Вы можете найти больше информации в большинстве имеющихся книг о сервлетах или на java.sun.com.
Это особенно удобно иметь доступ к JSP, даже если вашей целью является только создание сервлетов. Вы обнаружите, что если у вас есть вопрос относительно поведения функции сервлета, гораздо легче и быстрее написать тестовую программу на JSP, чтобы получить ответ, чем писать сервлет. Часть удобства состоит в том, что нужно писать меньше кода и можно смешивать отображаемый HTML с Java кодом, но это преимущество становится особенно явным, когда вы увидите, что JSP Контейнер обрабатывает всю перекомпиляцию и перезагрузку JSP за вас в любое время, когда меняется исходный код.
Однако весь ужас JSP состоит в том, что необходимо учитывать, что создание JSP требует большего уровня умения, чем простое программирования на Java или просто создание Web страниц. Кроме того, отладка неработающего JSP не такое простое дело, как в случае Java программы, так как (в настоящее время) сообщения об ошибках более непонятны. Это должно измениться с улучшением систем разработки, но мы можем также видеть другие технологии, основанные на Java и Web, которые лучше адаптированы к умениям дизайнеров Web сайтов.
Упражнения
Java Server Pages JSP
Разработчики Java Server Pages могут использовать компоненты JavaBeans и создавать собственные библиотеки нестандартных тегов, которые инкапсулируют сложные динамические функциональные средства.
Спецификация Java Server Pages наследует и расширяет спецификацию сервлетов. Как и сервлеты, компоненты JSP относятся к компонентам Web и располагаются в Web-контейнере. Страницы JSP не зависят от конкретной реализации Web-контейнера, что обеспечивает возможность их повторного использования.
В дополнение к классам и интерфейсам для программирования сервлетов (пакеты javax.servlet и javax.servlet.http), в пакетах javax.servlet.jsp и javax.servlet.jsp.target содержатся классы и интерфейсы, относящиеся к программированию Java Server Pages.
Обзор технологии Java Server Pages
Технология Java Server Pages содержит четыре ключевых компонента:
Наличие данных с неизменяемой структурой определяют выбор программиста в принятии решения, какую технологию следует использовать: сервлеты или страницы JSP. Программисты предпочитают использовать страницы JSP, если основная часть посылаемого клиенту содержимого представляет собой данные с неизменяемой структурой, и лишь небольшая часть содержимого генерируется динамически с помощью кода Java.
Сервлеты предпочтительнее использовать, если только небольшая часть содержимого, посылаемого клиенту, представляет собой данные с неизменяемой структурой. На самом деле отдельные сервлеты могут вообще не генерировать содержимого для клиента, выполняя определенную задачу в интересах клиента, а затем вызывают другие сервлеты или JSP-страницы, чтобы отправить ответ.
Необходимо заметить, что во многих случаях сервлеты и JSP-страницы являются взаимозамеяемыми. Подобно сервлетам, JSP-страницы обычно выполняются на стороне Web-сервера, который называют контейнером JSP.
Когда Web-сервер, поддерживающий технологию JSP, принимает первый запрос на JSP-страницу, контейнер JSP транслирует эту JSP-страницу в сервлет Java, который обслуживает текущий запрос и все последующие запросы к этой странице. Если при компиляции нового сервлета возникают ошибки, эти ошибки приводят к ошибкам на этапе компиляции. Контейнер JSP на этапе трансляции помещает операторы Java, которые реализует ответ JSP-страницы, в метод _jspService. Если сервлет компилируется без ошибок, контейнер JSP вызывает метод _jspService для обработки запроса.
JSP-страница может обработать запрос непосредственно, либо вызвать другие компоненты Web-приложения, чтобы содействовать обработке запроса. Любые ошибки, которые возникают в процессе обработки, вызывают исключительную ситуацию в Web-сервере на этапе запроса.
Таким образом, достаточно написать страницу JSP, сохранить ее в файле с расширением jsp и установить файл в контейнер, так же, как и страницу HTML, не заботясь о компиляции. При установке можно задать начальные параметры страницы JSP также, как и начальные параметры сервлета.
Архитектура JSP
Базовая архитектура Java Server Pages в самом общем виде представлена на рисунке. Платформа J2EE обеспечивает базу, на которой функционирует все приложение в целом и страницы JSP, в частности, в то время, как сеть Интернет предоставляет механизм транспортировки данных.
Страница JSP располагается на Web-сервере в среде виртуальной Java-машины. Доступ к страниц JSP, как и в случае сервлета, осуществляется через Web с использованием протокола HTTP.
Использование межплатформенных компонентов JavaBeans и библиотек тегов значительно расширяет возможности JSP. Программный Java-код в странице JSP, в идеале, должен использоваться только для управления представлением информации.
Основные модели архитектуры JSP
Возможны различные подходы к использованию технологии JSP. Два основных архитектурных подхода, нашедшие применение при реализации приложений уровня предприятия, имеют специальные названия:
JSP Model 1
Первая модель JSP Model 1 практически реализует базовую архитектуру JSP. В архитектурном решении JSP Model 1 полностью отвечает за получение запроса от клиента, его обработку, подготовку ответа и доставку ответа пользователю. Разделение представления и динамического содержания обеспечивается тем, что доступ к данным осуществляется через компоненты JavaBeans.
В сценарии JSP Model 1 предполагается следующая последовательность действий:
Архитектура JSP Model 1 может с успехом применяться для небольших приложений. Однако использование данной модели для более сложных задач вызывает определенные трудности и не является технологичным из-за большого объема встроенных в страницу программных фрагментов. Для сложных корпоративных приложений рекомендуется применение второй модели архитектуры JSP.
JSP Model 2
Вторая модель JSP Model 2 реализует гибридный подход к обслуживанию динамического содержания Web-страницы, при котором совместно используется сервлет и страница JSP. Эта модель позволяет эффективно использовать преимущества обеих технологий: сервлет поддерживает задачи, связанные с обработкой запроса и созданием объектов JavaBeans, используемых JSP, а страница JSP отвечает за визуальное представление информации. Сервлет используется как управляющее устройство (контроллер). Схематично вторая модель представлена на рисунке.
Сценарии JSP Model 2, как правило реализует следующую типовую последовательность действий:
Необходимо отметить, что в рамках этой модели страница JSP сама не реализует никакую логику, это входит в функции сервлета-контроллера. Страница JSP отвечает только за получение информации от компонента JavaBean, который был предварительно создан сервлетом, и за визуальное представление этой информации в удобном для клиента виде.
Архитектуры JSP Model 2 в большей степени, чем архитектура JSP Model 1, соответствует идее отделения представления от содержания. Эта модель позволяет четко выделить отдельные части приложения и связанные с ними роли и обязанности персонала, занятого в разработке:
Чем сложнее разрабатываемая система, тем заметнее становятся преимущества архитектуры JSP Model 2.
Функционирование JSP
Работа со страницей JSP становится возможной только после ее преобразования в сервлет. В процессе трансляции как статическая, так и динамическая части JSP преобразуются в Java-код сервлета, который передает преобразованное содержимое браузеру через выходной поток Web-сервера.
При трансляции, которая выполняется один раз для каждой страницы JSP, создается или локализуется класс типа Servlet, реализующий JSP. Трансляция JSP может производиться как отдельно, до ее использования, так и в процессе размещения JSP на Web-сервере или сервере приложений.
Во второй фазе осуществляется обработка запросов и подготовка ответов.
Жизненный цикл JSP
Страница JSP обслуживает запросы, как сервлет. Следовательно, жизненный цикл и многие возможности страниц JSP (в частности, динамические аспекты) определяются технологией Servlet и многие обсуждения в этой главе ссылаются на функции, описанные на странице cервлетов.
Когда запрос отображается на страницу JSP, он обрабатывается специальным сервлетом, который сначала проверяет, не старше ли сервлет страницы JSP, чем сама страница JSP. Если это так, он переводит страницу JSP в класс сервлета и компилирует класс. При разработке Web-приложения одним из преимуществ страниц JSP перед сервлетами является то, что процесс построения (компиляции страницы JSP в сервлет) выполняется автоматически.
Трансляция и компиляция страницы JSP
На фазе трансляции каждый тип данных в странице JSP интерпретируется отдельно. Шаблонные данные трансформируются в код, который будет помещать данные в поток, возвращающий данные клиенту. Элементы JSP трактуются следующим образом:
И фаза трансляции, и фаза компиляции могут порождать ошибки, которые будут выведены только, когда страница будет в первый раз запрошена. Если ошибка возникает при трансляции страницы (например, транслятор находит элемент JSP с неправильным форматом), сервер возвращает ParseException, и исходный файл класса сервлета будет пустым или незаконченным. Последняя незаконченная строка дает указатель на неправильный элемент JSP. Если ошибка возникает при компиляции страницы (например, синтаксическая ошибка в скриптлете), сервер возвращает JasperException и сообщение, которое включает в себя имя сервлета страницы JSP и строку, в которой произошла ошибка.
Когда страница оттранслирована и откомпилирована, сервлет страницы JSP в основном следует жизненному циклу сервлета, описанному на странице сервлета:
Если контейнеру нужно удалить сервлет страницы JSP, он вызывает метод jspDestroy.
Пример интеграции JSP-страницы с сервлетом и jQuery можно увидеть здесь.
Java Server Pages
Введение
Технология Java Server Pages (JSP) является составной частью единой технологии создания бизнес-приложений J2EE. JSP — это альтернативная методика разработки приложений, динамически генерирующих ответ на те или иные запросы клиента. Прежде чем JSP документ будет использован, специальная процедура преобразует его в соответствующий сервлет. В свою очередь, сервлет, как правило, пишется на языке Java и реализует определенный интерфейс. Далее, сервлет также не является самостоятельным приложением и функционирует, только будучи помещен в соответствующий web-контейнер. Web-контейнер обеспечивает обмен данными между сервлетом и клиентами, берет на себя выполнение таких функций, как создание программной среды для функционирующего сервлета, идентификацию и авторизацию клиентов, организацию сессии для каждого из них.
На настоящий момент реализована трансляция JSP страницы в сервлет, программный код которого пишется на языке Java. Однако авторы спецификации Java Server Pages оставляют возможность реализации JSP и на других языках программирования.
Соотношение между сервлетами бизнес-приложения и адресами URL на сервере задается в дескрипторе размещения. Технология реализации сервлетов обсуждается в отдельной статье. Сейчас же важно отметить тот факт, что программный код, используемый для написания сервлетов, не всегда удобен для динамической генерации текстовых документов в ответ на запрос клиента. Например, фрагмент сервлета, где осуществляется генерация динамической HTML страницы, может выглядеть следующим образом:
Как видим, каждой строке HTML документа в сервлете соответствует определенный фрагмент программного кода, что не способствует простоте разработки и сопровождения бизнес-приложений.
Удобнее разделить динамическую и статическую части генерируемой web-страницы. Для создания динамической части по-прежнему будет использоваться Java или другой язык программирования. Статическую же часть имеет смысл оформить как текстовый документ — Java Server Page (JSP страницу), оформленную в соответствии с требованиями HTML, XML или другого стандарта разметки. Фактически, JSP страница можно рассматривать как шаблон или прообраз динамической страницы, которую остается дополнить динамическими элементами. Для описания динамической составляющей, в технологии JSP предусмотрено два основных механизма: компоненты JavaBean и библиотеки дополнительных тэгов. Как результат, технология JSP предполагает параллельную работу над приложением двух разных специалистов: программиста и ответственного за верстку документов (web мастера), которые отвечают, соответственно, за разработку динамической и статической частей документов, генерируемых в ответ на запросы клиентов.
Как уже говорилось, перед тем, как использовать JSP страницу, ее необходимо преобразовать в соответствующий сервлет. Такое преобразование может выполняться либо в момент, когда JSP страница помещается на сервер, либо когда клиент первый раз обращается к этой странице. Поскольку процедура преобразования довольно трудоемка и занимает много времени, то выполняется она обычно только один раз. Все же последующие обращения клиента к JSP странице сервер автоматически переадресует на сервлет, который был получен в результате ее преобразования.
Сервлет, полученный после преобразования JSP страницы, функционируют в рамках стандартного контейнера сервлетов и используют строго регламентированный интерфейс. Поэтому эта технология не зависит от каких-либо особенностей той или иной аппаратной платформы. С другой стороны, поскольку JSP технологии может строиться на базе интерпретируемого языка Java, то это дает гарантию портируемости приложений, построенных на технологии JSP, на любую платформу, где можно установить виртуальную Java машину.
JSP страница
Динамическая составляющая JSP страницы представлена тремя типами специальных элементов: директивами, action и скриптами. Подробнее каждый из них рассматривается в соответствующем разделе.
Директивы
Поскольку web контейнер, прежде чем использовать JSP страницу, предоставленную разработчиками бизнес-приложения, транслирует ее в соответствующий сервлет, имеет смысл предоставить возможность оставлять на JSP странице директивы, которые будут управлять процессом трансляции. Директивы имеют синтаксис
Рассмотрим некоторые из таких директив
Директива page. Декларирует ряд свойств JSP страницы. Синтаксис директивы:
Опишем некоторые наиболее интересные параметры данной директивы:
Директива taglib. Позволяет использовать на JSP страницах дополнительные тэги, созданные разработчиком приложения (custom тэги). Синтаксис директивы:
где, uri — абсолютный или относительный адрес URI, уникальным образом идентифицирующий дескриптор библиотеки тэгов, связанных с указанным префиксом. Указанный префикс используется для идентификации соответствующих custom тэгов.
Процедуру создания custom тэгов мы рассмотрим позднее.
Директива include. Используется для помещения в JSP страницу текстов и программного кода из других источников. Подстановка выполняется в момент, трансляции JSP страницы в соответствующий сервлет. Пример использования директивы:
Фрагмент программного кода на JSP странице (скрипт)
Скрипт, как и остальные элементы, привносит в конечный документ динамическую составляющую. Однако, в отличие от них, скрипт — программный код, помещенный непосредственно в текст JSP страницы. Скрипт может производить вычисления или манипулировать объектами, что позволяет наглядно связывать характеристики генерируемой страницы с параметрами запроса клиента и бизнес-правилами приложения. Элементы скриптов бывают трех типов: декларации, скриплеты и выражения.
Декларации
Примеры деклараций на JSP странице:
Скриплеты
Скриплет может содержать программный код и декларации локальных переменных, которые будут использованы для обработки запросов клиентов. Фактически, скриплет — это фрагмент программного кода из будущего сервлета, который в свое время будет помещен в метод _jspService(). Являясь частью сервлета, скриплет получает доступ к объекту response и, соответственно, может самостоятельно формировать определенную часть конечной динамической страницы. Однако чаще всего скриплеты используются не для этого, а для того, чтобы управлять объектами бизнес-логики и логикой приложения.
Чтобы оценить наглядность и простоту этой конструкции, сравните ее с эквивалентным фрагментом программного кода в сервлете:
Выражения
Часто страница, передаваемая клиенту, содержит результаты вычислений или обращений к тем или иным методам и атрибутам определенных классов. Любой из таких динамических элементов можно преобразовать в строку и представить на JSP странице с помощью вызова out.println в соответствующем скриплете:
Вторую строку в приведенном примере удобнее и нагляднее представить в боле кратном виде, используя синтаксис выражения :
Другой пример использования выражения в теле JSP страницы:
JSP страницы и объекты
В ходе обработки запросов, JSP страница может получать доступ к объектам, расположенным на сервере, создавать их и модифицировать. Доступ к объектам осуществляется через элементы скриптов и action. Каждый создаваемый в приложении объект имеет определенное время существования, которое декларируется в соответствующем атрибуте. Спецификацией предусматривается четыре интервала:
JSP страница всегда имеет доступ к определенному набору объектов, создаваемых web контейнером по умолчанию:
Элементы action
Независимо от того, какой тип будет иметь документ, генерируемый в ответ на запрос пользователя, в общем случае, JSP страница содержит текст и тэги. Очевидно, что последние соответствуют типу генерируемого документа: HTML, XML и т.д. Кроме того, в теле JSP страницы могут содержаться фрагменты программного кода на языке Java, которые должны войти в состав сервлета, получаемого после трансляции: декларации, скриплеты и выражения. Идея заключается в том, чтобы дополнить набор тэгов стандартной разметки специальными тэгами — элементами action, за которыми разработчик бизнес-приложения может скрыть часть программного кода, относящегося к приложению, либо некоторые дополнительные инструкции.
Заметим, что с точки зрения специалиста по верстке документов, элементы action являются такими же тэгами, как и все остальные, а потому допустимо их совместное использование с другими элементами:
Рассмотрим некоторые из этих элементов.
Стандартные элементы action
jsp:useBean
Элемент jsp:useBean позволяет использовать на JSP странице объекты, соответствующие компонентам JavaBean. Элемент содержит параметр, который связывает с компонентом некий уникальный идентификатор. Последний затем будет использоваться при обращениях к этому объекту:
В данном примере создается объект класса com.myco. В дальнейшем, чтобы обратиться к нему, достаточно воспользоваться идентификатором «customer». Например:
По умолчанию, объекты, связанные с элементом JavaBean, по умолчанию имеют область видимости page. Разработчик JSP страницы может указать более продолжительное время существования объекта JavaBean, воспользовавшись при написании элемента jsp:useBean элементом scope. Возможные значения этого атрибута — page, request, session и application — мы обсуждали несколько ранее во время разговора об области видимости объектов, связанных с JSP страницей.
Мы не будем рассматривать остальные атрибуты элемента jsp:useBean. Приведем лишь еще один пример его использования:
Внутреннее устройство элементов JavaBean будет рассмотрено нами в отдельной статье.
Любой класс должен давать доступ к некоторым из своих атрибутов и методов. Отличие элемента JavaBean заключается в том, что доступ к атрибутам у него унифицирован и реализуется на JSP странице с помощью элементов jsp:setProperty и jsp:getProperty.
Элемент jsp:getProperty берет экземпляр Bean, извлекает значение указанного атрибута, преобразует его в случае необходимости в строку и помещает в поток данных, передаваемых клиенту. Например, согласно следующей записи
в генерируемый документ помещается значение свойства name из экземпляра Bean, имеющего идентификатор user.
Элемент jsp:setProperty, в отличие от предыдущего, не извлекает, а задает новое значение атрибута. Например:
Помимо явного задания новых значений, элемент jsp:setProperty позволяет заносить в атрибут объекта значение, извлеченное из запроса клиента. Например:
Данная запись означает, что среди данных, полученных от клиента, находится параметр login и его значение передается для помещения в атрибут name объекта Bean, имеющего идентификатор «user».
Наконец, когда названия полей в запросе клиента совпадают с названиями атрибутов объекта Bean, предусмотрен еще один вариант, когда разом осуществляется перенос всех значений. Например:
jsp:include
Подобно директиве include, данный элемент позволяет помещать в тело динамически генерируемой страницы статический и динамический материал из внешнего источника. При этом, хотя заимствованный таким образом материал обрабатывается в том же контексте, что и текущая страница, ему предоставляется доступ только к выходному потоку сервлета. Например, код, включаемый в JSP страницу, не должен обращаться к cookies или использовать собственные заголовки, декларирующие кодировку или тип документа.
Отличие директивы include от элемента jsp:include заключается в том, что для нее включаемый материал не может быть динамическим, а поиск и обработка возможных динамических фрагментов осуществляется не отдельно, а после включения, со всей страницей.
Пример использования элемента jsp:include:
jsp:forward
Данный элемент позволяет переадресовать дальнейшее формирование динамической страницы на другую JSP страницу, сервлет или использовать для завершения заранее приготовленный текст. Например:
В следующем, более сложном примере динамическая страница завершается содержимым текстового файла, название которого берется из переменной someValue:
В заключение следует заметить, что есть две основные схемы обработки запросов клиента:
В первом случае, обработка запроса клиента и формирование в ответ динамической страницы производятся в рамках одной JSP страницы или сервлета. Последняя, в случае необходимости, может обращаться к объектам JavaBean или импортировать материал из внешних источников с помощью директивы include или элемента jsp:include.
Во втором случае, обработка производится в два этапа. Сперва управление подается на сервлет или JPS страницу, осуществляющую собственно обработку запроса. Например, из запроса клиента извлекаются данные и помещаются в базу данных или атрибуты определенных объектов. Затем управление передается на отдельную JSP страницу или сервлет, ответственные за генерацию динамической страницы для последующей передачи ее клиенту. При этом между обработкой запроса и генерацией новой страницы необязательно должна существовать какая-либо взаимосвязь. Например, это может быть всего лишь возврат клиента на главную страницу по завершении какой-либо процедуры.
Дополнительные наборы тэгов
Такие протоколы разметки текстовых документов, как HTML, имеют строго регламентированный набор тэгов. Вместе с тем, в ходе разработки документов часто возникает потребность использовать дополнительные, специальные тэги, которые хотя и не были заявлены в соответствующие спецификации, но зато в большей степени соответствуют предметной области бизнес-приложения. С одной стороны, подобные дополнительные или custom тэги можно рассматривать как своеобразные макросы, которые перед передачей документа клиенту будут заменены эквивалентной комбинацией стандартных тэгов. В другом варианте, за custom тэгом может стоять определенный фрагмент программного кода. Например, вполне обычный одинарный тэг может оказаться счетчиком посещений или меню, содержимое которого зависит от той роли, которую данный клиент играет в бизнес-процессе.
Построение custom тэгов связано с написанием определенного программного кода. Технология JSP предусматривает размещение этого кода в отдельном программном модуле — библиотеке custom тэгов. Разработка подобных библиотек может быть поручена сторонним компаниям. Подключение JSP страницы к той или иной библиотеке custom тэгов осуществляется с помощью ранее описанной директивы taglib. Указанная директива связывает дескриптор соответствующей библиотеки с определенным префиксом, который, в свою очередь, идентифицирует в теле JSP страницы все custom тэги из данной библиотеки. Так, директива
объявляет, что в JSP странице используется библиотека дополнительных тэгов, название каждого из которых начинается с префикса dscat. Например:
Программный код данной библиотеки описывается дескриптором exttags.tld. Мы не будем здесь останавливаться на правилах написания дескриптора библиотеки, а рассмотрим лишь один из возможных примеров его реализации:
Создание библиотеки custom тэгов
Custom тэги без обработки содержимого
Программный код для поддержки custom тэга — это специальным образом написанный экземпляр Java класса, который вызывается web контейнером всякий раз, когда требуется обработать JSP страницу, содержащую соответствующий тэг.
В простейшем случае, для поддержки custom тэга можно взять какой-либо из классов бизнес-приложения и дополнить его методами, соответствующими интерфейсу Tag. Если же внешних объектов использовать не надо, то в качестве базового класса можно использовать TagSupport. Эти и другие стандартные классы и интерфейсы находятся в пакете javax.servlet.jsp.tagext.
Пример класса, осуществляющего поддержку custom тэга:
Методы класса, который осуществляет обработку custom тэга, вызываются в определенной последовательности. Когда в JSP странице обработка доходит до открывающего custom тэга, для его обработки вызывается метод doStartTag(). Когда обработка доходит до соответствующего закрывающего тэга, вызывается метод doEndTag(). Для обработки той части JSP страницы, которая заключена между этими двумя тэгами, используются методы doInitBody() и doAfterBody().
Помимо того, что метод doStartTag() может осуществлять какую-либо обработку запроса, большое значение имеет возвращаемое им значение. Если это SKIP_BODY, то информация, заключенная между соответствующими открывающим и закрывающим тэгами, будет игнорироваться, а обработка JSP страницы сразу перейдет на закрывающий тэг. Чтобы содержимое custom тэга все же обрабатывалось, медот должен возвратить EVAL_BODY_INCLUDE. Аналогично, если метод doEndTag() возвратит значение SKIP_PAGE, то оставшаяся часть JSP страницы после закрывающего тэга будет проигнорирована. Чтобы не допустить этого, метод должен возвратить значение EVAL_PAGE.
В некоторых случаях бывает необходимо показать содержимое custom тэга не один, а несколько раз. В этом случае, класс, осуществляющий обработку тэга, должен реализовывать интерфейс IterationTag, либо использовать в качестве родителя класс TagSupport. Чтобы повторить вывод содержимого custom тэга еще раз, необходимо, чтобы методы doStartTag и doAfterBody возвращали EVAL_BODY_AGAIN.
Custom тэги с обработкой содержимого
Если требуется доступ к содержимому custom тэга, то соответствующий Java класс должен реализовывать интерфейс BodyTag или же наследовать класс BodyTagSupport. И в том, и в другом случае класс может реализовать методы doInitBody и doAfterBody.
Метод doInitBody вызывается сразу после того, как выявлено содержимое тэга, но до того, как оно будет обработано. Обычно этот метод используется когда необходимо выполнить инициализацию класса в зависимости от содержимого custom тэга.
Метод doAfterBody вызывается после того, как содержимое custom тэга было обработано. Как и в предыдущем разделе, метод doAfterBody может указывать, следует ли повторить обработку содержимого тэга еще раз. Если это необходимо, метод должен возвратить значение EVAL_BODY_BUFFERED. В противном случае он должен возвратить SKIP_BODY.
В дополнение к двум предыдущим, технологией JSP предусмотрен вызов метода release с тем, чтобы позволить классу, осуществляющему поддержку custom тэга, освободить выделенные ему ресурсы, а также произвести другие необходимые действия для возврата в исходное состояние.
Непосредственно для доступа к содержимому custom тэга технологией предусмотрено два метода: getString и getReader.
Атрибуты в custom тэгах
Помимо информации в промежутке между открывающим и закрывающим тэгами, custom тэг может иметь некоторые атрибуты, которые также могут оказывать влияние на порядок обработки запроса клиента. Для каждого из таких атрибутов в классе, реализующем custom тэг, должен быть указан соответствующий атрибут, а также два метода get и set. Например, если custom тэг имеет вид
то реализующий этот custom тэг класс должен содержать следующий код:
Атрибуты custom тэга также необходимо декларировать в дескрипторе библиотеки custom тэгов.
Следует заметить, что в этом разделе мы рассмотрели лишь наиболее часто используемые методы, связанные с обработкой custom тэгов. К примеру, неосвещенными остались такие важные темы, как интерфейс TryCatchFinally и абстрактный класс BodyContent.






