首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Taglib 開發實戰第五章:協作 JSTL 與 EL 表達式的自定義標籤

     編輯:Java 程式設計入門

場景痛點

自定義標籤處理完業務邏輯後,希望將結果暴露給頁面上的 JSTL 標籤(如 <c:out>、<c:forEach>)直接使用,關鍵在於將數據放入頁面上下文(PageContext/Request)並支持 EL 表達式解析。

核心協作機制

  1. 自定義標籤在 doEndTag() 中通過 pageContext.setAttribute(var, value) 發布變量。
  2. JSTL 標籤讀取變量時,其內部調用 ExpressionEvaluatorManager.evaluate(...) 解析 EL 表達式(${name})。
  3. 因此,自定義標籤只需負責「準備數據 → 存入作用域」,無需關心 EL 解析細節。

完整示例:<my:set> 標籤

1. TLD 定義

<tag>
    <name>set</name>
    <tag-class>diegoyun.SetVarTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue> <!-- 支持運行時表達式/EL -->
    </attribute>
    <attribute>
        <name>property</name>
        <required>false</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
        <name>var</name>
        <required>false</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>
</tag>

2. Tag Handler 實現

package diegoyun;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;

public class SetVarTag extends TagSupport {
    private Object value;
    private String property;
    private String var;

    public void setValue(Object value) throws JspException {
        // 關鍵:解析 EL/運行時表達式
        this.value = ExpressionEvaluatorManager.evaluate(
            "value", value.toString(), Object.class, this, pageContext);
    }

    public void setProperty(String property) { this.property = property; }
    public void setVar(String var) { this.var = var; }

    @Override
    public int doEndTag() throws JspException {
        Object propertyValue = null;
        try {
            // 從 value 對象提取屬性(支持巢狀/索引)
            propertyValue = PropertyUtils.getProperty(value, property);
        } catch (Exception e) {
            throw new JspException(e);
        }
        // 發布到頁面上下文,JSTL 即可通過 ${var} 訪問
        pageContext.setAttribute(var, propertyValue);
        return EVAL_PAGE;
    }
}

3. JSP 使用示例

<%@ taglib prefix="my" uri="https://example.com/tags" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>

<% request.setAttribute("user", new User("Alice", "admin")); %>

<!-- 從 user 對象提取 role 屬性,存為 pageScope 變量 currentRole -->
<my:set value="${user}" property="role" var="currentRole"/>

<!-- JSTL 直接使用 -->
<c:out value="${currentRole}"/>
<c:if test="${currentRole == 'admin'}">管理員面板</c:if>

關鍵技術點解析

技術點說明
rtexprvalue=true 允許屬性值為 EL 表達式(${...})或腳本表達式(<%=...%>),容器會在調用 setter 前自動求值。
ExpressionEvaluatorManager.evaluate 手動解析表達式字符串,參數含義:
1. 屬性名(用於錯誤提示)
2. 表達式字符串
3. 期望返回類型
4. Tag 實例(提供 pageContext)
5. PageContext(作用域查找)
PropertyUtils.getProperty Commons BeanUtils 提供,支持 user.address.city、list[0].name 等巢狀/索引路徑。
pageContext.setAttribute(var, value) 默認存入 PageContext.PAGE_SCOPE,也可指定 REQUEST/SESSION/APPLICATION_SCOPE。

進階模式:BodyContent 處理與迭代

若自定義標籤需要對體內容進行多次渲染(如 <c:forEach>),需實現 BodyTag 接口,利用 doInitBody、doAfterBody 協同 BodyContent.getString() 獲取體內容,配合 EVAL_BODY_BUFFERED、EVAL_BODY_AGAIN 控制迭代流程。

總結

自定義標籤與 JSTL/EL 協作的核心契約是:標籤負責「數據準備+作用域發布」,JSTL 負責「表達式解析+渲染」。遵循 rtexprvalue=true、ExpressionEvaluatorManager、PropertyUtils、pageContext.setAttribute 四步曲,即可無縫融入 JSTL 生態。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved