Org.apache.catalina.core.ApplicationContext log

INFO: Request for /FirstProject/SessionServlet; Count=1

Request уничтожен

При этом класс «обработчик событий» должен быть зарегистрирован в файле web.xml следующим образом:

<listener>

<listener-name>MyRequestListener</listener-name>

<listener-class>chapt21.MyRequestListener</listener-class>

</listener>

Фильтры

Реализация интерфейса Filter позволяет создать объект, который может трансформировать заголовок и содержимое запроса клиента или ответа сервера. Фильтры не создают запрос или ответ, а только модифицируют его. Фильтр выполняет предварительную обработку запроса, прежде чем тот попадает в сервлет, с последующей (если необходимо) обработкой ответа, исходящего из сервлета. Фильтр может взаимодействовать с разными типами ресурсов, в частности
и с сервлетами, и с JSP-страницами.

Основные действия, которые может выполнить фильтр:

· перехват инициализации сервлета и определение содержания запроса, прежде чем сервлет будет инициализирован;

· блокировка дальнейшего прохождения пары request-response;

· изменение заголовка и данных запроса и ответа;

· взаимодействие с внешними ресурсами;

· построение цепочек фильтров;

· фильтрация более одного сервлета.

При программировании фильтров следует обратить внимание на интерфейсы Filter, FilterChain и FilterConfig из пакета javax.servlet. Сам фильтр определяется реализацией интерфейса Filter. Основным методом этого интерфейса является метод

void doFilter(ServletRequest req, ServletResponse res, FilterChain chain),

которому передаются объекты запроса, ответа и цепочки фильтров. Он вызывается каждый раз, когда запрос/ответ проходит через список фильтров FilterChain. В данный метод помещается реализация задач, обозначенных выше.

Кроме того, необходимо реализовать метод void init(FilterConfig config), который принимает параметры инициализации и настраивает конфигурационный объект фильтра FilterConfig. Метод destroy() вызывается при завершении работы фильтра, в тело которого помещаются команды освобождения используемых ресурсов.

Жизненный цикл фильтра начинается с однократного вызова метода init(), затем контейнер вызывает метод doFilter() столько раз, сколько запросов будет сделано непосредственно к данному фильтру. При отключении фильтра вызывается метод destroy().

С помощью метода doFilter() каждый фильтр получает текущий запрос и ответ, а также список фильтров FilterChain, предназначенных для обработки. Если в FilterChain не осталось необработанных фильтров, то продолжается передача запроса/ответа. Затем фильтр вызывает chain.doFilter() для передачи управления следующему фильтру.

В следующем примере рассматривается обращение к объекту request JSP-страницы demofilter.jsp и изменение значения атрибута запроса testName.

<!--пример # 7 : обращение к атрибуту : demofilter.jsp -->

<%@ page language="java" contentType="text/html;

charset=ISO-8859-5" pageEncoding="ISO-8859-5"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<html><head><title>Demo Filter</title></head>

<body>

<c:out value="Info from filter: ${info}"/><br>

<P>Дублирование действий фильтра смотреть в консоли</P>

</body></html>

Если фильтр не подключать, то переменная info значения не получит.

Реализация интерфейса Filter для поставленной задачи выглялит следующим образом:

/* пример # 8 : простая фильтрация значения атрибута : MyFilter.java */

package chapt21;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

 

public class MyFilter implements Filter {

private FilterConfig filterConfig;

 

public void init(final FilterConfig filterConfig) {

this.filterConfig = filterConfig;

}

public void doFilter(final ServletRequest request,

final ServletResponse response, FilterChain chain)

throws java.io.IOException,

javax.servlet.ServletException {

System.out.println("Вход в фильтр");

String value = "Simple Filter";

 

request.setAttribute("info", value);

 

chain.doFilter(request, response);

System.out.println("info = " + value);

System.out.println("Окончание фильтрa");

}

public void destroy() {

System.out.println("Уничтожение фильтрa");

}

}

Чтобы к фильтру происходило обращение, необходимо включить упоминание о фильтре и обрабатываемом ресурсе в элемент <web-app> дескрипторного файла web.xml в виде:

<filter>

<filter-name>simplefilter</filter-name>

<filter-class>chapt21.MyFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>simplefilter</filter-name>

<url-pattern>/demofilter.jsp</url-pattern>

</filter-mapping>

Фильтр может модифицировать ответ сервера клиенту. Одним из распространенных приемов использования фильтра является модификация коди­ровки ответа. Когда сервлет посылает ответ клиенту через поток PrintWriter, используется установленная в сервлете кодировка. В следующем примере рассматривается фильтр, изменяющий кодировку ответа на кириллицу UTF-8.

// пример # 9 : фильтр, устанавливающий кодировку запроса : SetCharFilter.java

package chapt21;

import java.io.IOException;

import javax.servlet.*;

 

