Серверные страницы Java
Серверные страницы Java [7,8] представляют собой компоненты, разрабатываемые на смеси из HTML и Java и предназначенные для динамического создания HTML-документов, содержащих результаты обработки запросов пользователя. Таким образом, JSP обычно играют роль представления в образце "данные–представление–обработчик", принятом за основу архитектуры приложений J2EE. Результатом работы JSP является HTML-страничка, а вставки Java кода служат для построения некоторых ее элементов на основе результатов работы приложения.
При работе Web-приложения JSP компилируются в сервлеты специального вида. При этом основное содержание страницы JSP превращается в метод doGet(), в котором HTML-элементы записываются в поток содержимого ответа в неизменном виде, а элементы Java-кода преобразуются в код, записывающий некоторые данные в тот же поток на основании параметров запроса или данных приложения.
Для развертывания JSP-страниц необходимо их описание в дескрипторе развертывания приложения web.xml, которое устроено так же, как описание сервлетов. Сами JSP-страницы помещаются, вместе с HTML-файлами и другими файлами, используемыми приложением, в корневую директорию этого приложения или ее поддиректории.
Основные интерфейсы и базовые классы JSP-страниц и их отдельных элементов находятся во входящих в J2EE SDK пакетах javax.servlet.jsp, javax.servlet.jsp.el, javax.servlet.jsp.tagext.
Элементами JSP-страниц могут быть обычные теги HTML, а также специальные элементы JSP — директивы, теги или действия (tags, actions) и скриптовые элементы.
JSP-директивы описывают свойства страницы в целом и служат для передачи информации механизму управления JSP-страницами.
Директивы имеют следующий общий синтаксис.
<%@ directive attribute1="value1" ... attributeN="valueN" %>.
Основные директивы JSP следующие:
- Директива page предоставляет общую информацию о данной странице и статически включаемых в нее файлах. Такая директива на странице может быть только одна. Она может иметь следующие атрибуты.
- import = "имена включаемых классов и пакетов через запятую"
Порождает соответствующую Java-директиву import в сгенерированном коде сервлета. - contentType = "MIME-тип[;charset=таблица символов]"
Задает тип MIME для генерируемого документа. По умолчанию используется text/html. Эквивалентен скриплету
<% response.setContentType(MIME-тип); %> (см. далее). - isThreadSafe = "true|false"
Значение true позволяет использовать один экземпляр сервлета, полученного из странички, для обработки множественных запросов. При этом необходимо синхронизовать доступ к данным этого сервлета. - session = "true|false"
Значение true предписывает привязать сервлет к имеющейся HTTP-сессии, значение false говорит, что сессии использоваться не будут и обращение к переменной session приведет к ошибке. - autoFlush = "true|false"
Определяет необходимость сбрасывать буфер вывода при заполнении. - buffer = "размер в KB|none"
Задает размер буфера для выходного потока сервлета. - extends = "наследуемый класс"
Определяет класс, наследуемый сгенерированным из данной JSP сервлетом. - errorPage = "url странички с информацией об ошибках"
Определяет страницу, которая используется для обработки исключений, не обрабатываемых в рамках данной. - isErrorPage = "true|false"
Допускает или запрещает использование данной страницы в качестве страницы обработки ошибок. - language = "java"
Определяет язык программирования, применяемый в скриптовых элементах данной страницы. Пока есть возможность использовать только Java. Впоследствии предполагается (аналогично .NET) разрешить использование других языков, код которых будет также транслироваться в байт-код, интерпретируемый JVM.
- import = "имена включаемых классов и пакетов через запятую"
- Директива include обеспечивает статическое (в ходе трансляции JSP в сервлет) включение в страничку внешнего документа. Она имеет атрибут file, значением которого должна быть строка, задающая URL включаемого файла.
- Директива taglib указывает используемую в данной странице библиотеку пользовательских тегов.
Она имеет два атрибута — uri, значением которого является URI библиотеки, и prefix, определяющий префикс тегов из данной библиотеки. Префикс употребляется в дальнейшем с тегами только данной библиотеки. Он не может быть пустым и не должен совпадать с одним из зарезервированных префиксов jsp, jspx, java, javax, servlet, sun, sunw.
Теги или действия определяют основные действия, выполняемые при обработке данных и построении результирующего документа.
Теги могут быть стандартными, использование которых возможно в любой странице без дополнительных объявлений, или пользовательскими, которые могут употребляться, только если предварительно с помощью директивы taglib была подключена содержащая их библиотека. Любой тег имеет следующий синтаксис.
<tagprefix:tag attribute1="value1" … attributeN="valueN" />
Теги могут содержать вложенные теги, такие как jsp:param, jsp:attribute. В этом случае они выглядят следующим образом.
<tagprefix:tag attribute1="value1" … attributeN="valueN"> … (вложенные теги) </tagprefix:tag>
Стандартные теги имеют префикс jsp, а префикс пользовательских тегов определяется в директиве taglib, подключающей содержащую их библиотеку.
Имеется довольно много стандартных тегов. Основные из них следующие.
- jsp:include
Определяет динамическое включение некоторой страницы или файла в данную страницу при обработке запроса. С помощью вложенных тегов jsp:param может указывать один или несколько пар параметр-значение в качестве параметров включаемой страницы.
Имеет атрибуты page, определяющий URL включаемой страницы, и flush, имеющий значения true или false в зависимости от того, нужно ли сразу после включения сбросить буфер выходного потока в генерируемом ответе или нет. - jsp:useBean
Определяет используемый объект или компонент. Фактически такой тег эквивалентен декларации переменной определенного типа, инициализируемой определенным объектом и доступной в рамках некоторого контекста.
Имеет следующие атрибуты.
- id = "имя объекта"
Задает имя объекта, которое будет использоваться в коде JSP. Должно быть уникально в пределах страницы. - class = "класс объекта"
Задает класс этого объекта. - scope = "page|request|session|application"
Задает область видимости декларируемого объекта. - type = "тип используемой ссылки на объект"
Указанный тип должен быть предком класса объекта. Это тип декларируемой переменной, а класс объекта определяет истинный тип объекта, хранящегося в ней.
- id = "имя объекта"
- jsp:setProperty, jsp:getProperty
Устанавливает или получает значение свойства объекта.
Атрибут name определяет имя объекта, чье свойство используется, а атрибут property — имя свойства.
Тег jsp:getProperty записывает полученное значение свойства в результирующий документ в виде строки (результата вызова toString() для этого значения).
Тег jsp:setProperty имеет также дополнительный атрибут — либо value, значение которого присваивается свойству, либо param, который указывает имя параметра запроса, значение которого записывается в свойство. Если в теге jsp:setProperty вместо имени свойства в атрибуте property указан символ *, то всем свойствам указанного объекта с именами, совпадающими с именами параметров запроса, будут присвоены значения соответствующих параметров. - jsp:forward
Этот тег употребляется для перенаправления запроса на обработку другой странице. URL этой страницы указывается в качестве значения атрибута page. В качестве этого URL может использоваться JSP-выражение (см. далее), вычисляемое на основе параметров запроса.
С помощью вложенных тегов jsp:param можно передать одно или несколько значений параметров странице, на которую переключается управление. - jsp:plugin
Этот тег вставляет аплет или компонент JavaBean на страницу. Параметры инициализации компонента могут быть заданы при помощи вложенного тега jsp:params. Кроме того, jsp:plugin имеет следующие атрибуты.- type = "bean|applet"
Задает вид вставляемого компонента. - code = "имя файла класса компонента (включая расширение .class)"
- codebase = "имя директории, в которой находится файл класса компонента"
Если этот атрибут отсутствует, используется директория, содержащая данную JSP-страницу. - name = "имя используемого экземпляра компонента"
- archive = "список разделенных запятыми путей архивных файлов, которые будут загружены перед загрузкой компонента"
Эти архивы содержат дополнительные классы и библиотеки, необходимые для работы компонента. - align = "bottom|top|middle|left|right"
Задает положение экземпляра компонента относительно базовой строки текста содержащего его HTML-документа. - height = "высота изображения объекта в точках"
- width = "ширина изображения объекта в точках"
- hspace = "ширина пустой рамки вокруг объекта в точках"
- vspace = "высота пустой рамки вокруг объекта в точках"
- jreversion = "версия JRE, необходимая для работы компонента"
- type = "bean|applet"
По умолчанию используется версия 1.1.
Пользовательские теги могут быть определены для выполнения самых разнообразных действий. Одна из наиболее широко используемых библиотек тегов core (подключаемая с помощью директивы <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c" %>), содержит теги, представляющие все конструкции языка Java.
Например, с помощью тега <c:set var="variable" value="value" /> можно присвоить значение value в переменную variable, с помощью тега <c:if test="expression">…</c:if> можно выполнить код JSP, расположенный внутри этого тега только при том условии, если expression имеет значение true, с помощью тега <c:forEach var="variable" items="collection">…</c:forEach> можно выполнить содержащийся в нем код для всех элементов коллекции collection, используя для обращения к текущему элементу переменную variable.
Таким образом, весь код, который может быть записан в виде скриптовых элементов (см. далее), можно записать и в виде тегов. Применение тегов при этом вносит некоторые неудобства для Java-программиста. Но оно же делает код JSP-страниц более однородным и позволяет обрабатывать его с помощью инструментов для разработки Web-сайтов, гораздо лучше приспособленных к работе с размеченным с помощью тегов текстом.
Скриптовые элементы могут иметь один из следующих трех видов.
- JSP-объявления, служащие для определения вспомогательных переменных и методов. Эти переменные становятся впоследствии полями сгенерированного по JSP сервлета, а методы — его методами. Синтаксис JSP-объявления следующий.
<%! код на Java %> - Скриплеты, которые служат для вставки произвольного кода, обрабатывающего данные запроса или генерирующего элементы ответа, в произвольное место. Они имеют следующий синтаксис.
<% код на Java %> - JSP-выражения, используемые для вставки в какое-то место в результирующем документе вычисляемых значений (они также могут использоваться в качестве значений атрибутов тегов). Их синтаксис может иметь три вида.
<% = выражение на Java %> ${выражение на Java} #{выражение на Java}
Различий между первым и вторым способом представления выражений практически нет. Выражение третьего типа вычисляется отлаженно — вычисление его значения происходит только тогда, когда это значение действительно понадобится.
Комментарии в коде JSP оформляются в виде содержимого тега <%-- … --%>. Встречающийся в них код не обрабатывается во время трансляции и не участвует в работе полученного сервлета. Элементы кода внутри HTML-комментариев <!-- … --> обрабатываются так же, как и в других местах — они генерируют содержимое комментариев в результирующем HTML-документе.
Помимо объявленных в объявлениях и тегах jsp:useBean переменных в скриптовых элементах могут использоваться неявно доступные объекты, связанные с результирующим сервлетом, обрабатываемым им запросом и генерируемым ответом, например, следующие.
- request — запрос клиента (тип ServletRequest).
- param — параметры запроса (тип Map).
- response — ответ сервера (тип ServletResponse).
- out — выходной поток сервлета (тип PrintWriter).
- session — сеанс (тип HttpSession).
- application —приложение (ServletContext).
- config — конфигурация сервлета (ServletConfig).
- pageContext — контекст страницы (javax.servlet.jsp.PageContext).
- exception — произошедшее исключение.
Ниже приведен пример JSP страницы, генерирующей таблицу балансов клиентов некоторой организации в долларовом и рублевом выражениях.
<%@ page import="java.util.Date, java.util.Iterator, com.company.Client" %> <jsp:useBean id="clients" class="com.company.ClientList" scope="page" /> <jsp:useBean id="convertor" class="com.company.ExchangeRate" scope="page" /> <html> <head> <title>Table of clients</title> </head> <body> <h3 align="center">Table of clients</h3> Created on <%= new Date() %> <br><br>
<table width="98%" border="1" cellspacing="1" cellpadding="1"> <tr> <%! private double dollarsToRubles(double m) { return m*convertor.getDollarToRubleRate(new Date()); } %> <th width="50%" scope="col">Client</th> <th width="25%" scope="col">Balance, dollars</th> <th width="25%" scope="col">Balance, rubles</th> </tr> <% Iterator it = clients.getNumberOfClients().iterator(); while(it.hasNext()) { Client сlient = (Client)it.next(); %> <tr> <td> ${client.getFullName()} </td> <td> ${client.getBalance()} </td> <td> ${dollarsToRubles(client.getBalance())} </td> </tr> <% } %> </table> <br><br>
<jsp: include page="footer.txt" flush= "true" /> </body> </html>
Пример 14.5.