Библиотеки тегов, добавляют дополнительные теги в джееспе страницу, что позволяет реализовывать дополнительную логику дизайна(манипуляции с данными и отображение их с помощью хтмл-тегов).
- Нужно создать описание библиотеки в ВЕБ-инфе, оно делается в *.tld файле. Это иксемель с определенной схемой. Каждый ее тег определят тег библиотеки, в этом теге есть ссылка на java-класс, который определяет поведение тега, и есть ссылка на класс, который описует, какие этот тег добавляет переменные в контекст(их можно использовать вместе с применением тега), дальше идут атрибуты которые характерны для тега.
<?xml version="1.0" encoding="ISO-8859-1" ?> <! DOC TYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>simple</short-name> <uri>http://jakarta.apache.org/tomcat/example-taglib</uri> <description> A simple tab library for the examples </description> <tag> <name>ShowSource</name> <tag-class>examples.ShowSource</tag-class> <description> Display JSP sources </description> <attribute> <name>jspFile</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> <!-- A simple Tag --> <!-- foo tag --> <tag> <name>foo</name> <tag-class>examples.FooTag</tag-class> <tei-class>examples.FooTagExtraInfo</tei-class> <body-content>JSP</body-content> <description> Perform a server side action; uses 3 mandatory attributes </description> <attribute> <name>att1</name> <required>true</required> </attribute> <attribute> <name>att2</name> <required>true</required> </attribute> <attribute> <name>att3</name> <required>true</required> </attribute> </tag> <!-- Another simple tag --> <!-- log tag --> <tag> <name>log</name> <tag-class>examples.LogTag</tag-class> <body-content>TAGDEPENDENT</body-content> <description> Perform a server side action; Log the message. </description> <attribute> <name>toBrowser</name> <required>false</required> </attribute> </tag> </taglib>В теле<body-content>могут быть следующие варианты:
- empty - doStartTag() должен возвращать SKIP_BODY, если не возвратит, то произойдет ексепшин.
- JSP - я так понимаю тут могут находится другие теги.
- tagdependent - на тег не ставятся ограничения и он себя может вести по ситуации по разному, возвращая разные значения.
- Теперь в дескрипторе в теге <jsp-config> нужно сделать через тег <taglib> ссылку на наш файл с определением библиотеки, и для нее определить урл по которому нужно ссылаться из jsp-страницы, чтобы получить доступ к тегам этой библиотеки.
<taglib> <taglib-uri>http://jakarta.apache.org/tomcat/debug-taglib</taglib-uri> <taglib-location>/WEB-INF/jsp/debug-taglib.tld</taglib-location> </taglib> - В нужной джееспе странице нужно ссослаться на нашу библиотеку и теперь мы можем использовать новые теги через префикс, который сами определили при подключении библиотеки.
<%@ taglib uri="http://jakarta.apache.org/tomcat/examples-taglib" prefix="eg"%>
Интересна конечно и сама структура классов в ява-файлах.
Все эти классы являются непрямыми наследниками интерфейса JSPTag.
(i)JSPTag
-------------->
(i)SimpleTag(отличается от Tag более упрощенным интрфейсом, вместо этапов doStartTag() doEndTag(), у него просто выполняется один метод doTag(), который вызывается только раз за вызов тега -- вся логика тега, итерации, считывание тела выполняются в одном этом методе.
Этапы:
1. Каждый раз когда на странице происходит вызов этого тега JSP-контейнер создает новую инстанцию, в отличии от просто тега, который контейнером кешируется для страницы(одна интсанции класса используется для страницы внезависимости от того сколько раз на странице используется тег.
2. Вызываются методы
setJspContext() and setParent()происходит установка контекста и родителя, если конечно тег не рут на странице.3. Вызываются все сеттере для атрибутов, которые были установлены тегу.
4. Если тег с телом, то вызвается метод
setJspBody(), при этом тело представлется инстанцией класса JspFragment.5. Выполняется метод doTag(), и вся логика тега, итерации(за счет установленной интстанции
JspFragment), считывание тела выполняются.По большому счету реализация этого интерфейса является альтернативой реализации BodyTag только имеет более простой интерфейс.
)
+ void setJspContext(JspContext pc)
+ void setJspBody(JspFragment jspBody)
+ void doTag()
+ JspTag getParent()
+ void setParent(JspTag parent)
------------->
(i)Tag(тэг, которому не нужно манипулировать содержимым тела)
+static final int EVAL_BODY_INCLUDE(это значение может возвращать doStartTag(), если содержимое тега должно попасть в out-поток)
+static final int EVAL_PAGE(это значение может возвращать doEndTag(), что означает что контейнер продолжит обоработку тегов, которые находятся за поточным в JSP-странице)
+static final int SKIP_BODY(это значение могут возвращать doStartTag и doAfterBody, если нужно не выводить содержимое тела)
+static final int SKIP_PAGE(это значение может возвращать doEndTag(), контейнер не будет обрабатывать в таком случае теги находящиеся после поточного)
--------
+int doEndTag() (вызывается на закрывающий тег, возвращает значение, которое определяет будет ли остаток джееспе страницы обрабатываться. Если SKIP_PAGE, то методы doEndTag() отцовских тегов вызваны не будут. Но только для поточной страницы - если эта старница заинклюжена, то отцовская продолжит свое выполнение при любом возвращенном значении.)
+int doStartTag()(вызывается на открывающийся тег. Если возвращает EVAL_BODY_INCLUDE, то содержимое тела передается в поток "out" JspWriter-ра. Если SKIP_BODY, то содержимое боди не выводится)
+Tag getParent()(возвращает отцовский тег)
+void release()(сброс поточного состояния. Эта штука вызывается наверно только при остановки контейнера, потому что когда приходят повторые запросы на страницу, то состояние тега сохраняется между запросами при этом даже если тег используется в нескольким местах страницы, то состояние сохраняется, что свидетельствует о одной инстанции класса на одну страницу в независимости от к-ва использования в ней тега. А этот тег сбрасывает состояние только когда идет запрос на другую страницу, где этот тег используется - но это потому, что происходит создание новой инстанции класса тега, потому что если вернуться на предыдую страницу, то все ее состояния будут в прежнем виде. ).
+void setPageContext(PageContext pc) (сюда передается контекс страницы)
+void setParent(Tag t) (установить отцовский тег)
------->
(i)IterationTag
+static final int EVAL_BODY_AGAIN (это значение возвращается из нового метода doAfterBody, что будет означать что этот метод обратно вызовется и тело тега будет повторно обработано, чтобы перкратить цикл нужно вернуть SKIP_BODY)
+int doAfterBody() (этот метод вызывается между doStartTag и doEndTag. И вызывается он после того, как было прочитано тело тега и помещенно в исходящий поток. Этот метод зацикливается до тех пор пока не вернет SKIP_BODY -(для повторной итерации - EVAL_BODY_AGAIN). При этом содержимое тела тега каждый раз дублируется в буфер исходящего потока, мы также можем получить
JspWriter out = pc.getOut(); и дописать еще и своего. Если с первого раза вернуть SKIP_BODY, то будет выведено то, что находится в боди один раз(это не doStartTag(), который не выведет ничего)). Чтобы не допустть вывод, нужно получить буфер потока и почистить его.----------------->
(i)BodyTag
+static int EVAL_BODY_BUFFERED - дополнительное значение, которое может возвращать doStartTag(), если вернули его то вызывается новый метод setBodyContent(BodyContent b), вызывается он джееспе страницей и создает новый отдельный буфер под содержимое тега, к которому можно будет получать доступ через инстанцию класса BodyContent. Если вернется EVAL_BODY_INCLUDE из метода doStartTag(), то тег будет себя вести как IterationTag.
+ void setBodyContent(BodyContent b) Установка обьекта, который хранит в себе буфер иходящего поток
+ void doInitBody() Вызывается этот метод до того, как значение тела тега считывается JSP-сервлетом и поместится в буффер инстанции BodyContent.
(i)TryCatchFinally этот интерфейс могут реализовывать классы, которые реализовывают IterationTag and BodyTag, когда контейнер сервлетов выполняет методы этого класса doStartTag() и т.д., и если на где происходит исключение, то в своей обработке контейре вызывает методы этого класса doCatch(), doFinally().
+ void doCatch(Throwable t)
+ void doFinally()
В библиотеке джееспе есть классы, которые уже реализовали эти интерфейсы:
SimpleTagSupport implements SimpleTagTagAdapter inplements Tag TagSupport implements IterationTag BodyTagSupport implemets BodyTagКогда добавляются переменные в контекст страницы тегом, и их можно вызывать в криптелетах и выражениях, их можно определить из какого места тега они могут быть достпными:

Комментариев нет:
Отправить комментарий