版權所有:(xiaodaoxiaodao)藍小刀 ?? xiaodaoxiaodao@gmail.com

http://www.tkk7.com/xiaodaoxiaodao/articles/103438.html ? ? ?

轉(zhuǎn)載請注明來源/作者

?

JSP tag 學習

?

JSP2.0 中,對于自定義的標簽有兩種實現(xiàn)方法,實現(xiàn)接口或者繼承現(xiàn)有的類

如下圖,標注藍色的是接口,其它是標簽類(SimpleTagSupport只在JSP2.0中才有)

?

tag2.JPG?

在以上接口和類中,定義了一些靜態(tài)常量,如下:

Tag 中定義:

SKIP_BODY = 0;????????? // 不處理標簽體,直接調(diào)用doEndTag()方法

EVAL_BODY_INCLUDE = 1;?? // 解析標簽體,但繞過 doInitBody () setBodyContent () 方法

SKIP_PAGE = 5;????????? // 不解析標簽后面的JSP內(nèi)容

EVAL_PAGE = 6;????????? // 解析標簽后,繼續(xù)解析標簽后面的JSP內(nèi)容

?

IterationTag 中定義:

EVAL_BODY_AGAIN = 2;

?

BodyTag 中定義:

EVAL_BODY_TAG = 2; ???????? // deprecated

EVAL_BODY_BUFFERED = 2;??? //

?

特別的,對于EVAL_BODY_AGAINEVAL_BODY_BUFFERED

doAferBody中返回SKIP_BODY,表示終止標記正文處理;若返回的是 EVAL_BODY_BUFFERED ,將會再一次調(diào)用doAferBody方法,重新處理標記正文,直到返回SKIP_BODY為止。? //

?

TagSupport 默認doStartTag()/doAfterBody()返回SKIP_BODY

BodyTagSupport 默認doStartTag()返回EVAL_BODY_BUFFERED / doInitBody()什么也不做 /doAfterBody()返回SKIP_BODY

下面是自定義tag的執(zhí)行過程(由上至下),對于以上各常量的實際運用為:

注意其中的 doInitBody/setBodyContent 方法在自定義標簽實現(xiàn)了 BodyTag 接口或繼承BodyTagSupport才可以使用

Tag 方法

可返回的靜態(tài)常量

doStartTag

SKIP_BODY EVAL_BODY_INCLUDE

EVAL_BODY_AGAIN/EVAL_BODY_BUFFERED

doInitBody

做標簽一些初始化工作,無返回值

setBodyContent

doInitBody 之后執(zhí)行,使用setBodyContent得到JSP頁面中標簽體之間內(nèi)容

doAfterBody

最終必須返回SKIP_BODY ,否則可能導致OutOfMemoryError,可參考上面

doEndTag

SKIP_PAGE/EVAL_PAGE

?

示例代碼如下:

public int doAfterBody() throws JspException {

? try {

?? this.pageContext.getOut().write("<br>");

? } catch (IOException e) {

????? e.printStackTrace();

? }

? if(cou>1){

?? cou--;

?? return this.EVAL_BODY_AGAIN;

? }else{

?? return this.SKIP_BODY;?? // 最終必須返回SKIP_BODY

? }

?}

?

自定義標簽的開發(fā)包括:

1.? 開發(fā)標簽的處理程序(java類)

2.? .tld 文件中指定標簽使用的類

3.? web.xml中指定JSP中使.tld(標簽庫描述文件)文件的位置。

?

.tld文件中

<tag>

??? <name>out</name>

??? <tag-class>org.apache.taglibs.standard.tag.el.core.OutTag</tag-class>

<body-content>JSP</body-content>

<attribute>

??????? <name>value</name>

??????? <required>true</required>

??????? <rtexprvalue>false</rtexprvalue>

?</attribute>

? </tag>

?

body-content

根據(jù)web-jsptaglibrary_2_0.xsd(位于servlet-api.jar包($TOMCAT_HOME\common\lib)中的\javax\servlet\resources下,其中web.xml驗證時所需要的xsd文件都位于此resources目錄下), body-content 的值有下面4種:

<xsd:enumeration value="tagdependent"/>

??? <xsd:enumeration value="JSP"/>

??? <xsd:enumeration value="empty"/>

??? <xsd:enumeration value="scriptless"/>

?

?

tagdependent 標簽體內(nèi)容 直接被寫入BodyContent,由自定義標簽類來進行處理,而不被JSP容器解釋