public class SetCharFilter implements Filter {

private FilterConfig filterConfig = null;

 

public void init(FilterConfig config)

throws ServletException {

this.filterConfig = config;

 

}

public void doFilter(ServletRequest request,

ServletResponse response, FilterChain next)

throws IOException, ServletException {

// чтение кодировки из запроса

String encoding = request.getCharacterEncoding();

System.out.println(encoding);

// установка UTF-8, если не установлена

if (!"UTF-8".equalsIgnorCase(encoding))

response.setCharacterEncoding("UTF-8");

next.doFilter(request, response);

}

public void destroy() {

}

}

И его конфигурации в web.xml:

<filter>

<filter-name>setCharFilter</filter-name>

<filter-class>chapt21.SetCharFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>setCharFilter</filter-name>

<url-pattern>/DemoCharServlet</url-pattern>

</filter-mapping>

Таким образом, ответ сервлета DemoCharServlet будет в необходимой кодировке.

/*пример # 10 : без установки кодировки ответ сервлета будет нечитаем :
DemoCharServlet.java*/

package chapt21;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class DemoCharServlet extends HttpServlet {

public void init() throws ServletException {

}

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.print("Кодировка установлена успешно!");

}

public void destroy() {

super.destroy();

}

}

В результате в браузер будет выведено:

Кодировка установлена успешно!

Задания к главе 21

Вариант А

Для всех заданий использовать авторизованный вход в приложение. Пара­метры авторизации, дату входа в приложение и время работы сохранять в сессии.

1. В тексте, хранящемся в файле, определить длину содержащейся в нем максимальной серии символов, отличных от букв. Все такие серии символов с найденной длиной сохранить в cookie.

2. В файле хранится текст. Для каждого из слов, которые вводятся в текстовые поля HTML-документа, вывести в файл cookie, сколько раз они встречаются в тексте.

3. В файле хранится несколько стихотворений, которые разделяются стро­кой, состоящей из одних звездочек. В каком из стихотворений больше всего восклицательных предложений? Результат сохранить в файле cookie.

4. Записать в файл cookie все вопросительные предложения текста, которые хранятся в текстовом файле.

5. Код программы хранится в файле. Подсчитать количество операторов этой программы и записать результаты поиска в файл cookie, перечислив при этом все найденные операторы.

6. Код программы хранится в файле. Сформировать файл cookie, записи которого дополнительно слева содержат уровень вложенности циклов. Ограничения на входные данные:

а) ключевые слова используются только для обозначения операторов;

б) операторы цикла записываются первыми в строке.

7. Подсчитать, сколько раз в исходном тексте программы, хранящейся на диске, встречается оператор, который вводится с тер­минала. Сохранить в файле cookie также номера строк, в которых этот опе­ратор записан. Ограничения: ключевые слова используются только для обозначения операторов.

8. Сохранить в cookie информацию, введенную пользователем, и восстановить ее при следующем обращении к странице.

9. Выбрать из текстового файла все числа-полиндромы и их количество. Результат сохранить в файле cookie.

10. В файле хранится текст. Найти три предложения, содержащие наибольшее количество знаков препинания, и сохранить их в файле cookie.

11. Подсчитать количество различных слов в файле и сохранить информацию в файл cookie.

12. В файле хранится код программы. Удалить из текста все комментарии
и записать измененный файл в файл cookie.

13. В файле хранится HTML-документ. Проверить его на правильность
и записать в файл cookie первую строку и позицию (если они есть), нарушающую правильность документа.

14. В файле хранится HTML-документ. Найти и вывести все незакрытые теги с указанием строки и позиции начала в файл cookie. При выполнении задания учесть возможность присутствия тегов, которые не требуется закрывать. Например: <BR>.

15. В файле хранится HTML-документ с незакрытыми тегами. Закрыть все незакрытые теги так, чтобы документ HTML стал правильным, и записать измененный файл в файл cookie. При выполнении задания учесть возможность присутствия тегов, которые не требуется закрывать. Например: <BR>.

16. В файле хранятся слова русского языка и их эквивалент на английском языке. Осуществить перевод введенного пользователем текста и записать его в файл cookie.

17. Выбрать из файла все адреса электронной почты и сохранить их в файле cookie.

18. Выбрать из файла имена зон (*.by, *.ru и т.д.), вводимые пользователем, и сохранить их в файле cookie.

19. Выбрать из файла все заголовки разделов и подразделов (оглавление)
и записать их в файл cookie.

20. При работе приложения сохранять в сессии имена всех файлов, к которым обращался пользователь.

Вариант B

Для заданий варианта В главы 4 каждому пользователю должен быть поставлен в соответствие объект сессии. В файл cookie должна быть занесена информация
о времени и дате последнего сеанса пользователя и информация о количестве посещений ресурса и роли пользователя.

Тестовые задания к главе 21

Вопрос 21.1.

Каким образом можно явно удалить объект сессии?

1) нельзя, так как сессия может быть удалена только после истечения времени жизни;

2) вызовом метода invalidate() объекта сессии;

3) вызовом метода remove() объекта сессии;

4) вызовом метода delete() объекта сессии;

5) вызовом метода finalize() объекта сессии.

Вопрос 21.2.

Какие методы могут быть использованы объектом сессии?

1) setAttribute(String name, Object value);

2) removeAttribute();

