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

Пользовательские теги — это определяемые пользователем элементы языка JSP. Когда JSP-страница содержит пользовательский тег, она преобразуется в сервлет, а тег преобразуется в операции над объектом, называемым обработчиком тега, то есть когда сервлет выполняется, веб-контейнер вызывает эти операции.

Расширения тегов JSP позволяют создавать новые теги, которые можно вставлять непосредственно в JSP-страницу. Спецификация JSP 2.0 представила простые обработчики тегов для написания таких пользовательских тегов.

Вы можете расширить класс SimpleTagSupport и переопределить метод doTag(), чтобы разработать простой пользовательский тег.


Создание тега "Hello"

Далее мы хотим создать пользовательский тег с именем <ex:Hello>, формат тега следующий:

<ex:Hello />

Чтобы создать пользовательский тег JSP, необходимо сначала создать Java-класс, который обрабатывает этот тег. Итак, давайте создадим класс HelloTag следующим образом:

package com.example;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {

  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    out.println("Hello Custom Tag!");
  }
}

Следующий код переопределяет метод doTag(), который использует метод getJspContext() для получения текущего объекта JspContext и передаёт "Hello Custom Tag!" объекту JspWriter.

Скомпилируйте приведённый выше класс и скопируйте его в каталог, указанный в переменной среды CLASSPATH. Наконец, создайте следующую библиотеку тегов: <каталог установки Tomcat>webapps\ROOT\WEB-INF\custom.tld.

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>Example TLD</short-name>
  <tag>
    <name>Hello</name>
    <tag-class>com.example.HelloTag</tag-class>
    <body-content>empty</body-content>
  </tag>
</taglib>

Далее мы можем использовать тег Hello в JSP-файле:

<%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>
<html>
  <head>
    <title>A sample custom tag</title>
  </head>
  <body>
    <ex:Hello/>
  </body>
</html>

Приведённая выше программа выводит следующий результат:

Hello Custom Tag!

Доступ к телу тега

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

<ex:Hello>
   This is message body
</ex:Hello>

Мы можем изменить файл класса обработчика тега, код выглядит следующим образом:

package com.example;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {

   StringWriter sw = new StringWriter();
   public void doTag()
      throws JspException, IOException
    {
       getJspBody().invoke(sw);
       getJspContext().getOut().println(sw.toString());
    }

}

Далее нам нужно изменить файл TLD, как показано ниже:

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>Example TLD with Body</short-name>
  <tag>
    <name>Hello</name>
    <tag-class>com.example.HelloTag</tag-class>
    <body-content>scriptless</body-content>
  </tag>
</taglib>

Теперь мы можем использовать изменённый тег в JSP, как показано ниже:

<%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>
<html>
  <head>
    <title>A sample custom tag</title>
  </head>
  <body>
    <ex:Hello>
        This is message body
    </ex:Hello>
  </body>
</html>

Приведённая выше программа выводит следующий результат:

This is message body

Атрибуты пользовательских тегов

Вы можете задавать различные атрибуты для пользовательских тегов. Чтобы принимать атрибуты, класс пользовательского тега должен реализовывать методы-сеттеры. Методы-сеттеры в JavaBean выглядят следующим образом:

package com.example;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {

   private String message;

   public void setMessage(String msg) {
      this.message = msg;
   }

   StringWriter sw = new StringWriter();

   public void doTag()
      throws JspException, IOException
    {
       if (message != null) {
          /* 从属性中使用消息 */
          JspWriter out = getJspContext().getOut();
          out.println( message );
       }
       else {
          /* 从内容体中使用消息 */
          getJspBody().invoke(sw);
          getJspContext().getOut().println(sw.toString());
       }
   }

}

Имя атрибута — "message", поэтому метод-сеттер — setMessage(). Теперь давайте добавим этот атрибут в файл TLD с помощью элемента <attribute>:

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>Example TLD with Body</short-name>
  <tag>
    <name>Hello</name>
    <tag-class>com.example.HelloTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
       <name>message</name>
    </attribute>
  </tag>
</taglib>

Теперь мы можем использовать атрибут message в файле JSP следующим образом:

<%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>
<html>
  <head>
    <title>A sample custom tag</title>
  </head>
  <body>
    <ex:Hello message="This is custom tag" />
  </body>
</html>

Приведённый выше пример выводит следующий результат:

This is custom tag

Вы также можете включить следующие атрибуты:

AttributeОписание
nameОпределяет имя атрибута. Имя атрибута каждого тега должно быть уникальным.
requiredУказывает, является ли атрибут обязательным или необязательным. Если задано значение false, атрибут необязателен.
rtexprvalueОбъявляет, допустим ли атрибут тега при вычислении выражений времени выполнения.
typeОпределяет тип Java-класса атрибута. По умолчанию указывается какString
descriptionОписательная информация
fragmentЕсли этот атрибут объявлен, значение атрибута будет рассматриваться какJspFragment。

Ниже приведён пример указания связанных атрибутов:

.....
    <attribute>
      <name>attribute_name</name>
      <required>false</required>
      <type>java.util.Date</type>
      <fragment>false</fragment>
    </attribute>
.....

Если вы используете два атрибута, измените TLD-файл, как показано ниже:

.....
    <attribute>
      <name>attribute_name1</name>
      <required>false</required>
      <type>java.util.Boolean</type>
      <fragment>false</fragment>
    </attribute>
    <attribute>
      <name>attribute_name2</name>
      <required>true</required>
      <type>java.util.Date</type>
    </attribute>
.....
Другие расширения