Как РІРёРґРЅРѕ РёР· приведенных РІ предыдущей главе листингов, большую часть сервлета занимают операторы вывода РІ выходной поток тегов HTML, формирующих результат — страницу HTML. Рти операторы почти без изменений повторяются РёР· сервлета РІ сервлет. Возникла идея РЅРµ записывать теги HTML РІ операторах Java, Р°, наоборот, записывать операторы Java РІ РєРѕРґРµ HTML СЃ помощью тегов специального РІРёРґР°. Затем обработать полученную страницу препроцессором, распознающим РІСЃРµ теги Рё преобразующим РёС… РІ РєРѕРґ сервлета Java.
Так получился язык разметок JSP (JavaServer Pages), расширяющий язык HTML тегами вида <% имя_тега атрибуты %>. С помощью тегов можно не только записать описания, выражения и операторы Java, но и вставить в страницу файл с текстом или изображением, вызвать объект Java, компонент JavaBean или компонент EJB.
Программист может даже расширить язык JSP своими собственными, как говорят, пользовательскими тегами (custom tags), которые сейчас чаще называют расширениями тегов (tag extensions).
В листинге 27.1 приведен пример JSP-страницы "Hello, World!" с текущей датой.
Листинг 27.1. Простейшая страница JSP
<%@ page contentType=Mtext/html;charset=utf-8M %>
<%@ page import="java.util.*, java.text.*" %>
content="text/html; charset=utf-8">
Hello, World!
Сегодня <%= getFormattedDate() %>
String getFormattedDate(){
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm"); return sdf.format(new Date());
}
%>
Контейнер сервлетов расширили препроцессором, переводящим запись, подобную листингу 27.1, в сервлет. В контейнере сервлетов Tomcat такой препроцессор называется Jasper. Препроцессор срабатывает автоматически при первом обращении к странице JSP. Полученный в результате его работы сервлет тут же компилируется и выполняется. Откомпилированный сервлет затем хранится в контейнере, так же как и все сервлеты, и выполняется при следующих вызовах страницы JSP.
Для сервлетов и страниц JSP придумано общее название — Web-компоненты (Web Components). Контейнер сервлетов, расширенный средствами работы с JSP, называется Web-контейнером (Web Container или JSP Container). Приложение, составленное из сервлетов, страниц JSP, апплетов, документов HTML и XML, изображений и прочих документов, относящихся к приложению, называется Web-приложением (Web Application).
Весь статический текст HTML, называемый в документации JSP шаблоном HTML (template HTML), сразу направляется в выходной поток. Выходной поток страницы буферизуется. Буферизацию обеспечивает класс JspWriter, расширяющий класс Writer. Размер буфера по умолчанию 8 Кбайт, его можно изменить атрибутом buffer тега <%@ page>. Наличие буфера позволяет заносить заголовки ответа в выходной поток вперемешку с выводимым текстом. В буфере заголовки будут размещены перед текстом.
Таким образом, программисту достаточно написать страницу JSP, записать ее в файл с расширением jsp и установить файл в контейнер, подобно странице HTML, не заботясь о компиляции. При установке можно задать начальные параметры страницы JSP так же, как и начальные параметры сервлета.
В то время как создавался и развивался язык JSP, широкое распространение получил язык XML, который мы рассмотрим в главе 28. Для совместимости с ним все теги JSP продублированы элементами XML с именами из пространства имен , получающего, как правило, префикс jsp:. Теги JSP, записанные в форме XML, сейчас называют действиями (actions) JSP.
Например, страницу JSP, представленную в листинге 27.1, можно написать в форме XML так, как это сделано в листинге 27.2.
Листинг 27.2. Простейшая страница JSP в форме XML
contentType="text/html;charset=utf-8" />
import="j ava.util.Date, j ava.text.SimpleDateFormat" />
content="text/html; charset=utf-8">
Hello, World!
Сегодня ]]>
]]>
String getFormattedDate(){
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMMM-yyyy hh:mm"); return sdf.format(new Date());
}
Файл со страницей JSP, записанной в форме XML, обычно получает расширение jspx.
Некоторые теги —
Вы уже знаете, что язык XML различает регистр букв. Теги XML записываются, как правило, строчными буквами. Значения атрибутов тегов обязательно записываются в кавычках или апострофах. У большинства элементов XML есть открывающий тег (start tag) с необязательными атрибутами, тело (body) и закрывающий тег (end tag), они имеют вид:
Тело элемента или вложенные элементы XML
Тело элемента может быть пустым, тогда элемент выглядит так:
Внимание!
Если между открывающим и закрывающим тегом есть хотя бы один пробел, то тело элемента уже не пусто.
Наконец, тело может отсутствовать, тогда закрывающий тег не пишется, а в открывающем теге перед закрывающей угловой скобкой ставится наклонная черта:
Если у XML-элемента есть тело, то его открывающий тег заканчивается просто угловой скобкой, без наклонной черты.
Спецификация "JavaServer Pages Specification" не рекомендует смешивать в одном документе теги вида JSP с элементами XML. Страницу HTML, в которую вставлены теги вида <%...%>, она официально называет страницей JSP (JSP Page), а документ XML с тегами вида
Документ JSP РїСЂРѕС…РѕРґРёС‚ еще РѕРґРЅСѓ стадию предварительной обработки, РЅР° которой РѕРЅ приводится РІ полное соответствие СЃ синтаксисом XML. Рто приведение включает РІ себя запись корневого элемента СЃ пространством имен Рё вставку элементов cdata. После приведения получается документ XML, официально называемый представлением XML (XML View).
Стандартные действия (теги) JSP
Набор стандартных тегов JSP довольно прост. При их написании следует помнить три правила:
□ язык JSP различает регистр букв, как и язык Java;
□ при записи атрибутов, после знака равенства, отделяющего имя атрибута от его значения, нельзя оставлять пробелы;
□ значения атрибутов можно заносить не только в кавычки, но и в апострофы.
Будем записывать теги и в старой форме JSP, и в новой форме элементов XML. Комментарий на страницах JSP отмечается тегом
<%— Комментарий —%>
или тегом
Комментарий первого вида не передается клиенту. Все, что написано внутри него, не обрабатывается препроцессором. Комментарий второго вида переносится в формируемую HTML-страницу. Все JSP-теги, записанные внутри такого комментария, интерпретируются.
Объявления полей и методов Java записываются в теге
<%! Объявления %>
После обработки препроцессором они будут полями и методами сервлета.
Выражение Java записывается в теге
<%= Выражение %>
Выражение вычисляется, результат подставляется на место тега. Учтите, что в конце выражения не надо ставить точку с запятой, поскольку выражение, завершающееся точкой с запятой, — это уже оператор.
Фрагмент кода Java, называемый в JSP скриптлетом (scriptlet), который может включать в себя не только операторы, но и определения, записывается в теге
<% Скриптлет %>
Такой фрагмент после обработки препроцессором попадет в метод _jspService () создаваемого сервлета, являющийся оболочкой метода service ().
Включение файла во время компиляции производится тегом
<%@ include file="URL файла относительно контекста" %>
Общие свойства страницы JSP задаются тегом
<%@ page Атрибуты %>
Все атрибуты здесь необязательны. В листингах 27.1 и 27.2 уже использованы атрибуты contentType и import этого тега. Другие атрибуты:
□ pageEncoding=" Кодировка" — по умолчанию "ISO 8859-1";
□ extends="Долное имя расширяемого класса" — суперкласс того класса, в который компилируется страница JSP;
□ session=" true или false" — создавать ли сеанс связи с клиентом, по умолчанию
"true";
□ buffer="Nkb или none " — размер выходного буфера, по умолчанию "8kb";
□ autoFlush=" true или false" — автоматическая очистка буфера по его заполнении, по умолчанию "true"; если значение этого атрибута равно "false", то при переполнении буфера выбрасывается исключение;
□ isThreadSafe=" true или false" одновременный доступ к странице нескольких клиентов, по умолчанию "true"; если этот атрибут равен "false", то полученный после компиляции сервлет реализует устаревший и не используемый сейчас интерфейс
SingleThreadModel;
□ info="какой-то текст" — сообщение, которое можно будет прочитать методом
getServletInfo();
□ errorPage=" URL относительно контекста" — адрес страницы JSP, которой посылается исключение и которая показывает сообщения, посылаемые исключением;
□ isErrorPage=" true или false" — может ли данная страница JSP использовать объектисключение exception, или он будет переслан другой странице, по умолчанию
"false".
Два последних атрибута требуют разъяснения. Дело РІ том, что если страница JSP РЅРµ обрабатывает исключение, Р° выбрасывает его дальше, то Web-контейнер формирует страницу HTML c сообщениями РѕР± исключении Рё посылает ее клиенту. Рто мешает работе клиента. Атрибут errorPage позволяет вместо страницы HTML СЃ сообщениями передать встроенный объект-исключение exception для обработки странице JSP, которую предварительно создал разработчик. Атрибут isErrorPage страницы-обработчика исключения должен равняться "true".
Пусть, например, имеется страница JSP:
<%@ page errorPage="myerrpage.jsp" %>
<%
String str = <%= request.getParameter("name") %>; int n = str.length();
%>
Ссылка str может оказаться равной null, тогда метод length() выбросит исключение. Контейнер создаст встроенный объект exception и передаст его странице myerrpage.jsp. Она может выглядеть так:
<%@ page isErrorPage="true" %>
При выполнении страницы JSP выброшено исключение:
<%= exception %>
На этом набор тегов вида <%...%> заканчивается. Остальные теги записываются только в форме элементов XML.
Включение файла на этапе выполнения или включение результата выполнения сервлета, если этот результат представлен страницей JSP, выполняется элементом
В этом теге может быть один или два атрибута. Обязательный атрибут
page="относительный URL или выражение JSP"
задает адрес включаемого ресурса. Здесь "выражение JSP" записывается в форме JSP
<%= выражение %> или в форме XML
В результате выражения должен получиться адрес URL. Чаще всего в качестве выражения используется обращение к методу getParameter(String).
Второй, необязательный, атрибут
flush="true или false"
указывает, очищать ли выходной буфер перед включением ресурса. Его значение по умолчанию "false".
Вторая форма элемента, include, содержит теги
Здесь записываются теги вида
В теле элемента можно записывать произвольные параметры. Они имеют вид
value="значение параметра или выражение JSP" />
"Выражение JSP" записывается так же, как и в заголовке тега. Параметры передаются включаемому ресурсу как его начальные параметры, и их имена, разумеется, должны совпадать с именами начальных параметров ресурса.
Включаемый JSP-файл может быть оформлен не полностью, а содержать только отдельный фрагмент кода JSP. В таком случае его имя записывают обычно с расширением jspf (JSP Fragment).
Следующий стандартный тег
xmlns:j sp="">
Еще один простой стандартный тег
while(k < 10) {a[k]++; b[k++] = $1;}
Вы, наверное, заметили, что теги JSP не создают никакого кода инициализации сервлета, того, что обычно записывается в метод init() сервлета. Такой код при необходимости как-то инициализировать полученный после компиляции сервлет надо записать в метод j spInit () по следующей схеме:
public void jspInit(){
// Записываем код инициализации
}
Аналогично, завершающие действия сервлета можно записать в метод jspDestroy() по такой схеме:
public void jspDestroy(){
// Записываем код завершения
}
Язык записи выражений EL
Хотя на странице JSP можно записать любое выражение языка Java в теге <%=.. .%> или в элементе XML
Р’ языке JSP EL выражения окружаются символами ${...}, например ${2 + 2}. Рто окружение дает сигнал Рє вычислению заключенного РІ РЅРёС… выражения. Выражение, записанное без этих символов, РЅРµ будет вычисляться Рё воспримется как простой набор символов.
В выражениях можно использовать данные типов boolean, long, float и строковые константы, заключенные в кавычки или апострофы. Значение null считается отдельным типом.
РЎ данными этих типов можно выполнять арифметические операции +, -, *, /, %, сравнения ==, !=, <, >, <=, >=, логические операции !, &&, || Рё условную операцию ?:. Рнтересно, что сравнения "равно", "РЅРµ равно", "меньше", "больше", "меньше или равно", "больше или равно" можно записать РЅРµ только специальными символами, РЅРѕ Рё сокращениями eq, ne, lt, gt, le, ge слов "equal", "not equal", "less than", "greater", "less than or equal", "greater or equal". Рто позволяет оставить знаки "больше" Рё "меньше" только для записи тегов XML. РџРѕ аналогии операцию деления можно записать словом div, операцию взятия остатка РѕС‚ деления — словом mod, Р° логические операции — словами not, and Рё or.
В выражениях можно обращаться к переменным, например ${name}, полям и методам объектов, например ${pageContext.request.requestURI}. В выражениях языка JSP EL можно использовать следующие предопределенные объекты:
□ pageContext — объект типа PageContext;
□ pageScope — объект типа Map, содержащий атрибуты страницы и их значения;
□ requestScope — объект типа Map, содержащий атрибуты запроса и их значения;
□ sessionScope — объект типа Map, содержащий атрибуты сеанса и их значения;
□ applicationScope — объект типа Map, содержащий атрибуты приложения и их значения;
□ param — объект типа Map, содержащий параметры запроса, получаемые в сервлетах методом ServletRequest. getParameter (String name);
□ paramValues — объект типа Map, содержащий параметры запроса, получаемые в сервлетах методом ServletRequest.getParameterValues(String name);
□ header — объект типа Map, содержащий заголовки запроса, получаемые в сервлетах методом ServletRequest. getHeader (String name);
□ headerValues — объект типа Map, содержащий заголовки запроса, получаемые в сервлетах методом ServletRequest.getHeaders(String name);
□ initParam — объект типа Map, содержащий параметры инициализации контекста, получаемые в сервлетах методом ServletContext.getInitParameter(String name);
□ cookie — объект типа Map, содержащий имена и объекты типа Cookie.
Наконец, в выражениях языка JSP EL можно записывать вызовы функций.
Встроенные объекты JSP
Каждая страница JSP может содержать в выражениях и скриптлетах девять готовых встроенных объектов, создаваемых контейнером JSP при выполнении сервлета, полученного после компиляции страницы JSP. Мы уже использовали объекты request и exception. У этих объектов заданы определенные имена и типы. В большинстве случаев заданы не точные типы объектов, а их суперклассы и интерфейсы:
□ request — объект типа ServletRequest, чаще всего это объект типа HttpServletRequest;
□ response — объект типа ServletResponse, обычно это объект типа HttpServletResponse;
□ config — объект типа ServletConfig;
□ application — объект типа ServletContext;
□ session — объект типа HttpSession;
□ pageContext — объект типа PageContext; □ out — выходной поток типа JspWriter; □ page — произвольный объект класса Object; □ exception — исключение класса Throwable. В листинге 27.3 приведена страница JSP, использующая скриптлеты и встроенные объекты для организации запроса к базе СДО, описанной в предыдущей главе.
Листинг 27.3. Страница JSP, использующая скриптлеты
<%@ page import="java.sql.*"
contentType="text/html;charset=utf-8" %>
Здравствуйте
<%= (request.getRemoteUser() != null ? ", " + request.getRemoteUser() : "") %>!
<%
try{
Connection conn =
DriverManager.getConnection(
(String)session.getValue("connStr"), "sdoadmin", "sdoadmin"); Statement st = conn.createStatement ();
ResultSet rs = st.executeQuery ("SELECT name, mark " +
"FROM students ORDER BY name");
if (rs.next()){
%>
<1>Ученик1> | <Й>ОценкаС> |
---|---|
<%= rs.getString(1) %> | <%= rs.getInt(2) %> |
<%= rs.getString(1) %> | <%= rs.getInt(2) %> |
<%
}else{
%>
Рзвините, РЅРѕ сведений нет!
<%
}
rs.close(); st.close();
}catch(SQLException e){
out.println(,,
Cшибка при выполнении запроса:"); out.println ("
" + e + "");
}
%>
Обращение к компоненту JavaBean
РР· страницы JSP можно обращаться Рє объектам Java, оформленным как компоненты JavaBeans. Рто выполняется тегом
[ scope="page или request или session или application" ]
Класс компонента
/> "РРјСЏ экземпляра компонента" id определяет РёРјСЏ JavaBean, уникальное РІ заданной атрибутом scope области. РџРѕ умолчанию принимается область page — текущая страница JSP Рё включенные РІ нее страницы. Компонент хранится как атрибут контекста указанной атрибутом scope области Рё вызывается методом getAttribute () соответствующего контекста.
□ Если атрибут scope равен "page", то компонент хранится как один из атрибутов объекта класса PageContext.
□ Если атрибут scope равен "request", то компонент хранится как атрибут объекта типа
ServletRequest.
□ Если атрибут scope равен "session", то компонент будет атрибутом объекта типа
HttpSession.
□ Наконец, если атрибут scope равен "application", то компонент станет атрибутом типа ServletContext.
Определенное в атрибуте id имя используется при обращении к свойствам и методам компонента JavaBean. Обязательный атрибут "класс компонента" описывается одним из трех способов:
□ class="полное имя класса" [ type="полное имя суперкласса" ]
□ beanName="полное имя класса или выражение JSP"
type="полное имя суперкласса"
□ type="полное имя суперкласса"
При обращении к компоненту JavaBean в теле элемента можно задавать и другие элементы.
Свойство (property) уже вызванного тегом
property="имя" value="строка или выражение JSP" />
или тегом
property="имя" param^'n^ параметра запроса" />
Во втором случае свойству компонента JavaBean дается значение, определенное параметром запроса, имя которого указано атрибутом param.
Третья форма этого тега
применяется в тех случаях, когда имена всех свойств компонента JavaBean совпадают с именами параметров запроса вплоть до совпадения регистров букв.
Для получения свойств уже вызванного компонента JavaBean с именем "myBean" существует тег
В его атрибуте property уже нельзя записывать звездочку.
Выполнение апплета в браузере клиента
Если в браузере клиента установлен Java Plug-in, то в нем можно организовать выполнение апплета или компонента с помощью элемента
[code="имя класса апплета"]
[codebase= "каталог апплета"]
Прочие параметры заголовка тега
>
Здесь записываются необязательные параметры
Как видно из этого описания, элемент
□ name="имя экземпляра";
□ archive="список адресов URL архивов апплета";
□ align="bottom или top, или middle, или left, или right";
□ height="высота в пикселах или выражение JSP";
□ width="ширина в пикселах или выражение JSP";
□ hspace="горизонтальные поля в пикселах";
□ vspace="вертикальные поля в пикселах";
□ jreversion="версия JRE, по умолчанию 1.2";
□ nspluginurl=,,полный адрес URL, с которого можно загрузить Java Plug-in для Netscape Communicator";
□ iepluginurl=,,полный адрес URL, с которого можно загрузить Java Plug-in для Internet Explorer".
В теле элемента можно поместить любые параметры вида
которые будут переданы апплету или компоненту. Кроме того, в теле элемента допустимо указывать сообщение, которое появится в окне браузера, если апплет или компонент не удалось загрузить. Для этого используется элемент
Передача управления
Страница JSP имеет возможность передать управление РґСЂСѓРіРѕРјСѓ ресурсу: странице JSP, сервлету или странице HTML. Рто выполняется тегом
содержащим адрес объекта, которому передается управление. Адрес может быть получен как результат вычисления выражения JSP. Управление не возвращается, и строки, следующие за тегом
Ресурсу можно передать один или несколько параметров в теле элемента:
Пользовательские теги
Разработчик страниц JSP может расширить набор стандартных действий (тегов) JSP, создав СЃРІРѕРё собственные, как РіРѕРІРѕСЂСЏС‚, пользовательские теги (custom tags). Пользовательские теги организуются РІ РІРёРґРµ целой библиотеки, даже если РІ нее РІС…РѕРґРёС‚ только РѕРґРёРЅ тег. Описание каждой библиотеки хранится РІ отдельном XML-файле СЃ расширением tld, называемым описателем библиотеки тегов TLD (Tag Library Descriptor). Ртот файл хранится РІ каталоге WEB-INF данного Web-приложения или РІ его подкаталоге. Если Web-приложение упаковано РІ JAR-архив, то TLD-файлы, описывающие библиотеки пользовательских тегов этого приложения, находятся РІ каталоге META-INF архива.
В листинге 27.4 приведен пример простого TLD-файла, описывающего библиотеку пользовательских тегов с одним тегом head, реализуемым классом HeadTag. Полное объяснение использованных в нем элементов XML вы получите в следующей главе.
Листинг 27.4. Описатель TLD библиотеки тегов
xmlns:xsi="" xsi:schemaLocation=
" web-jsptaglibrary 2 0.xsd" version="2.0">
На странице JSP перед применением пользовательских тегов следует сослаться на библиотеку тегом
<%@ taglib uri="адрес URI библиотеки"
prefix="префикс тегов библиотеки" %>
Например, если на странице JSP написан тег
<%@ taglib uri="/WEB-INF/sdotaglib.tld" prefix="sdo" %>
то на ней можно использовать теги вида
У этого тега нет прямого XML-эквивалента. Префикс тегов библиотеки и ее адрес определяются в форме XML как пространство имен атрибутом xmlns в элементе
xmlns:j sp="" xmlns:sdo="/WEB-INF/sdotaglib.tld" version="2.0"
>
Страница JSP
Необязательный элемент
Как видите, к каждой странице JSP всегда подключается библиотека с префиксом тегов jsp. Стандартные (core) действия JSP входят в эту библиотеку. Префиксы jsp, jspx, java, j avax, servlet, sun, sunw зарезервированы корпорацией Sun Microsystems, их нельзя употреблять в библиотеках пользовательских тегов.
В конфигурационном файле web.xml можно создать псевдонимы адреса URI библиотеки с помощью элемента
После этого на странице JSP можно написать ссылку на библиотеку так:
<%@ taglib uri="/sdo" prefix="sdo" %>
Псевдоним может быть указан и в TLD-файле, в элементе
Каждый тег создаваемой библиотеки реализуется классом Java, называемым РІ документации обработчиком тега (tag handler). Обработчик тега должен реализовать интерфейс Tag, Р° если Сѓ тега есть тело, которое надо выполнить несколько раз, то нужно реализовать его расширение — интерфейс IterationTag. Если же тело пользовательского тега требует предварительной обработки, то следует использовать расширение интерфейса IterationTag — интерфейс BodyTag. Рти интерфейсы собраны РІ пакет j avax. servlet. j sp.tagext. Р’ нем есть Рё готовые реализации указанных интерфейсов — класс TagSupport, реализующий интерфейс IterationTag, Рё его расширение — класс BodyTagSupport, реализующий интерфейс BodyTag.
Ртак, для создания пользовательского тега без тела или СЃ телом, РЅРѕ РЅРµ требующим предварительной обработки, СѓРґРѕР±РЅРѕ расширить класс TagSupport, Р° для создания тега СЃ телом, которое надо предварительно преобразовать, — класс BodyTagSupport.
Классы, реализующие библиотеку тегов, хранятся в каталоге WEB-INF/classes, а если они упакованы в JAR-архив — то в каталоге WEB-INF/lib своего Web-приложения. Если библиотека разделяется несколькими Web-приложениями, то она хранится в каком-нибудь общем каталоге, например common/lib. Соответствие между именами тегов и классами, реализующими их, указывается в TLD-файле, описывающем библиотеку, в XML-элементе
Если после этого на странице JSP написать пользовательский тег
или с помощью языка JSP EL:
то для обработки данного тега будет создан объект класса RegTag из пакета sdotags.
Класс-обработчик пользовательского тега
Как уже было сказано ранее, класс-обработчик элемента, не имеющего тела, или тело которого не требует преобразований, должен реализовать интерфейс Tag или расширить класс TagSupport. Если тело элемента перед посылкой клиенту надо преобразовать, то классу-обработчику следует реализовать интерфейс BodyTag или расширить класс BodyTagSupport. В случае простых преобразований можно реализовать интерфейс SimpleTag или расширить класс SimpleTagSupport.
Основной метод интерфейса Tag
public int doStartTag();
выполняет действия, предписанные открывающим тегом. К нему сервлет обращается автоматически, начиная обработку элемента. Метод должен вернуть одну из двух констант интерфейса Tag, указывающих на дальнейшие действия:
□ eval_body_include — обрабатывать тело элемента;
□ skip_body — не обрабатывать тело элемента.
После завершения этого метода сервлет обращается к методу
public int doEndTag();
который выполняет действия, завершающие обработку пользовательского тега. Метод возвращает одну из двух констант интерфейса Tag:
□ eval_page — продолжать обработку страницы JSP;
□ ski p_page — завершить на этом обработку страницы JSP.
Рнтерфейс IterationTag добавляет метод
public int doAfterTag();
позволяющий обработать повторно тело пользовательского тега. Он будет выполняться перед методом doEndTag (). Если метод doAfterTag () возвращает константу EVAL_BODY_AGAI N интерфейса IterationTag, то тело элемента будет обработано еще раз, если константу ski p_body — обработка тела не станет повторяться.
Рнтерфейс BodyTag позволяет буферизовать выполнение тела элемента. Буферизация производится, если метод doStartTag() возвращает константу EVAL_BODY_BUFFERED интерфейса BodyTag. Р’ таком случае перед обработкой тела тега контейнер обращается Рє методу
public void doInitBody();
который может выполнить различные предварительные действия.
У этих методов нет аргументов, они получают информацию из объекта класса PageContext, который всегда создается Web-контейнером для выполнения любой страницы JSP. При реализации интерфейса Tag или BodyTag данный объект можно получить методом getPageContext ( ) класса JspFactory, предварительно получив объект класса JspFactory его собственным статическим методом getDefaultFactory(). Сложность таких манипуляций — еще один аргумент для того, чтобы не реализовывать интерфейсы, а расширять класс TagSupport или класс BodyTagSupport.
Ртак, для создания пользовательского тега без тела или СЃ телом, РЅРµ требующим обработки, удобнее всего расширить класс TagSupport, Р° для создания пользовательского тега СЃ обработкой тела — расширить класс BodyTagSupport. РџСЂРё этом разработчик получает РІ СЃРІРѕРµ распоряжение объект класса PageContext просто РІ РІРёРґРµ защищенного поля
pageContext.
Описанные ранее методы реализованы в классе TagSupport очень просто:
public int doStartTag() throws JspException{ return SKIP_BODY;
}
public int doEndTag() throws JspException{ return EVAL_PAGE;
}
public int doAfterBody() throws JspException{ return SKIP BODY;
В подклассе BodyTagSupport реализация метода dostartTag () немного изменена:
public int doStartTag() throws JspException{ return EVAL_BODY_BU FFERED;
}
Метод doinitBody () оставлен пустым.
Ртак, РІ самом простом случае достаточно расширить класс TagSupport, переопределив метод doStartTag (). Пусть, например, определен пользовательский тег без аргументов Рё без тела, всего лишь отправляющий клиенту сообщение:
Реализующий его класс может выглядеть так, как показано в листинге 27.5.
Листинг 27.5. Класс простейшего пользовательского тега
package sdotags;
import javax.servlet.jsp.*;
import j avax.servlet.jsp.tagext.*;
public class InfoTag extends TagSupport{
public int doStartTag() throws JspException{
pageContext.getOut().print(,,Библиотека тегов СДО."); return SKIP_BODY;
}
}
Рсходный текст листинга 27.5 надо откомпилировать обычным образом Рё установить РІ контейнер так же, как устанавливается сервлет. Проследите Р·Р° правильным соответствием пакетов Java Рё каталогов файловой системы: РІ каталоге WEB-INF/classes должен быть подкаталог sdotags СЃ файлом InfoTag.class.
Еще проще эти действия выполняются с помощью метода doTag( ) интерфейса SimpleTag, реализованного в классе SimpleTagSupport. У данного метода нет аргументов и возвращаемого значения, он объединяет действия, обычно выполняемые методами
doStartTag() Рё doEndTag().
Пользовательский тег с атрибутами
Для каждого атрибута открывающего тега надо определить свойство JavaBean, т. е. поле с именем, совпадающим с именем атрибута, и методы доступа getXxx() и setXxx(). Например, немного ранее (см. разд. "Пользовательские теги” данной главы) мы определили пользовательский тег
с одним атрибутом name. Класс RegTag, содержащийся в листинге 27.6, реализует этот тег.
Листинг 27.6. Пользовательский тег с атрибутом
package sdotags;
import javax.servlet.jsp.*;import javax.servlet.jsp.tagext.*;
public class RegTag extends TagSupport{
private String name;
public String getName(){ return name;
}
public void setName(String name){ this.name = name;
}
public int doStartTag() throws JspException{ if (name == null)
name = pageContext.getRequest().getParameter("name"); registrate(name); return SKIP_BODY;
}
}
Пользовательский тег с телом
Если у пользовательского тега есть тело, то при описании тега в TLD-файле в элементе
У тела элемента
Если содержимое тела тега не нужно обрабатывать, а надо только отправить клиенту, то при создании его обработчика достаточно реализовать интерфейс Tag или расширить класс TagSupport. Если метод dostartTag() обработчика вернет значение eval_body_include, то все тело тега будет автоматически отправлено в выходной поток.
Пусть, например, в файле sdotaglib.tld определен пользовательский тег head:
Ртот тег реализован классом HeadTag, описанным РІ листинге 27.7.
Листинг 27.7. Пользовательский тег с простым телом
package sdotags;
import javax.servlet.jsp.*; import j avax.servlet.jsp.tagext.*;
public class HeadTag extends TagSupport{
private String size = "4";
public String getSize(){ return size;
}
public void setSize(String size){ this.size = size;
}
public int doStartTag(){ try{
JspWriter out = pageContext.getOut(); out.print(""); }catch(Exception e){
System.err.println(e);
}
return EVAL_BODY_INCLUDE;
}
public int doEndTag(){ try{
JspWriter out = pageContext.getOut(); out.print("");
}catch(Exception e){
System.err.println(e);
}
return EVAL_PAGE;
}
} После этого на странице JSP можно писать пользовательский тег
Сегодня
Текст, написанный в его теле, будет выведен у клиента шрифтом указанного размера.
Обработка тела пользовательского тега
Если тело пользовательского тега требует обработки, то его класс-обработчик должен реализовать интерфейс BodyTag или расширить класс BodyTagSupport. Метод dostartTag ( ) должен вернуть значение eval_body_buffered. После завершения метода dostartTag(), если тело тега не пусто, контейнер вызовет метод doInitBody(), который может выполнить предварительные действия перед обработкой содержимого тела пользовательского тега. Далее контейнер обратится к методу doAfterBody(), в котором и надо проделать обработку тела тега, поскольку к этому моменту тело тега будет прочитано и занесено в объект класса BodyContent.
Класс BodyContent расширяет класс JspWriter, значит, формально является выходным потоком. Однако его удобнее рассматривать как хранилище информации, полученной из тела тега.
Объект класса BodyContent создается после каждой итерации метода doAfterBody( ), и все эти объекты хранятся в стеке.
Ссылку на объект класса BodyContent можно получить двумя способами: методом
public BodyContent getBodyContent();
класса BodyTagSupport или, используя объект pageContext, следующим образом:
BodyContent bc = pageContext.pushBody();
Содержимое тела тега можно прочитать из объекта класса BodyContent тоже двумя способами: или получить ссылку на символьный входной поток методом
public Reader getReader();
или представить содержимое объекта в виде строки методом
public String getString();
После обработки прочитанного содержимого его надо отправить в выходной поток out методом
public void writeOut(Writer out);
Выходной поток out, аргумент этого метода, выводит информацию в стек объектов класса BodyContent. Поэтому его можно получить двумя способами: методом
public JspWriter getPreviousOut();
класса BodyTagSupport или методом
public JspWriter getEnclosingWriter();
класса BodyContent.
Приведем пример. Пусть тег query, описанный в TLD-файле sdotaglib.tld следующим образом:
содержит в своем теле SQL-запросы, например:
SELECT * FROM students В листинге 27.8 приведен фрагмент обработчика этого тега.
Листинг 27.8. Пользовательский тег обработки SQL-запросов
package sdotags;
import java.sql.*;
import javax.servlet.jsp.*;
import j avax.servlet.jsp.tagext.*;
public class QueryTag extends BodyTagSupport{
private Connection conn; private ResultSet rs;
public int doStartTag(){
// . . .
return EVAL_BODY_BU FFERED;
}
public void doInitBody(){
conn = DriverManager.getConnection(. . .); // Проверка соединения
}
public int doAfterBody(){
BodyContent bc = getBodyContent(); if (bc == null) return SKIP BODY;
String query = bc.getString();
try{
Statement st = conn.createStatement(); rs = st.executeQuery(query);
// Обработка результата запроса
JspWriter out = bc.getEnclosingWriter();
out.print("Вывод результатов"); }catch(Exception e){
System.err.println(e);
return SKIP_BODY;
}
public int doEndTag(){ conn = null; return EVAL_PAGE;
}
}
Обработка взаимодействующих тегов
Часто пользовательские теги, расположенные на одной странице JSP, должны взаимодействовать друг с другом. Например, тело тега может содержать другие, вложенные, теги JSP. Они могут быть самостоятельными по отношению к внешнему тегу или зависеть от него. Так, например, в языке HTML тег
В языке JSP тоже могут появиться теги, зависящие друг от друга. Например, мы можем определить тег
устанавливающий соединение с базой данных, указанной в атрибуте source. Внутри этого тега допустимо обращение к базе данных, например:
SELECT * FROM students
INSERT INTO students (name) VALUES ('Рванов')
Конечно, вложенные теги можно реализовать вложенными классами-обработчиками или расширениями внешних классов. Но в классах-обработчиках пользовательских тегов есть свои средства. Внешний и вложенный теги реализуются отдельными классами, расширяющими классы TagSupport или BodyTagSupport. Описания тегов в TLD-файле тоже не вложены, они записываются независимо друг от друга, например:
Для связи обработчиков тегов используются их методы. Сначала обработчик вложенного тега задает себе внешний, "родительский" тег parent методом
public void setParent(Tag parent);
Затем обработчик вложенного тега может обратиться к обработчику внешнего тега методом
public Tag getParent();
Более общий метод
public static final Tag findAncestorWithClass(Tag from, Class class);
позволяет обратиться к обработчику тега, не обязательно непосредственно окружающего данный тег. Первый аргумент этого метода чаще всего просто this, а второй аргумент должен реализовать интерфейс Tag или его расширения.
Ртак, РІСЃРµ вложенные теги РјРѕРіСѓС‚ обратиться Рє полям Рё методам внешних тегов Рё взаимодействовать СЃ РёС… помощью.
Допустим, класс ConnectionTag, реализующий пользовательский тег connection, устанавливает соединение с источником данных, как показано в листинге 27.9.
Листинг 27.9. Реализация тега соединения с базой данных
public class ConnectionTag extends TagSupport{
private Connection conn;
public Connection getConnection(){ return conn;
}
public int doStartTag(){
Connection conn = DriverManager.getConnection(url, user, password);
if (conn == null) return SKIP_BODY; return EVAL_BODY_INCLUDE;
}
public int doEndTag(){ conn = null; return EVAL_BODY;
}
}
Класс QueryTag, реализующий тег query, может воспользоваться объектом conn, как показано в листинге 27.10.
Листинг 27.10. Реализация связанного тега
public class QueryTag extends BodyTagSupport{
private ConnectionTag parent;
public int doStartTag(){
parent = (ConnectionTag)findAncestorWithClass(this, ConnectionTag.class);
if (parent == null) return SKIP BODY; return EVAL_BODY_INCLUDE;
}
public int doAfterBody(){
Connection conn = parent.getConnection();
// Прочие действия
return SKIP_BODY;
}
}
Другой СЃРїРѕСЃРѕР± сделать объект obj доступным для нескольких тегов — указать его РІ РІРёРґРµ атрибута какого-РЅРёР±СѓРґСЊ контекста. Рто выполняется методом
public void setAttribute(String name, Object obj);
класса PageContext. Контекст этого атрибута — страница, на которой он определен. Если область действия атрибута надо расширить, то используется метод
public void setAttribute(String name, Object obj, int scope);
того же класса. Третий аргумент данного метода задает область действия атрибута — это одна из констант: page_scope, application_scope, request_scope, session_scope.
Значение атрибута всегда можно получить методами
public Object getAttribute(String name, int scope); public Object getAttribute(String name);
класса PageContext.
Для удобства работы с атрибутом обработчик тега может создать переменную, известную в области действия атрибута и доступную для других тегов в этой области (scripting variable). Она будет содержать ссылку на созданный атрибут. Переменную можно определить не только по атрибуту контекста, но и по атрибуту открывающего тега. Для определения переменной есть два способа.
Первый способ — указать в TLD-файле элемент
в–Ў
в–Ў
Остальные вложенные элементы необязательны:
в–Ў
в–Ў
true;
в–Ў
• nested — между открывающим и закрывающим тегами, т. е. в методах
doStartTag (), dolnitBody (), doEndBody (); принимается по умолчанию;
• at_begin — от открывающего тега до конца страницы;
• at_end — после закрывающего тега до конца страницы.
Например:
Второй способ — определить объект, содержащий ту же самую информацию, что и элемент
Вот как выглядит это расширение для примера, приведенного ранее:
public class MyTei extends TagExtraInfo{
public VariableInfo[] getVariableInfo(TagData data){ return new VariableInfo[]{
new VariableInfo(data.getAttributeString("id"),
"java.lang.String", true, VariableInfo.AT END)
};
}
}
Класс MyTei описывается в TLD-файле в элементе
У этого способа больше возможностей, чем у элемента
public boolean isValid(TagData info);
Его можно применять для проверки атрибутов тега на этапе компиляции страницы JSP.
Обработка исключений в пользовательских тегах
Ранее уже говорилось о том, что обработку исключения, возникшего на странице JSP, можно перенести на другую страницу, указанную атрибутом errorPage тега <%@ page %>. В пользовательских тегах можно облегчить обработку исключения, реализовав интерфейс TryCatchFinally.
Рнтерфейс TryCatchFinally описывает всего РґРІР° метода:
public void doCatch(Throwable thr); public void doFinally();
Метод doCatch () вызывается автоматически контейнером при возникновении исключения в одном из методов doStartTag(), doInitBody(), doAfterTag(), doEndTag() обработчика, реализующего интерфейс TryCatchFinally. Методу doCatch () передается созданный объект-исключение. Метод doCatch () сам может выбросить исключение.
Метод doFinally ( ) выполняется во всех случаях после метода doEndTag( ). Он уже не может выбрасывать исключения.
Например, при реализации тега
public class ConnectionTag extends TagSupport implements TryCatchFinally{
private Connection conn;
// Прочие поля и методы класса
public void doCatch(Throwable t) throws Throwable{ conn.rollback();
throw t;
}
public void doFinally(){ conn.close();
}
}
Обработка тегов средствами JSP
Уже упоминавшаяся тенденция Рє изгнанию СЃРѕ страниц JSP РІСЃСЏРєРѕРіРѕ чужеродного РєРѕРґР°, даже РєРѕРґР° Java, привела Рє тому, что для обработки пользовательского тега РІС‹ можете вместо класса Java написать страницу JSP, описав РЅР° ней действия тега. РРјСЏ файла СЃ такой страницей-обработчиком JSP получает расширение tag, Р° если РѕРЅР° оформлена как документ XML, то расширение tagx. Файл, содержащий отдельный фрагмент страницы-обработчика, получает РёРјСЏ СЃ расширением tagf.
Например, тег
xmlns:j sp=" ava.sun.com/JSP/Page"
version="2.0" >
Библиотека тегов СДО.
Поскольку элемент
Библиотека тегов СДО.
На странице-обработчике пользовательских тегов можно записывать любые теги JSP, кроме директивы page. Вместо нее указывается специально введенная для этой цели в язык JSP директива tag. Например:
<%@ tag body-content="scriptless">
Второе отличие заключается в том, что в директиве <%@ taglib %> следует записывать не атрибут uri, а атрибут tagdir, в котором указывается каталог с tag-файлами, например:
<%@ taglib tagdir="/WEB-INF/tags" prefix="sdo" %>
Атрибуты обрабатываемого пользовательского тега описываются еще одной специально введенной директивой attribute, аналогичной элементу
В файле reg.tag, обрабатывающем этот тег, можно написать
<%@ attribute name="name" required="true" fragment="false" rtexprvalue="false"
%>
<%@ attribute name="age" type="j ava.lang.Integer"
%>
Если тип type атрибута не указан, то по умолчанию он считается строкой класса
j ava.lang.String.
Типом атрибута может быть фрагмент JSP, т. е. объект класса javax.servlet.jsp.tagext. JspFragment. В таком случае атрибуты type и rtexprvalue не указываются, а атрибут
fragment="true".
После этого описания значения атрибутов, введенные РІ обрабатываемый тег, РІ примере РѕРЅРё равны "Рванов" Рё "25", можно использовать РІ файле reg.tag как ${name} Рё $ {age}.
Третья, специально введенная директива variable, аналогичная элементу
<%@ variable name-given="x"
variable-class="j ava.lang.Integer"
scope="NESTED"
declare="true"
%>
Область действия переменной определяется атрибутом scope, таким же, как описанный в разд. "Обработка взаимодействующих тегов” данной главы одноименный элемент TLD-файла.
Значения атрибутов, являющихся фрагментами страниц JSP, и тело пользовательского тега не вычисляются Web-контейнером, а передаются tag-файлу.
Для того чтобы заставить Web-контейнер выполнить значение атрибута, являющегося фрагментом страницы JSP, в tag-файле нужно использовать стандартный тег
<%@ attribute name="price"
fragment="true"
%>
Для вычисления его значения Web-контейнером в tag-файле следует написать:
Если же надо заставить Web-контейнер выполнить не фрагмент, а все тело пользовательского тега, то в tag-файле записывается стандартный тег
Tag-файлы не требуют никакого TLD-описания, если файл, содержащий страницу-обработчик пользовательского тега, хранится в каталоге WEB-INF/tags/ или в его подкаталогах. Другое место хранения tag-файлов должно быть описано в TLD-файле элементом
Если Web-приложение упаковано в JAR-архив, то tag-файлы должны храниться в каталоге META_INF/tags/ архива или в его подкаталогах.
Стандартные библиотеки тегов JSTL
Несмотря РЅР° недолгую историю языка JSP, его возможность создания пользовательских тегов была использована РјРЅРѕРіРёРјРё фирмами Рё отдельными разработчиками. Уже создано множество библиотек пользовательских тегов. РС… РѕР±Р·РѕСЂ можно посмотреть, например, РЅР° сайте . Р’ рамках уже РЅРµ раз упоминавшегося проекта Jakarta создана мощная Рё широко применяемая библиотека пользовательских тегов Struts, которую можно скопировать СЃ сайта . Рљ сожалению, рамки нашей РєРЅРёРіРё РЅРµ позволяют дать ее описание.
Корпорация Sun Microsystems создала стандартные библиотеки пользовательских тегов, носящие общее название JSTL (JSP Standard Tag Library). РС… реализации составляют пакет javax.servlet.jsp.jstl Рё его подпакеты. Справку Рѕ том, РіРґРµ найти самую последнюю реализацию, можно получить РїРѕ адресу java/index-jsp-135995.html. Впрочем, библиотеки JSTL РІС…РѕРґСЏС‚ РІ стандартную поставку
Java EE SDK. Всю библиотеку JSTL составляют два JAR-архива: jstl-1.2.jar и standard. j ar. Номер версии JSTL, конечно, может быть другим.
В пакет JSTL входят пять библиотек пользовательских тегов: core, xml, fmt, sql и fn.
Библиотека core
Библиотека core описывается на странице JSP тегом
<%@ taglib uri="" prefix="c" %>
В нее входят теги, создающие подобие языка программирования. Они призваны заменить операторы Java, тем самым устраняя скриптлеты со страниц JSP.
Тег
Например:
Здравствуйте, уважаемый
Тег
или, что то же самое:
${param.name}
Тег
Тег
или, что то же самое:
После этого переменную bhv можно использовать для создания сеанса связи с пользователем, как это делалось в предыдущей главе, или записывать в гиперссылках HTML:
К создаваемому адресу URL можно добавить параметры вложенным тегом
Тег
Уважаемый ${name}! Укажите, пожалуйста, свой возраст.
Как видите, этот тег не реализует полностью условие "if-then-else". Такое разветвление можно организовать тегом
Тег
Например:
На вашем счету отрицательный остаток.
На вашем счету нулевой остаток.
На вашем счету положительный остаток.
Нет сведений о вашем остатке.
В примере листинга 27.11 показано, как можно организовать разветвление с помощью тега
Листинг 27.11. Ответ, сформированный с помощью JSTL
<%@ taglib uri="" prefix="c" %>
Здравствуйте, ${user.name}!
form method="POST" action="/sdo/jsp/user.jsp">
РРјСЏ:
Пароль:
У тега
Например:
${item.quantity}
td>
Вторая форма тега
${^-й столбец
td>
Тег
Тег
/>
Переменную, определенную атрибутом var, можно использовать в своей области действия, определенной атрибутом scope (по умолчанию, page). Атрибут charEncoding показывает кодировку символов включаемого ресурса. По умолчанию это кодировка ISO 8859-1, которая плохо подходит для кириллицы.
Тег
Необязательный атрибут context устанавливает контекст для нового запроса.
В тег
Библиотека xml
Библиотека xml, описываемая тегом
<%@ taglib uri="" prefix="x" %>
содержит теги
Работа с библиотекой xml основана на адресации элементов документа XML средствами языка XPath, что выходит за рамки нашей книги.
Библиотека fmt
Библиотека fmt содержит теги, помогающие в интернационализации страниц JSP. Она описывается так:
<%@ taglib uri="" prefix="fmt" %>
В нее входят теги
Например, тег
запишет в переменную formattedAmount типа String количество amount с двумя цифрами в дробной части, а тег
запишет в переменную ruDate типа String дату today в виде 08.12.2007.
Теги
выполняют обратное преобразование строки символов, заданной атрибутом value, в объекты типа Number и Date соответственно, записанные в переменные n и d по шаблону pattern.
Рти теги реализованы классами DecimalFormat Рё SimpleDateFormat РёР· пакета java.text Рё преобразуют данные РїРѕ правилам этих классов, которые можно посмотреть РІ документации Java SE.
Библиотека sql
Четвертая библиотека, sql, описываемая тегом
<%@ taglib uri="" prefix="sql" %>
содержит теги связи и работы с базами данных:
/>
insert into DEPT values(50, 'XXX', 'YYY')
Библиотека fn
Пятая библиотека, fn, содержит функции для обработки строк. Она описывается тегом
<%@ taglib uri="" prefix="fn" %>
и содержит теги
несомненно, узнаете в названиях этих тегов привычные методы обработки строк, которые мы изучили в главе 5.
Кроме тегов обработки строк, библиотека fn содержит функцию
<%@include file="response.jsp" %>
Frameworks
Приступая к разработке Web-приложения, каждая команда решает вопрос о его архитектуре. Чаще всего ответ находится в схеме MVC (Model-View-Controller) (см. главу 3). Один или несколько сервлетов, принимающих и обрабатывающих запросы клиента, составляют Контроллер. Подготовка ответа, связь с базой данных, отбор информации, все то, что называется бизнес-логикой или бизнес-процессами, выполняется классами Java, образующими Модель. Страницы HTML и JSP, заполненные информацией, полученной от Модели, составляют Вид.
Р’ С…РѕРґРµ обсуждения Рё реализации проекта каждая РёР· трех частей схемы MVC конкретизируется, описывается интерфейсами Рё абстрактными классами. РРЅРѕРіРґР° РЅР° этом этапе получается наполовину реализованная конструктивная схема, подходящая для выполнения целого класса типовых проектов. Для завершения проекта Web-приложения остается реализовать несколько интерфейсов, дописать РїСЂРё необходимости СЃРІРѕРё собственные классы Рё определить РїРѕРґ СЃРІРѕР№ проект параметры приложения, записав РёС… РІ конфигурационные файлы.
Наиболее удачные из таких шаблонов готового приложения становятся достоянием всего сообщества программистов, активно обсуждаются, улучшаются, модернизируются и получают широкое распространение. Такие общепризнанные шаблоны, или, по-другому, каркасы программного продукта получили название Frameworks.
В технологии Java уже есть десятки таких каркасов, в их числе JSF, Seam, Struts, Facelets, Tales, Shale, Spring, Velocity, Tapestry, Jena, Stripes, Trails, RIFE, WebWork и множество других. В состав Java EE SDK входит каркас JSF. Познакомимся с ним подробнее.
JavaServer Faces
Framework под названием JSF (JavaServer Faces) вырос из простой библиотеки тегов, расширяющей возможности тегов HTML. Он входит в стандартную поставку Java EE, хотя всеми возможностями JSF можно воспользоваться и не имея у себя на компьютере Java EE. Есть много других реализаций интерфейсов JSF.
Рталонную реализацию, которую предоставляет проект GlassFish, можно загрузить СЃ сайта . РР· РґСЂСѓРіРёС… реализаций следует выделить очень популярный РїСЂРѕРґСѓРєС‚ Apache MyFaces, .
Все необходимое для работы с JSF собрано в одном архивном файле. Достаточно распаковать его в какой-нибудь каталог, и JSF готов к работе. В этом каталоге вы найдете подкаталоги с документацией и подкаталог с подробными примерами. Основу реализации JSF составляют два JAR-файла jsf-api.jar и jsf-impl.jar из подкаталога lib, которые надо скопировать в ваше Web-приложение или в ваш сервер приложений или записать пути к ним в переменную classpath. Для работы JSF понадобится библиотека JSTL, проследите за тем, чтобы у вашего Web-приложения был доступ к ее JAR-архиву, например файлу jstl-1.2.j ar.
Каркас JSF построен по схеме MVC (Model-View-Controller), которую мы обсуждали в главе 3.
Роль Контроллера РІ JSF играет сервлет РїРѕРґ названием FacesServlet. Как Рё РІСЃРµ сервлеты, РѕРЅ должен быть описан РІ конфигурационном файле web.xml. Рто описание выглядит так:
После этого описания мы можем обращаться к JSF c запросами вида
,
Часто элемент
После такого описания запросы к JSF должны выглядеть так:
sp, sp
Рв первом, и во втором случае запрашиваются файлы index.jsp и login.jsp. Расширение имени файла faces в запросах первого вида сделано только для JSF, на сервере файлов с такими именами нет. Увидев в запросе имя index.faces, JSF будет искать файл index.jsp.
Для организации Вида в JSF разрабатываются библиотеки тегов. В состав JSF сейчас входят две библиотеки: core и html. Они обычно описываются на странице JSP директивами
<%@ taglib uri="" prefix="h" %>
<%@ taglib uri="" prefix="f" %>
Все теги JSF вкладываются в элемент
Чаще всего на странице JSP формируется пользовательский интерфейс, который будет отображен браузером клиента. В нем размещаются формы с полями ввода, списками выбора, кнопками и прочими компонентами, текст с гиперссылками, панели, вкладки, таблицы.
Создание классической страницы HTML уже не удовлетворяет ни разработчиков, ни клиентов. Набор тегов HTML невелик и фиксирован, их возможности весьма ограниченны. Уже давно придумываются разные способы оживления страниц HTML: таблицы стилей CSS, динамический HTML, апплеты. Библиотека тегов html в первую очередь призвана усилить возможности тегов HTML.
Для каждого тега HTML в JSF есть соответствующий тег, обладающий дополнительными возможностями. В листинге 27.12 показана форма с полями ввода имени и пароля и кнопкой типа Submit.
Листинг 27.12. Страница JSP с тегами библиотеки JSF
<%@ taglib uri="" prefix="h" %>
<%@ taglib uri="" prefix="f" %>
value="#{cashier.name}" required="true">
value="#{cashier.pswd}"
required="true">
В библиотеке html есть более двух десятков тегов, соответствующих графическим компонентам пользовательского интерфейса. Кроме того, разработчик может легко создать свои, пользовательские, компоненты (custom components), расширив классы JSF. Уже создано много библиотек тегов для JSF, свободно распространяемых или коммерческих.
Главная особенность библиотеки html заключается в том, что ее составляют не просто теги, а целые компоненты. Компоненты JSF реагируют на события мыши и клавиатуры, которые могут быть обработаны обычными средствами JavaScript или специальными средствами JSF. Для этого введены теги-обработчики событий. Один такой тег,
Форма, записанная в листинге 27.12, посылает на сервер имя и пароль, связанные с полями cashier.name и cashier.pswd атрибутом value. Что это за поля и какому объекту cashier они принадлежат?
Данные, полученные РѕС‚ HTML-формы, Р±СѓРґСѓС‚ храниться РІ объекте, класс которого должен написать разработчик Web-приложения. Ртот класс оформляется как JavaBean, чтобы JSF РјРѕРі заполнять Рё читать его поля методами доступа. РћРЅ будет частью Модели РІ схеме MVC. Класс для хранения имени Рё пароля, полученных РѕС‚ формы листинга 27.12, показан РІ листинге 27.13.
Листинг 27.13. Класс с данными HTML-формы j
package myjsf;
import javax.faces.bean.*;
@ManagedBean(name="cashier")
@RequestScoped public class Cashier{
private String name; private String pswd;
public String getName(){ return name; }
public void setName(String name){ this.name = name; }
public String getPswd(){ return pswd; }
public void setPswd(String pswd){ this.pswd = pswd; }
public String submit(){
if ("Cashier".equalsIgnoreCase(name) && "rT34?x D".equals(pswd))
return "success"; else
return "failure";
}
}
Как видите, в этом же классе записан метод обработки щелчка по кнопке Отправить.
Теперь надо каким-то образом указать JSF этот класс. Сведения Рѕ нем записываются РІ аннотациях или РІ конфигурационном XML-файле faces-config.xml, который должен храниться РІ каталоге WEB-INF вместе СЃ файлом web.xml. Ртот файл для нашего примера записан РІ листинге 27.14.
Листинг 27.14. Конфигурационный файл JSF
xmlns:xsi="" xsi:schemaLocation=" 1 2.xsd" version="1.2">
Класс-обработчик регистрации кассира
После удачной проверки переход на страницу welcome.jsp
После неудачной проверки возврат на страницу index.jsp
Рлемент
Для полноты осталось написать файл welcome.jsp. Он может выглядеть так, как показано в листинге 27.15.
Листинг 27.15. Страница приветствия с тегами библиотеки JSF
<%@ taglib uri="" prefix="h" %>
<%@ taglib uri="" prefix="f" %>
Здравствуйте, ${cashier.name}!
Обзор всех возможностей JSF выходит за рамки нашей книги. Вы можете ознакомиться с ними на сайте разработчиков JSF . Множество статей и учебников по JSF собрано на сайте . Там вы можете найти дальнейшие ссылки.
Вопросы для самопроверки
1. Для чего придуман язык JSP?
2. Можно ли смешивать код JSP и код HTML на одной странице?
3. Можно ли записывать код Java на страницах JSP?
4. Можно ли включать в страницу JSP другие файлы?
5. Можно ли передавать управление из страницы JSP другим ресурсам?
6. Можно ли расширить набор стандартных тегов JSP?
7. Можно ли написать несколько классов Java, по-разному обрабатывающих один и тот же пользовательский тег?
8. Можно ли обработать пользовательский тег не классом Java, а страницей JSP?
9. Как подключить библиотеку пользовательских тегов к странице JSP?
ГЛАВА 28
может появиться только внутри тега . При этом атрибуты тега
могут использоваться в теге
, а также могут быть переопределены внутри него. Таких примеров много в языке XML.