3) deleteAttribute();

4) setValue(String name, Object value);

5) getAttributeNames();

6) getInactiveTime().

Вопрос 21.3.

Каким образом можно получить объект-сеанс из ассоциированного с ним объекта-запроса HttpServletRequest req?

1) HttpSession session = req.getSession();

2) HttpSession session = req.createHttpSession();

3) Session session = req.createSession();

4) Session session = req.getSession();

5) HttpSession session = req.getHttpSession();

6) HttpSession session = req.createSession();

7) HttpSession session = req.getSession(true).

Вопрос 21.4.

Какие из следующих утверждений относительно объекта Cookie являются верными?

1) имя файла передается конструктору в качестве параметра при создании объекта Cookie и далее не может быть изменено;

2) имя файла может быть изменено с помощью вызова метода Cookie.setName(String name);

3) значение объекта может быть изменено с помощью вызова метода setValue(String value);

4) браузер ограничивает размер одного файла cookie до 4096 байт;

5) браузер не ограничивает общее число файлов cookie;

6) максимальное время существования файла cookie в днях устанавливается вызовом метода Cookie.setMaxAge(int day).

Вопрос 21.5.

Какие из следующих объявлений объекта класса Cookie верны?

1) Cookie c1 = new Cookie ();

2) Cookie c2 = new Cookie ("cookie2");

3) Cookie c3 = new Cookie ("$cookie3", "value3");

4) Cookie c4 = new Cookie ("cookie 4", "value4");

5) Cookie c5 = new Cookie ("cookie5", "value5");

6) Cookie c6 = new Cookie ("6cookie", "value6");

7) Cookie c7 = new Cookie ("c7,8", "value7").

Вопрос 21.6.

Каким образом файлы cookie присоединяются к объекту-ответу HttpServletResponse resp?

1) resp.setCookie(Cookie cookie);

2) resp.addCookie(Cookie cookie);

3) resp.createCookie(Cookie cookie);

4) resp.putCookie(Cookie cookie);

5) resp.setCookies(Cookie cookie).

 
Глава 22

ПОЛЬЗОВАТЕЛЬСКИЕ ТЕГИ

Начиная с версии JSP 1.1 у разработчиков появилась возможность определения собственных тегов. Это значительно упростило жизнь Web-дизайнерам, которым привычнее использовать теги, а не код на языке Java. Если один и тот же скриптлет используется на разных страницах, то он явный кандидат для переноса кода в пользовательский тег. Фактически последний представляет собой перенос Java-кода из страницы JSP в Java-класс, что можно считать продолжением идеи
о необходимости отделения логики от представления. JSP-страница должна содержать как можно меньше логики.

Для создания пользовательских тегов необходимо определить класс обработчика тега, определяющий его поведение, а также дескрипторный файл библиотеки тегов (файл .tld), в которой описываются один или несколько тегов, устанавливающих соответствия между именами XML-элементов и реализацией тегов.

При определении нового тега создается класс Java, который должен реализовывать интерфейс javax.servlet.jsp.tagext.Tag. Обычно создается класс, который наследует один из классов TagSupport или BodyTagSupport(для тегов без тела и с телом соответственно). Указанные классы реализуют интерфейс Tag и содержат стандартные методы, необходимые для базовых тегов. Класс для тега должен также импортировать классы из пакетов javax.servlet.jsp и, если необходима передача информации в поток вывода, то java.ioили другие классы.

Простой тег

Для создания тега без атрибутов или тела необходимо переопределить метод doStartTag(), определяющий код, который вызывается во время запроса, если обнаруживается начальный элемент тега.

В качестве примера можно привести следующий класс тега, с помощью которого клиенту отправляется информация о размере некоторой коллекции объектов.

/ пример # 1 : простейший тег без тела и атрибутов : GetInfoTag.java */

package test.mytag;

import javax.servlet.jsp.tagext.TagSupport;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.JspWriter;

import java.io.IOException;

// класс бизнес-логики (см. пример #7 этой главы)

import test.my.MySet;

 

public class GetInfoTag extends TagSupport {

public int doStartTag() throws JspException {

//получение информации, передаваемой на страницу

int size = new Integer(new MySet().getSize());

String str = "Size =<B>( " + size + " )</B>";

try {

JspWriter out = pageContext.getOut();

out.write(str);

} catch (IOException e) {

throw new JspException(e.getMessage());

}

return SKIP_BODY;

}

}

Если в теге отсутствует тело, метод doStartTag() должен возвратить константу SKIP_BODY, дающую указание системе игнорировать любое содержимое между начальными и конечными элементами создаваемого тега.

Чтобы сгенерировать вывод, следует использовать метод write() класса JspWriter, который выводит на страницу содержимое объекта str. Объект pageContext класса PageContext – это атрибут класса, унаследованный от класса TagSupport, обладающий доступом ко всей области имен, ассоциированной со страницей JSP. Метод getOut()этого класса возвращает ссылку на поток JspWriter, с помощью которой осуществляется вывод. С помощью методов класса PageContext можно получить:

getRequest()– объект запроса;

