在 Java Web 開發中,JSTL(JSP Standard Tag Library)提供了豐富的標準標籤,但實際專案往往需要根據業務邏輯擴展自定義標籤與函數。本文將系統講解如何實現自定義 JSTL 標籤、函數庫,並介紹較少使用的 c:forTokens 標籤用法。
自定義標籤的核心在於實現標籤處理類並註冊 TLD(Tag Library Descriptor)檔案。
最基礎的方式是實作 javax.servlet.jsp.tagext.SimpleTag 介面。容器會自動呼叫 setJspContext() 注入 JspContext(實際上即 PageContext),在 doTag() 方法中編寫輸出邏輯,透過 jspContext.getOut() 取得 JspWriter 向頁面寫入內容。
public class MyTag2 implements SimpleTag {
private JspContext jspContext;
@Override
public void doTag() throws JspException, IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = sdf.format(new Date());
JspWriter out = jspContext.getOut();
out.write(dateStr);
}
@Override public void setJspContext(JspContext jspContext) { this.jspContext = jspContext; }
// 其他介面方法略...
}
在 WEB-INF 目錄下建立 .tld 檔案,定義標籤名稱、處理類、主體內容類型等資訊。參考 JSTL 內建的 c.tld 可加速開發。
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="https://java.sun.com/xml/ns/j2ee" ...>
<display-name>Custom Core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>custom</short-name>
<uri>https://example.com/tags</uri>
<tag>
<name>showDate</name>
<tag-class>com.example.tag.MyTag2</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
使用 <%@ taglib %> 指令引入標籤庫,指定前綴與 URI,即可在頁面中像使用內建標籤一樣呼叫自定義標籤。
<%@ taglib prefix="cust" uri="https://example.com/tags" %>
<html><body>
<cust:showDate/>
</body></html>
SimpleTagSupport 已實作 SimpleTag 介面並完成 JspContext、JspFragment 等屬性的注入,直接繼承即可專注於業務邏輯,減少樣板程式碼。
body-content 詳解TLD 中 <body-content> 決定標籤主體的處理方式,四種可選值:
<cust:showDate/>)。<% %>)。在處理類中提供 setXxx() 方法對應屬性名稱;TLD 中 <attribute> 子元素需設定 name(屬性名)、required(是否必填)、rtexprvalue(是否支援 EL 表達式)。
若需對主體進行處理(如轉大寫),可在 doTag() 中取得 JspFragment,呼叫 invoke(Writer) 將執行結果寫入 StringWriter,處理後再輸出至 JspWriter。
JspFragment body = getJspBody();
StringWriter sw = new StringWriter();
body.invoke(sw);
String result = sw.toString().toUpperCase();
getJspContext().getOut().print(result);
函數庫讓 EL 表達式能直接呼叫靜態 Java 方法,極大擴展表達能力。
類與方法必須為 public static。
public class MyFunctions {
public static String hello() {
return new Date().toString();
}
}
在 <function> 元素中指定函數名稱、完整類名、方法簽名(含回傳型別與參數型別)。
<function>
<name>hello</name>
<function-class>com.example.func.MyFunctions</function-class>
<function-signature>java.lang.String hello()</function-signature>
</function>
<%@ taglib prefix="fn" uri="https://example.com/tags" %>
${fn:hello()}
c:forTokens 標籤c:forTokens 可依指定分隔符拆分字串並迭代,適合處理逗號分隔等簡單場景。
<% pageContext.setAttribute("str", "aa,bb,ee,mm,tt"); %>
<c:forTokens items="${str}" delims="," var="item">
${item} <br/>
</c:forTokens>
輸出:
aa
bb
ee
mm
tt
掌握自定義標籤與函數庫,能讓 JSP 頁面更簡潔、邏輯更集中,提升專案可維護性。實務上建議優先考慮標準 JSTL 與 EL 能否滿足需求,若確有必要再擴展自定義元件。