JSP 自定义标签

写一个标签处理器、TLD 描述文件、在页面里使用。

Advanced
Key Points自定义标签 = 一个继承 SimpleTagSupport 的类 + 一个 TLD 描述文件 + 页面里的一句 taglib 指令。

三部分

PartFileJob
HandlerXxxTag.java写标签被解析时做什么
DescriptorWEB-INF/mytags.tld声明标签名、属性、处理器类
Usage*.jsp<%@ taglib %> + 标签

标签处理器

Java
package com.example.tags;

import java.io.IOException;
import jakarta.servlet.jsp.JspException;
import jakarta.servlet.jsp.tagext.SimpleTagSupport;

public class HelloTag extends SimpleTagSupport {

    private String name = "World";

    public void setName(String name) { this.name = name; }

    @Override
    public void doTag() throws JspException, IOException {
        getJspContext().getOut().print("Hello, " + name + "!");
    }
}

SimpleTagSupport has a single method to implement, doTag(). Write output with getJspContext().getOut(); run the body with getJspBody().invoke(null).

TLD 描述文件

XML
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="https://jakarta.ee/xml/ns/jakartaee"
        version="3.0">
  <tlib-version>1.0</tlib-version>
  <short-name>my</short-name>
  <uri>http://example.com/tags/my</uri>

  <tag>
    <name>hello</name>
    <tag-class>com.example.tags.HelloTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
      <name>name</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
</taglib>
ElementMeaning
uri页面 taglib 指令里用的标识
name页面上写的标签名
body-contentempty / scriptless / tagdependent
rtexprvalue能否用 ${...} 或 <%= %> 赋值

在页面里使用

JSP
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="my" uri="http://example.com/tags/my" %>

<my:hello/>
<my:hello name="${param.user}"/>
Output
Hello, World!
Hello, Ada!

带标签体的标签

Java
public class UpperTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        StringWriter sw = new StringWriter();
        getJspBody().invoke(sw);                       // 先执行标签体,结果进 sw
        getJspContext().getOut().print(sw.toString().toUpperCase());
    }
}
JSP
<my:upper>hello world</my:upper>
Output
HELLO WORLD

getJspBody().invoke(sw) captures the body output into a StringWriter so you can transform it before writing. That is the standard pattern for escaping, highlighting and truncation tags.

Keep the TLD under WEB-INF (or WEB-INF/tags, or META-INF in a jar). In the wrong place the container cannot resolve the uri and the tags are echoed as plain HTML — with no error at all, the hardest kind to debug.

什么时候值得写

  • 同一段展示逻辑重复三次以上 —— 比如分页条、权限按钮、状态徽章
  • 需要在视图里做转义/格式化 —— 比在每个页面写脚本可靠
  • 不写 —— 一次性需求、能用 JSTL 组合解决的、逻辑属于业务的

Friends & Partners