getResponse()– объект ответа;

getServletContext()– объект контекста сервлета;

getServletConfig()– объект конфигурации сервлета;

getSession()– объект сессии;

ErrorData getErrorData()– информацию об ошибках.

Кроме этого:

– с помощью метода forward(String relativeUrlPath)сделать перенаправление на другую страницу или action-класс;

– с помощью метода include()включить в поток выполнения текущие ресурсыServletRequest или ServletResponse, определяемые относительным адресом.

Следующей задачей после создания класса обработчика тега является идентификация этого класса для сервера и связывание его с именем XML-тега. Эта задача выполняется в формате XML с помощью дескрипторного файла библиотеки тегов.

Файл дескриптора .tld пользовательских тегов должен содержать корневой элемент <taglib>, содержащий список описаний тегов в элементах <tag>.
Каждый из элементов определяет имя тега, под которым к нему можно обращаться на странице JSP, и идентифицирует класс, который обрабатывает тег.
Для идентификации используется полное имя класса, например: test.mytag.GetInfoTag. Также должен присутствовать стандартный заголовок XML-файла с указанием версии и адреса ресурса для схемы XSD, который определяет допустимый формат тега <taglib>.

Перед списком тегов, сразу после открывающего тега <taglib>, указываются следующие параметры:

· tlib-version – версия пользовательской библиотеки тегов;

· short-name – краткое имя библиотеки тегов. В качестве него принято указывать рекомендуемое сокращение для использования в JSP-страницах;

· uri– уникальный идентификатор ресурса, определяющий данную библиотеку. Параметр необязательный, но если его не указать, то необходимо регистрировать библиотеку в каждом новом приложении через файл web.xml;

· info – указывается область применения данной библиотеки.

Основным в элементе <taglib> является элемент <tag>. В элементе tag между его начальным <tag>и конечным </tag>тегами должны находиться четыре составляющих элемента:

· name–тело этого элемента определяет имя базового тега, к которому будет присоединяться префикс директивы taglib;

· tag-class–полное имя класса-обработчика тега;

· info– краткое описание тега;

· body-content– имеет значение empty, если теги не имеют тела. Теги с телом, содержимое которого может интерпретироваться как обычный JSP-код, используют значение jsp, а редко используемые теги, тела которых полностью обрабатываются, используют значение
tagdependent.

Вся эта информация помещается в файл mytaglib.tld,который для JSP версии 2.0 имеет вид:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<taglib

xmlns="http://java.sun.com/JSP/TagLibraryDescriptor"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/ web-jsptaglibrary_2_0.xsd"

version="2.0"><!--дескриптор библиотеки тегов -->

<tlib-version>1.0</tlib-version>

<short-name>mytag</short-name>

<uri>/WEB-INF/mytaglib.tld</uri>

<tag>

<name>getinfo</name>

<!--класс обработки тега -->

<tag-class>test.mytag.GetInfoTag</tag-class>

<body-content>empty</body-content>

</tag>

</taglib>

Для JSP версии 2.1 тег taglib записывается в виде:

<taglib version="2.1"

xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

web-jsptaglibrary_2_1.xsd">

Зарегистрировать адрес URI библиотеки пользовательских тегов mytaglib.tld для приложения можно двумя способами:

1. Указать доступ к ней в файле web.xml, для чего следует указать после
<welcome-file-list\>:

<jsp-config>

<taglib>

<taglib-uri>/WEB-INF/mytaglib.tld</taglib-uri>

<taglib-location>/WEB-INF/mytaglib.tld

</taglib-location>

</taglib>

</jsp-config>

2. Прописать URI библиотеки в файле-описании (.tld) библиотеки и по­местить этот файл в папку /WEB-INFпроекта. В таком случае в файле web.xml ничего прописывать не требуется. Преимуществом данного способа является то, что так можно использовать библиотеку во многих приложениях под одним и тем же адресом URI. Естественно, в этом случае TLD-файл должен размещаться не в локальной папке проекта, а, например, в сети Интернет как независимый файл.

Непосредственное использование в странице JSP созданного и зарегистри­рованного простейшего тега выглядит следующим образом:

<!-- пример # 2 : вызов простого тега : demotag1.jsp -->

<HTML><HEAD>

<%@ taglib uri="/WEB-INF/mytaglib.tld"

prefix="mytag" %>

</HEAD>

<BODY>

<mytag:getinfo/>

</BODY>

</HTML>

В результате выполнения тега клиент в браузере получит следующую информацию:

Size = (3)

Тег с атрибутами

Тег может содержать параметры и передавать их значения для обработки
в соответствующий ему класс. Для этого при описании тега в файле *.tld используются атрибуты, которые должны объявляться внутри элемента tag с помощью элемента attribute. Внутри элемента attribute между тегами <attribute> и </attribute> могут находиться следующие элементы:

· name – имя атрибута (обязательный элемент);

· required– указывает на то, всегда ли должен присутствовать данный атрибут при использовании тега, который принимает значение true или false(обязательный элемент);

