| 術語 | 說明 |
|---|---|
| 標籤 | XML 元素,使 JSP 簡潔、可維護、支援多語言。名稱/屬性大小寫敏感。 |
| 標籤庫 | 功能相關標籤的集合,打包為 JAR 便於跨專案重用。 |
| TLD(標籤庫描述檔) | XML 配置檔,定義標籤名、處理類、屬性、體內容類型等元資料。 |
| 標籤處理類 | 實作 TagSupport 或 SimpleTag 介面的 Java 類,封裝標籤執行邏輯。 |
<%@ taglib prefix="my" uri="/WEB-INF/mytags.tld" %>
<my:hello name="World" />
prefix:自訂前綴(避開保留字:jsp, jspx, java, servlet, sun, sunw)。uri:對應 TLD 檔中 <uri> 元素,容器以此定位 TLD。doStartTag():遇到起始標籤。回傳值決定體內容處理:
SKIP_BODY:忽略標籤體EVAL_BODY_INCLUDE:正常執行標籤體doAfterBody()(可選):體內容處理後,可迭代處理(回傳 EVAL_BODY_AGAIN)。doEndTag():遇到結束標籤。回傳值決定頁面後續:
SKIP_PAGE:立即停止頁面執行EVAL_PAGE:繼續執行doTag() 封裝所有邏輯。getJspBody().invoke(null) 輸出標籤體。doStartTag/doEndTag,狀態管理更簡單。標籤屬性對應處理類的 JavaBean 屬性(提供 setter/getter):
public class HelloTag extends SimpleTagSupport {
private String name; // 屬性名
public void setName(String name) { this.name = name; }
public String getName() { return name; }
public void doTag() throws JspException, IOException {
getJspContext().getOut().write("Hello, " + name);
}
}
TLD 中宣告屬性:
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue> <!-- 支援 <%= ... %> 運算式 -->
</attribute>
| body-content | 說明 |
|---|---|
empty | 標籤無主體內容 <my:tag/> |
scriptless | 主體可含 EL、JSTL、自定義標籤,不可含 Scriptlet(推薦) |
tagdependent | 主體由標籤自行解析(如 SQL、模板語言) |
<taglib xmlns="..." version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>myTags</short-name>
<uri>/myTags</uri>
<tag>
<name>hello</name>
<tag-class>com.example.HelloTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
/WEB-INF/ 或 JAR 的 /META-INF/ 下。*.tld,建立 URI 映射。web.xml 可選配置 <taglib> 顯式映射(通常不需要)。PageContext.getServletContext() 讀取快取資源(如屬性檔、模板)。ServletContextListener 在應用啟動時載入靜態資源至 ServletContext 屬性,避免重複 I/O。Properties 類載入 key=value 靜態文本,支援國際化。<description>,降低團隊學習成本。JSP 自定義標籤是「視圖層重用」的核心機制。掌握 TLD 定義、處理類生命週期、屬性綁定與標籤體處理,能構建領域專用標籤語言(DSL),大幅提升頁面開發效率與一致性。現代框架(Spring MVC、JSF、Thymeleaf)皆內建標籤庫,理解底層原理有助於擴展與除錯。