JSP Custom Tags

Custom tags are user-defined JSP language elements. When a JSP page contains a custom tag, it is transformed into a servlet, and the tag is transformed into operations on an object called a tag handler, i.e., when the servlet executes, the Web container invokes those operations.

JSP tag extensions allow you to create new tags that can be inserted directly into a JSP page. The JSP 2.0 specification introduced Simple Tag Handlers to write these custom tags.

You can extend the SimpleTagSupport class and override the doTag() method to develop a simple custom tag.


Creating the "Hello" Tag

Next, we want to create a custom tag called <ex:Hello>, with the tag format as follows:

<ex:Hello />

To create a custom JSP tag, you must first create a Java class that handles the tag. So, let's create a HelloTag class as follows:

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!");
  }
}

The following code overrides the doTag() method, which uses the getJspContext() method to obtain the current JspContext object and passes "Hello Custom Tag!" to the JspWriter object.

Compile the above class and copy it to the directory in the CLASSPATH environment variable. Finally, create the following tag library: <Tomcat installation directory>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>

Next, we can use the Hello tag in a JSP file:

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

The above program outputs the following result:

Hello Custom Tag!

Accessing the Tag Body

You can include message content inside a tag just like the standard tag library. For example, if we want to include content in our custom Hello tag, the format is as follows:

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

We can modify the tag handler class file, the code is as follows:

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());
    }

}

Next, we need to modify the TLD file as shown below:

<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>

Now we can use the modified tag in JSP as shown below:

<%@ 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>

The above program outputs the following result:

This is message body

Custom Tag Attributes

You can set various attributes on custom tags. To receive attributes, the custom tag class must implement setter methods. The setter methods in JavaBean are as follows:

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());
       }
   }

}

The attribute name is "message", so the setter method is setMessage(). Now let's add this attribute to the TLD file using the <attribute> element:

<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>

Now we can use the message attribute in a JSP file as follows:

<%@ 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>

The above example outputs the following result:

This is custom tag

You can also include the following attributes:

AttributeDescription
nameDefines the name of the attribute. The attribute name of each tag must be unique.
requiredSpecifies whether the attribute is required or optional. If set to false, it is optional.
rtexprvalueDeclares whether the tag attribute is valid when evaluating runtime expressions.
typeDefines the Java class type of the attribute. The default is specified asString
descriptionDescription information
fragmentIf this attribute is declared, the attribute value will be treated as aJspFragment。

The following is an example of specifying related attributes:

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

If you use two attributes, modify the TLD file as shown below:

.....
    <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>
.....
Other Extensions