· rtexprvalue– показывает, может ли значение атрибута быть JSP-выражением вида ${expr}или <%=expr%> (значениеtrue) или оно должно задаваться строкой данных (значениеfalse). По умолчанию устанавливается false, поэтому этот элемент обычно опускается, если не требуется задавать значения атрибутов во время запроса (необязательный элемент).

Соответственно для каждого из атрибутов тега класс, его реализующий, должен содержать метод setИмяАтрибута().

В следующем примере рассматривается простейший тег с атрибутом firstname, который выводит пользователю сообщение:

// пример # 3 : тег с атрибутом : HelloTag.java

package test.mytag;import javax.servlet.jsp.tagext.TagSupport; import java.io.IOException; public class HelloTag extends TagSupport { private String firstname; public void setFirstname(String firstname) { this.firstname = firstname; } public int doStartTag() { try { pageContext.getOut().write("Hello, " + firstname); } catch (IOException e) { e.printStackTrace(); } return SKIP_BODY; }}

В файл mytaglib.tld должна быть помещена следующая информация
о теге:

<tag>

<name>hello</name>

<tag-class>test.mytag.HelloTag</tag-class>

<body-content>empty</body-content>

<attribute>

<name>firstname</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

Использовать созданный тег в файле demotag2.jsp можно следующим образом:

пример # 4 : вызов тега с передачей ему значения : demotag2.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag"%>

<%@ page

language="java"

contentType="text/html; charset=CP1251"

pageEncoding="CP1251"

%><HTML><HEAD>

<TITLE>demotag2.jsp</TITLE>

</HEAD>

<BODY>

<c:set var="login" value="Bender"/>

<mytag:hello firstname="${login}" />

</BODY>

</HTML>

При обращении по адресу:

http://localhost:8080/FirstProject/demotag2.jsp

в браузер будет выведено:

Hello, Бендер

Тег с телом

Как и в обычных тегах, между открывающим и закрывающим пользовательскими тегами может находиться тело тега, или body. Пользовательские теги могут использовать содержимое элемента body-content. На данный момент поддерживаются следующие значения для body-content:

· empty – пустое тело;

· jsp – тело состоит из всего того, что может находиться в JSP-файле. Используется для расширения функциональности JSP-страницы;

· tagdependent – тело интерпретируется классом, реализующим данный тег. Используется в очень частных случаях.

Когда разрабатывается пользовательский тег с телом, то лучше наследовать класс тега от класса BodyTagSupport, реализующего в свою очередь интерфейс BodyTag. Кроме методов класса TagSupport (суперкласс для BodyTagSupport), он имеет методы, среди которых следует выделить:

void doInitBody() – вызывается один раз перед первой обработкой тела, после вызова метода doStartTag() и перед вызовом doAfterBody();

int doAfterBody() – вызывается после каждой обработки тела. Если вернуть в нем константу EVAL_BODY_AGAIN, то doAfterBody() будет вызван еще раз. Если SKIP_BODY, то обработка тела будет завершена;

int doEndTag() – вызывается один раз, когда отработаны все остальные методы.

Для того чтобы тело было обработано, метод doStartTag() должен вернуть EVAL_BODY_INCLUDE или EVAL_BODY_BUFFERED; если будет возвращено SKIP_BODY, то метод doInitBody() не вызывается.

В следующем примере рассматривается класс обработки тега, который получает значения атрибута num (в данном случае методом установки значения для атрибута num будет метод setNum(String num)) и формирует таблицу с указанным количеством строк, куда заносятся значения из тела тега:

// пример # 5 : тег с телом : AttrTag.java

package test.mytag;

import java.io.IOException;

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

 

public class AttrTag extends BodyTagSupport {

private int num;

public void setNum(String num) {

this.num = new Integer(num);

}

public int doStartTag() throws JspTagException {

try {

pageContext.getOut().write(

"<TABLE BORDER=\"3\" WIDTH=\"100%\">");

pageContext.getOut().write("<TR><TD>");

} catch (IOException e) {

Throw

new JspTagException(e.getMessage());

}

return EVAL_BODY_INCLUDE;

}

public int doAfterBody()

throws JspTagException {

if (num-- > 1) {

try {

pageContext.getOut().write("</TD></TR><TR><TD>");

} catch (IOException e) {

Throw

new JspTagException(e.getMessage());

}

return EVAL_BODY_AGAIN;

} else {

return SKIP_BODY;

}

}

public int doEndTag() throws JspTagException {

try {

pageContext.getOut().write("</TD></TR>");

pageContext.getOut().write("</TABLE>");

} catch (IOException e) {

Throw

new JspTagException(e.getMessage());

}

return SKIP_BODY;

}

}

В файл.tldследует вставить информацию о теге в виде:

<tag>

<name>bodyattr</name>

<tag-class>test.mytag.AttrTag</tag-class>

<body-content>JSP</body-content>

<attribute>

<name>num</name>

<required>false</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

При использовании в файле JSP тег bodyattr может вызываться с параметрами и без них:

пример # 6 : тег с телом : demotag3.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-5" pageEncoding="ISO-8859-5"%>

<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %>

<HTML><HEAD>

