JSTL標簽(如<c:out value="${tut}"/>)能無縫解析EL表達式,自定義標簽若想具備同等能力,需理解容器如何評估EL。本文揭秘ExpressionEvaluatorManager核心機制,並演示從零構建支持EL的標簽處理類。
位於org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager:
public static Object evaluate(
String attributeName, // 標簽屬性名,用於錯誤提示
String expression, // EL表達式字符串(如"${tut}")
Class<?> expectedType, // 期望返回類型,通常Object.class
Tag tag, // 當前標簽實例(this)
PageContext pageContext // 頁面上下文
) throws JspException
關鍵點:屬性聲明為Object類型,setXxx(Object value)中調用evaluate:
private Object value = null;
public void setValue(Object value) throws JspException {
this.value = ExpressionEvaluatorManager.evaluate(
"value", value.toString(), Object.class, this, pageContext);
}
五個參數照抄模板,僅修改attributeName為對應屬性名。
<diego:newout>標簽package diegoyun;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
public class NewOutputTag extends TagSupport {
private Object name = null;
public void setName(Object name) throws JspException {
this.name = ExpressionEvaluatorManager.evaluate(
"name", name.toString(), Object.class, this, pageContext);
}
public int doStartTag() throws JspException {
try {
JspWriter out = pageContext.getOut();
out.print("Hello! " + name);
} catch (Exception e) {
throw new JspException(e);
}
return EVAL_PAGE;
}
}
diego.tld)<tag>
<name>newout</name>
<tag-class>diegoyun.NewOutputTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue> <!-- 關鍵:允許運行時表達式/EL -->
</attribute>
</tag>
<%@ taglib uri="/WEB-INF/tlds/diego.tld" prefix="diego" %>
<html><body>
<%
String s = "diego";
request.setAttribute("name", s);
%>
Test EL supported tag:<br>
<diego:newout name="${name}"/>
</body></html>
輸出:
Test EL supported tag:
Hello! diego
rtexprvalue=true是前提:聲明標簽屬性接受運行時表達式值(含EL、Scriptlet)。String,容器會在調用setter前強制toString(),導致EL表達式字面量傳入而非評估結果。evaluate會拋JspException,直接拋出讓容器處理錯誤頁。ExpressionEvaluatorManager(屬於JSTL實現內部類,實際項目建議依賴標準javax.servlet.jsp.jstl.core.Config或容器提供的ExpressionEvaluator)。掌握EL評估機制,讓自定義標簽擁有與JSTL一致的表達能力,是構建領域特定標簽庫(DSL)的關鍵一步。