Пользовательские теги

С помощью пользовательских тегов можно отделить работу верстальщика от работы программиста, совершенно аналогично с JSTL.

Интерфейс Tag
Все теги должны прямо или косвенно реализовывать интерфейс Tag. У этого интерфейса ест методы. Через него веб-контейнер вызывает реализованные методы.

int doStartTag - Вызывается, когда веб-контейнер встречает начало тега int doEndTag - Вызывается, когда веб-контейнер встречает закрытие тега void release - при освобождении ресурса void setPageContext(PageContext) - вызывается раньше всех и в нем веб-контейнер передает контекст страницы. Как правило PageContext очень простое и просто сохраняет PageContext в приватную переменную, чтобы потом использовать setParent( Tag ) - передает внутри какого тега находится ваш тег.

Дополнительно есть несколько констант, управляющих процессом генерации страницы

doStartTag может возвращать либо SKIP_BODY, либо EVAL_BODY_INCLUDE

Если SKIP_BODY, то веб-контейнер будет обрабатывать вложенные теги EVAL_PAGE - обрабатывать ошибки

Интерфейс Tag расширяется IterationTag, который добавляет только

int doAfterBody - позволяет многократно обрабатывать содержимое тега (например, за счет этого делается forEach в JSTL)

InterationTag вызывается до тех пор, пока doAfterBody будет возвращать InterationTag.EVAL_BODY_AGAIN

Интерфейс InterationTag расширяется BodyTag для работы с тем, что содержится внутри тега. У него есть public void setBodyContent (BodyContent b), который позволяет передавать информацию об разобранных тегах вашему тегу (можно узнать какие теги внутри, какие аттрибуты и т.п.).

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

Например TagSupport или BodyTagSupport.

Многие интерфейсы могут выкидывать JspException.

Последовательность обращения контейнера к методам пользовательского тега
Пример обращения контейнера к методам пользовательского тега ATag ATag t = new ATag; t.setPagecontext(...); t.setParent(...); t.setAttribute1(value1);       // Правила геттеров и сеттеров используется также как в javabean t.setAttribute2(value2);       //Правила геттеров и сеттеров используется также как в javabean t.doStartTag; // Вызывается после начала обработки тегов // Сейчас обрабатываются вложенные теги t.doEndTag;   // Вызывается после того, как все вложенные теги отработают. t.release;

Описание тегов в TLD-файле
Но, прежде чем удастся использовать теги, надо описать пользовательскую библиотеку тегов в виде файла TLD (формат xml).

Пример  <!DOCTYPE taglib PUBLIC ... 1.2класс, реализующий интерфейс тега empty                        // определяет может ли в теге чтото содержаться или нет // описание user false  - название тега  - иконка  - описание  (empty, jsp, tagdependent) jsp - Обработка конейтенром, tagdependent - контейнер не обрабатывает, обработать - ваша задача.

У элемента могут быть свои аттрибуты:

- название - обязателен или нет - может ли в качестве аттрибута указываться выражение - тип данных аттрибута, это если испольлзуется rtexprvalue чтобы знать какого типа вернется - для документирования

Подключение taglib
Для использования тега на странице, его нужно подключить с помощью <%@ taglib prefix="tf" ...

Директива taglib можуте выглядеть: <%@ taglib uri="/WEB-INF/tags/taglib.tld" prefix="ut" %> и этот же путь uri надо указать в конфигурации веб-контейнера. При запуске веб-контейнера он просканирует и сделает маппинг данного uri-библиотеки с ее физическим местоположением.

Однако, тоже самое можно сделать в дескрипторе развертывания, используя тег taglib у которого будет  

Использование тега: ">

Пример реализации
... public int doStartTag throws JspException { try { JspWriter out = pageContext.getOut;   // получаем вывод и просто пишем out.printlninput.subsitrng(start,end); }   }