<TITLE>Example</TITLE>

</HEAD><BODY>

<jsp:useBean id="rw" scope="request" class=

"test.my.MySet"/>

<mytag:bodyattr num="${rw.size}">

${rw.element}

</mytag:bodyattr>

<mytag:bodyattr> Просто текст </mytag:bodyattr>

</BODY></HTML>

В результате запуска этой JSP клиенту будет возвращено:

Рис. 22.1. Выполнение тега с телом

В примерах данной главы были использованы методы класса Rows, который приведен ниже:

/* пример # 7 : примитивный класс бизнес-логики : MySet.java */

package test.my;

public class MySet extends java.util.HashSet {

private java.util.Iterator it;

 

public MySet() {

//переписать этот класс на чтение информации из БД

this.add("Sun");

this.add("Microsoft");

this.add("IBM");

}

public String getSize() {

it = this.iterator();

return Integer.toString(this.size());

}

public String getElement() {

return it.next().toString();

}

}

Элементы action

Элемент jsp:attribute позволяет определить значение атрибута тега в теле XML-элемента, а не через значение атрибута стандартного или пользовательского тега:

<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %>

<HTML>

<mytag:hello>

<jsp:attribute name="firstname">

Bender

</jsp:attribute>

</mytag:hello>

</HTML>

в браузер будет выведено:

Hello, Bender

Если в теле тега имеются элементы jsp:attribute, то тело тега нужно указать явно при помощи стандартного действия jsp:body:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c"%>

<%@ taglib uri="/WEB-INF/mytaglib.tld" prefix="mytag" %>

<HTML>

<jsp:useBean id="rw" scope="request"

class="test.my.MySet"/>

<mytag:bodyattr>

<jsp:attribute name="num">

<c:out value="${requestScope.rw.size}"/>

</jsp:attribute>

<jsp:body>

<c:out value="${requestScope.rw.element}"/>

</jsp:body>

</mytag:bodyattr>

</HTML>

В результате в браузер будет выведено:

IBM
Sun
Microsoft

Элемент jsp:element с обязательным атрибутом name используется для динамического определения элемента XML и дополнительно может содержать действия jsp:attribute и jsp:body:

<jsp:element name="H2" >

<jsp:attribute name="Style">

color:red

</jsp:attribute>

<jsp:body>

Simple Text

</jsp:body>

</jsp:element>

в результате должно быть сгенерировано:

<H2 Style="color:red">Simple Text</H2>

Стандартные действия jsp:doBodyиjsp:invokeиспользуются только
в тег-файлах. Тег jsp:doBody вызывает тело тега, выводя результат в JspWriterили в атрибут области видимости. Действие jsp:invokeподобно действию jsp:doBodyииспользуетсядля вызова атрибута-фрагмента. Например, поведение тега bodyattr можно воспроизвести так:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core"

prefix="c"%>

<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>

<tags:actiondemo>

<jsp:attribute name="num">

<c:out value="${sessionScope.mysetInstance.size}"/>

</jsp:attribute>

<jsp:body>

<c:out value="${sessionScope.mysetInstance.element}"/>

</jsp:body>

</tags:actiondemo>

Файл actiondemo.tag помещен в каталог /WEB-INF/tags:

<%@ tag import="test.my.MySet" %>

<%@ attribute name="num" fragment="true" %>

<%@ variable name-given="mysetInstance" %>

<%session.setAttribute("mysetInstance", new MySet());%>

<TABLE border=1>

<TR><TD>Rows number: <jsp:invoke fragment="num"</TD></TR>

<TR><TD><jsp:doBody /></TD></TR>

<TR><TD><jsp:doBody /></TD></TR>

<TR><TD><jsp:doBody /></TD></TR>

</TABLE>

Здесь директива tag схожа с директивой page для страниц JSP. Директива attribute декларирует атрибут тега actiondemo, и если fragment="true", то этот атрибут можно использовать совместно с jsp:invoke. Директива variable – для передачи переменной обратно в вызывающую JSP-страницу.

В браузер будет выведено:

Rows number: 3
IBM
Sun
Microsoft

Задания к главе 22

Вариант А

Создать классы пользовательских тегов, формирующих нужное количество элементов (строк, ячеек и др.) для размещения результатов выполнения запроса.

1. Элемент массива называют локальным максимумом, если у него нет соседа большего, чем он сам. Аналогично определяется локальный минимум. Определить количество локальных максимумов и ло­кальных минимумов в заданном строкой массиве чисел. Массив задает клиент. Возвратить все максимумы и минимумы пользователю.

2. В неубывающей последовательности, заданной клиентом, найти количество различных элементов и количество элементов, меньших, чем заданное число, и вернуть ему результат.

3. Дана числовая последовательность a1, a­2,…, an . Вычислить суммы вида Si = ai+ai+1 +…+ aj для всех 1£i£j£N и среди этих сумм определить максимальную. Последовательность и число N задает клиент.

4. Точка А и некоторое конечное множество точек в пространстве заданы своими координатами и хранятся в базе данных. Найти N точек из множества, ближайших к точке А. Число N задает клиент.