如下:

<test:myList>

select name,age from users

</test:myList>

?

JSP 接受所有JSP語法,如定制的或內(nèi)部的tagscripts、靜態(tài)HTML、腳本元素、JSP指令和動作。如:

<my:test>

??? <%=request.getProtocol()%>????? //

</my:test>

具體可參考后面附源碼。

?

empty 空標記,即起始標記和結(jié)束標記之間沒有內(nèi)容。

下面幾種寫法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>

?

scriptless 接受文本、ELJSP動作。如上述使用<body-content> scriptless </body-content> 報錯,具體可參考后面附源碼。

?

rtexprvalue:

由請求時表達式來指定屬性的值,默認為false,如下必須設置為true

<test:welcome uname="<%=request.getParameter("username") %>" />

?

?

body-content JSP/scriptless 時標簽體可以接受的代碼(jasper-compiler.jar $TOMCAT_HOME\common\lib)中 \org\apache\jasper\compiler\Parser.java中):

JSP:

private void parseElements(Node parent)

??????? throws JasperException

??? {

??????? if( scriptlessCount > 0 ) {

??????????? // vc: ScriptlessBody

??????????? // We must follow the ScriptlessBody production if one of

??????????? // our parents is ScriptlessBody.

??????????? parseElementsScriptless( parent );

??????????? return;

??????? }

???????

??????? start = reader.mark();

??????? if (reader.matches("<%--")) {

??????????? parseComment(parent);

??????? } else if (reader.matches("<%@")) {

??????????? parseDirective(parent);

??????? } else if (reader.matches("<jsp:directive.")) {

??????????? parseXMLDirective(parent);

??????? } else if (reader.matches("<%!")) {

??????????? parseDeclaration(parent);

??????? } else if (reader.matches("<jsp:declaration")) {

??????????? parseXMLDeclaration(parent);

??????? } else if (reader.matches("<%=")) {

??????????? parseExpression(parent);

??????? } else if (reader.matches("<jsp:expression")) {

??????????? parseXMLExpression(parent);

??????? } else if (reader.matches("<%")) {

??????????? parseScriptlet(parent);

??????? } else if (reader.matches("<jsp:scriptlet")) {

??????????? parseXMLScriptlet(parent);

??????? } else if (reader.matches("<jsp:text")) {

??????????? parseXMLTemplateText(parent);

??????? } else if (reader.matches("${")) {

??????????? parseELExpression(parent);

??????? } else if (reader.matches("<jsp:")) {

??????????? parseStandardAction(parent);

??????? } else if (!parseCustomTag(parent)) {

??????????? checkUnbalancedEndTag();

??????????? parseTemplateText(parent);

??????? }

}

Scriptless:

private void parseElementsScriptless(Node parent)

??????? throws JasperException

??? {

??????? // Keep track of how many scriptless nodes we've encountered

??????? // so we know whether our child nodes are forced scriptless

??????? scriptlessCount++;

???????

??????? start = reader.mark();

??????? if (reader.matches("<%--")) {

??????????? parseComment(parent);

??????? } else if (reader.matches("<%@")) {

??????????? parseDirective(parent);

??????? } else if (reader.matches("<jsp:directive.")) {

??????????? parseXMLDirective(parent);

??????? } else if (reader.matches("<%!")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??????? } else if (reader.matches("<jsp:declaration")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??????? } else if (reader.matches("<%=")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??? ????} else if (reader.matches("<jsp:expression")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??????? } else if (reader.matches("<%")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??????? } else if (reader.matches("<jsp:scriptlet")) {

??????????? err.jspError( reader.mark(), "jsp.error.no.scriptlets" );

??????? } else if (reader.matches("<jsp:text")) {

??????????? parseXMLTemplateText(parent);

??????? } else if (reader.matches("${")) {

??????????? parseELExpression(parent);

??????? } else if (reader.matches("<jsp:")) {

??????????? parseStandardAction(parent);

??????? } else if (!parseCustomTag(parent)) {

??????????? checkUnbalancedEndTag();

??????????? parseTemplateText(parent);

??????? }

???????

????? ??scriptlessCount--;

}

?

由上面可以看出,局限性比較小,在body-content可以使用 Scriptless 的地方都可以用 JSP 代替,反之則不可。

?

版權所有:(xiaodaoxiaodao)藍小刀 ?? xiaodaoxiaodao@gmail.com