版權(quán)所有:(xiaodaoxiaodao)藍(lán)小刀
??
xiaodaoxiaodao@gmail.com
http://www.tkk7.com/xiaodaoxiaodao/articles/103438.html
?
?
?
轉(zhuǎn)載請(qǐng)注明來(lái)源/作者
?
JSP tag
學(xué)習(xí)
?
在JSP2.0 中,對(duì)于自定義的標(biāo)簽有兩種實(shí)現(xiàn)方法,實(shí)現(xiàn)接口或者繼承現(xiàn)有的類
如下圖,標(biāo)注藍(lán)色的是接口,其它是標(biāo)簽類(SimpleTagSupport只在JSP2.0中才有)
?
?
在以上接口和類中,定義了一些靜態(tài)常量,如下:
Tag
中定義:
SKIP_BODY = 0;????????? //
不處理標(biāo)簽體,直接調(diào)用doEndTag()方法
EVAL_BODY_INCLUDE = 1;?? //
解析標(biāo)簽體,但繞過(guò)
doInitBody
()
和
setBodyContent
()
方法
SKIP_PAGE = 5;????????? //
不解析標(biāo)簽后面的JSP內(nèi)容
EVAL_PAGE = 6;????????? //
解析標(biāo)簽后,繼續(xù)解析標(biāo)簽后面的JSP內(nèi)容
?
IterationTag
中定義:
EVAL_BODY_AGAIN = 2;
?
BodyTag
中定義:
EVAL_BODY_TAG = 2;
???????? // deprecated
EVAL_BODY_BUFFERED = 2;??? //
?
特別的,對(duì)于EVAL_BODY_AGAIN和EVAL_BODY_BUFFERED:
在doAferBody中返回SKIP_BODY,表示終止標(biāo)記正文處理;若返回的是
EVAL_BODY_BUFFERED
,將會(huì)再一次調(diào)用doAferBody方法,重新處理標(biāo)記正文,直到返回SKIP_BODY為止。? // ①
?
TagSupport
默認(rèn)doStartTag()/doAfterBody()返回SKIP_BODY
BodyTagSupport
默認(rèn)doStartTag()返回EVAL_BODY_BUFFERED / doInitBody()什么也不做 /doAfterBody()返回SKIP_BODY
下面是自定義tag的執(zhí)行過(guò)程(由上至下),對(duì)于以上各常量的實(shí)際運(yùn)用為:
注意其中的
doInitBody/setBodyContent
方法在自定義標(biāo)簽實(shí)現(xiàn)了
BodyTag
接口或繼承BodyTagSupport才可以使用
Tag
方法
|
可返回的靜態(tài)常量
|
doStartTag
|
SKIP_BODY
、EVAL_BODY_INCLUDE、
EVAL_BODY_AGAIN/EVAL_BODY_BUFFERED
|
doInitBody
|
做標(biāo)簽一些初始化工作,無(wú)返回值
|
setBodyContent
|
在
doInitBody
之后執(zhí)行,使用setBodyContent得到JSP頁(yè)面中標(biāo)簽體之間內(nèi)容
|
doAfterBody
|
最終必須返回SKIP_BODY
,否則可能導(dǎo)致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
? }
?}
?
自定義標(biāo)簽的開(kāi)發(fā)包括:
1.?
開(kāi)發(fā)標(biāo)簽的處理程序(java類)
2.?
.tld
文件中指定標(biāo)簽使用的類
3.?
在web.xml中指定JSP中使.tld(標(biāo)簽庫(kù)描述文件)文件的位置。
?
在.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驗(yàn)證時(shí)所需要的xsd文件都位于此resources目錄下),
body-content
的值有下面4種:
<xsd:enumeration value="tagdependent"/>
??? <xsd:enumeration value="JSP"/>
??? <xsd:enumeration value="empty"/>
??? <xsd:enumeration value="scriptless"/>
|
?
?
tagdependent
:
標(biāo)簽體內(nèi)容
直接被寫(xiě)入BodyContent,由自定義標(biāo)簽類來(lái)進(jìn)行處理,而不被JSP容器解釋,
如下:
<test:myList>
select name,age from users
</test:myList>
?
JSP
:
接受所有JSP語(yǔ)法,如定制的或內(nèi)部的tag、scripts、靜態(tài)HTML、腳本元素、JSP指令和動(dòng)作。如:
<my:test>
??? <%=request.getProtocol()%>????? //
②
</my:test>
具體可參考后面附源碼。
?
empty
:
空標(biāo)記,即起始標(biāo)記和結(jié)束標(biāo)記之間沒(méi)有內(nèi)容。
下面幾種寫(xiě)法都是有效的,
<test:mytag />
<test:mytag uname="Tom" />
<test:mytag></test:mytag>
?
scriptless
:
接受文本、EL和JSP動(dòng)作。如上述②使用<body-content>
scriptless
</body-content>
則報(bào)錯(cuò),具體可參考后面附源碼。
?
rtexprvalue:
由請(qǐng)求時(shí)表達(dá)式來(lái)指定屬性的值,默認(rèn)為false,如下必須設(shè)置為true:
<test:welcome uname="<%=request.getParameter("username") %>" />
?
?
附body-content為
JSP/scriptless
時(shí)標(biāo)簽體可以接受的代碼(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
代替,反之則不可。
?
版權(quán)所有:(xiaodaoxiaodao)藍(lán)小刀
??
xiaodaoxiaodao@gmail.com