5. В базе данных хранится список студентов и их оценок по предметам за сессию по 100-балльной системе. Выбрать без повторений все оценки
и соответствующие им записи, встречающиеся более одного раза.

6. Получить упорядоченный по возрастанию массив С, состоящий из
k элементов, путем слияния упорядоченных по возрастанию массивов А и В, содержащих n и m элементов соответственно, k = n + m. Элементы массивов хранятся в базе данных, а значения n и m задает клиент.

7. В матрице А найти сумму элементов, расположенных в строках с отри­цательным элементом на главной диагонали, и произведение элементов, расположенных в строках с положительным элементом в пер­вом столбце. Матрица размерности n хранится в базе данных. Клиент задает размерность m < n матрицы, для которой будет произведен расчет.

8. В программе, хранящейся в текстовом файле, удалить строки с № 1 до № 2, где № 1 и № 2 вводятся клиентом. Удаляемые строки возвратить клиенту. Предусмотреть случаи, когда, например, № 1 меньше номера первой строки, № 1 = № 2, № 2 больше номера последней строки, и другие исключительные ситуации.

9. После n-ой строки программы, которая хранится в файле, вставить
m строк. Числа n, m и вставляемые строки вводятся пользователем. Новый набор данных сохранить на диске и вернуть клиенту.

10. В БД хранятся координаты множества m точек трехмерного пространства. Найти такую точку, чтобы шар заданного радиуса с центром
в этой точке содержал максимальное число точек. Координаты найденных точек возвратить клиенту.

11. Из заданного множества точек на плоскости, координаты которых хранятся в базе данных, выбрать две различные точки, так чтобы окружности заданного пользователем радиуса с центрами в этих точках содержали внутри себя одинаковое количество заданных точек. Полученные множества возвратить клиенту.

12. В базе данных хранятся координаты конечного множества точек плоскости. Пользователем вводятся координаты центра и радиусы 5 концентрических окружностей. Между какими окружностями (1 и 2, 2 и 3, ..., 4 и 5) больше всего точек заданного множества? Полученное множество точек возвратить клиенту.

13. В базе данных хранятся координаты вершин выпуклых четырехугольников на плоскости. Сформировать ответ клиенту, со­держащий координаты всех вершин тра­пеций, которые можно сформировать из данных точек.

14. В базе данных хранятся координаты вершин треугольников на плоскости. Для прямоугольных треугольников возвратить клиенту координаты вершин прямого угла, площадь и координаты вершин (одной или двух), ближайших к оси ОХ.

15. В базе данных хранятся координаты множества точек плоскости А
и коэффициенты уравнений множества прямых в этой же плоскости. Передать клиенту набор из пар различных точек – таких, что проходящая через них прямая параллельна прямой из множества В.

Вариант B

Для заданий варианта В предыдущей главы применить пользовательские теги для визуализации работы приложения.

Тестовые задания к главе 22

Вопрос 22.1.

Какой элемент тега <attribute> определяет имя атрибута, которое должно быть передано обработчику тегов?

1) <attribute-name>;

2) <name>;

3) <attributename>;

4) <param-name>.

Вопрос 22.2.

Обработчик тега реализует интерфейс BodyTag. Сколько раз может быть
в нем вызван метод doAfterBody()?

1) класс BodyTag не поддерживает метод doAfterBody();

2) 0;

3) 1;

4) 0 или 1;

5) сколько угодно раз.

Вопрос 22.3.

Какой метод обработчика тега будет вызван, если метод doStartTag() вернет значение Tag.SKIP_BODY?

1) doAfterBody();

2) doBody();

3) skipBody();

4) doEndTag();.

5) нет правильного.

Вопрос 22.4.

Какой из следующих элементов необходим для корректности тега <taglib> в файле web.xml?

1) <uri-tag>;

2) <tag-uri>;

3) <uri-name>;

4) <uri-location>;

5) <taglib-uri>.

Вопрос 22.5.

Какие элементы описывают характеристики пользовательского тега в файле .tld?

1) value;

2) name;

3) rtexprvalue;

4) class.

Вопрос 22.6.

Какие утверждения верны относительно метода doInitBody()класса BodyTagSupport?

1) используется контейнером и не может быть переопределен;

2) он может быть переопределен;

3) может возвращать или константы SKIP_BODY, или EVAL_BODY_INCLUDE;

4) его возвращаемое значение имеет тип void.

Вопрос 22.7.

Что нужно сделать в файле .tld для этого тега, чтобы в теле тега использовать скриптлеты?

1) в body-content должно быть выставлено значение jsp;

2) в script-enabled должно быть выставлено true;

3) ничего, так как скриптлеты используются по умолчанию.

 
Приложение 1

HTML

Язык HTML (HyperText Markup Language) позволяет публиковать в Internet документы с помощью заголовков, текста, списков, таблиц, получать доступ
к документам с помощью гиперссылок, включать видеоклипы, звук и т.д. Страницы JSP, привнося свои теги, активно используют уже существующие HTML-теги.

Существует несколько версий HTML. В 1999 году вышла последняя редакция языка – HTML 4.01. С тех пор развиваются языки разметки, базирующиеся на XML. Среди них – XHTML 1.0/ XHTML 2.0, MathML (язык разметки математических формул) и некоторые другие.

Каждый HTML-документ, отвечающий спецификации HTML какой-либо версии, должен начинаться со строки объявления версии HTML, которая выглядит так:

Строгий (Strict) – не содержит элементов, помеченных как «устаревшие» или «не одобряемые» (deprecated):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

"http://www.w3.org/TR/html4/strict.dtd">

Переходный (Transitional) – содержит устаревшие теги в целях совместимости и упрощения перехода со старых версий HTML:

<!DOCTYPE HTML PUBLIC

"-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

С фреймами (Frameset) – аналогичен переходному, но содержит также теги для создания наборов фреймов:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"

"http://www.w3.org/TR/html4/frameset.dtd">

Документ, соответствующий XHTML 1.0, автоматически соответствует также и HTML 4.0. XHTML 2.0 обеспечивает полное отделение содержания документа от его представления. В нем нет ничего отвечающего за внешний вид документа – нет элементов font, i, b, center, нет атрибутов align, size и bgcolor. Предполагается, что вся информация об оформлении документа содержится
в отдельной таблице стилей. Кроме того, в XHTML 2.0 вводится много новых элементов – например элемент section, обозначающий структурную часть документа, и элемент h – заголовок общего вида.

Таким образом, если предполагается использование документа вместе с расширениями в XHTML 2.0, базирующемся на XML, следует учитывать, что в документе нельзя использовать устарелые или нежелательные элементы. При этом:

· верхний и нижний регистры различаются, все теги следует писать с маленькой буквы;

· теги center, font, s, u, атрибутыalign, bgcolor, background, clear, color, face, size,т.е. почти все теги и атрибуты, определяющие представление документа HTML (цвета, выравнивание, шрифты, графика и т.д.), являются нежелательными, взамен рекомендуется использовать таблицы стилей;

· если пишется атрибут, то обязательно должно быть указано его значение. Все значения атрибутов должны писаться в кавычках.

· обязательно прописывать и закрывающие теги! (например у тега li). Примеры тегов, у которых отсутствуют закрывающие теги: <br>, <img> и т.д. В случае если закрывающий тег отсутствует, то в конце тега пишется «/».

HTML-документ создается с помощью HTML-редактора и сохраняется в виде текстового файла с расширением html или htm. Для просмотра HTML-документов используются Web-браузеры, интерпретирующие документы.

HTML-документ состоит из вложенных друг в друга элементов (тегов). Теги <html> начинаются со стартового тега (“< >”) и заканчиваются завершающим тегом (“</>”). Сам документ – это один большой элемент вида:

<html>

<!--Содержание документа-->

</ html>

HTML не реагирует на регистр символов, описывающих тег (в XML используются строчные буквы).

Заголовочная часть документа <HEAD>

Тег заголовочной части документа используется сразу после тега <HTML>. Данный тег содержит общее описание документа. Например:

<HTML><HEAD>

<TITLE> Список сотрудников </TITLE>

</HEAD></HTML>

Заголовок документа <TITLE>

Большинство Web-браузеров отображают заголовок документа, ограничен­ный тегами <TITLE> и </TITLE> вверху экрана, отдельно от содержимого документа.

Тело документа <BODY>

Тело документа должно находиться между тегами <BODY> и </BODY>. Это та часть документа, которая отображается как текстовая и графическая информация документа. Технически стартовые и завершающие теги типа <HTML>, <HEAD> и <BODY> необязательны. Но настоятельно рекомендуется их использовать, поскольку использование данных тегов позволяет Web-браузеру разделить заголовочную и смысловую часть документа.

<!--пример # 1: простой HTML документ-->

<HTML>

<HEAD><TITLE>Домашняя страница </TITLE></HEAD>

<BODY>

<!-- Это комментарий-->

<H1>Пример заголовка, размер 1</H1>

<H6>Пример заголовка, размер 6</H6>

<ADDRESS>Романчик - e-mail:rom@bsu.by</ADDRESS> <P>

</BODY></HTML>

В этом примере использовались теги: <P> – тег нового абзаца. Тег <ADDRESS> позволяет сформировать информацию о связи с автором документа
и определяет вид сообщения. HTML позволяет вставлять в тело документа комментарии. Синтаксис комментария:

<!-- Это комментарий -->

В тексте HTML-документа структурно выделяются собственно текст, заголовки частей текста, заголовки более высокого уровня и т.д. Самый большой заголовок обозначается цифрой 1, и т.д. до шести. Синтаксис заголовка уровня 1 следующий:

<H1> Заголовок первого уровня </H1>

В языке описания гипертекстовых документов все теги – парные (start-тег
и stop-тег). В конечном теге присутствует слэш, который сообщает обозревателю о завершении тега. Существуют исключения из этого правила пар, например: тег <P>, определяющий абзац, не требует завершающего тега, хотя может его иметь. Если браузер не понимает тега, то он его просто пропускает.