JSP tag 学习
在JSP2.0 中,对于自定义的标签有两种实现方法,实现接口或者继承现有的类
如下图,标注蓝色的是接口,其它是标签类(SimpleTagSupport只在JSP2.0中才有)
在以上接口和类中,定义了一些静态常量,如下:
Tag 中定义:
SKIP_BODY = 0; // 不处理标签体,直接调用doEndTag()方法
EV
SKIP_PAGE = 5; // 不解析标签后面的JSP内容
EV
IterationTag 中定义:
EV
BodyTag 中定义:
EV // deprecated
EV
特别的,对于EV
在doAferBody中返回SKIP_BODY,表示终止标记正文处理;若返回的是 EV,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。 // ①
TagSupport 默认doStartTag()/doAfterBody()返回SKIP_BODY
BodyTagSupport 默认doStartTag()返回EV
下面是自定义tag的执行过程(由上至下),对于以上各常量的实际运用为:
注意其中的 doInitBody/setBodyContent 方法在自定义标签实现了 BodyTag 接口或继承BodyTagSupport才可以使用
Tag 方法 | 可返回的静态常量 |
doStartTag | SKIP_BODY 、EV EV |
doInitBody 做标签一些初始化工作,无返回值 setBodyContent 在 doInitBody 之后执行,使用setBodyContent得到JSP页面中标签体之间内容 doAfterBody 最终必须返回SKIP_BODY ,否则可能导致OutOfMemoryError,可参考上面① doEndTag SKIP_PAGE/EV
附 ① 示例代码如下: public int doAfterBody() throws JspException { try { this.pageContext.getOut().write(" } catch (IOException e) { e.printStackTrace(); } if(cou>1){ cou--; return this.EV }else{ return this.SKIP_BODY; // 最终必须返回SKIP_BODY } }
自定义标签的开发包括: 1. 开发标签的处理程序(java类) 2. .tld 文件中指定标签使用的类 3. 在web.xml中指定JSP中使.tld(标签库描述文件)文件的位置。
在.tld文件中 <body-content>JSP <rtexprvalue>false
body-content : 根据web-jsptaglibrary_2_0.xsd(位于servlet-api.jar包($TOMCAT_HOME\common\lib)中的\javax\servlet\resources下,其中web.xml验证时所需要的xsd文件都位于此resources目录下), body-content 的值有下面4种:
tagdependent : 标签体内容 直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释, 如下: select name,age from users
JSP : 接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如: <%=request.getProtocol()%> // ②
具体可参考后面附源码。
empty : 空标记,即起始标记和结束标记之间没有内容。 下面几种写法都是有效的,
scriptless : 接受文本、EL和JSP动作。如上述②使用
rtexprvalue: 由请求时表达式来指定属性的值,默认为false,如下必须设置为true:
附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 on // 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(" parseXMLDirective(parent); } else if (reader.matches("<%!")) { parseDeclaration(parent); } else if (reader.matches(" parseXMLDeclaration(parent); } else if (reader.matches("<%=")) { parseExpression(parent); } else if (reader.matches(" parseXMLExpression(parent); } else if (reader.matches("<%")) { parseScriptlet(parent); } else if (reader.matches(" parseXMLScriptlet(parent); } else if (reader.matches(" parseXMLTemplateText(parent); } else if (reader.matches("${")) { parseELExpression(parent); } else if (reader.matches(" 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(" parseXMLDirective(parent); } else if (reader.matches("<%!")) { err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches(" err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches("<%=")) { err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches(" err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches("<%")) { err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches(" err.jspError( reader.mark(), "jsp.error.no.scriptlets" ); } else if (reader.matches(" 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 代替,反之则不可。 相关文章JBoss,Tomcat 中文URL支持方法JBOSS 找到jboss4的deploy\jbossweb-tomcat50.sar\server.xml,编辑该文件,在下面的XML节点中增加红色的字<Connector port="808... 在web.xml不认<taglib>解决办法在web.xml不认<taglib>解决办法: 如果是头是这样的<!DOCTYPE web-app PUBLIC "-//Sun Micros... struts,ajax乱码解决方案乱码问题好像跟我们中国程序员特别有缘,一直困扰着我们,从开始的JSP乱码问题,STRUTS乱码问题,到现在的AJAX乱码问题,无一不是搞得许多程序员焦头烂额的,整天骂XXX产品对中文支持不了,UT... JSP动态include与静态include的区别动态INCLUDE jsp:include page="included.jsp" flush="true" />它总是会检查所含文件中的变化,适合用于包含动态... 浏览网页时的错误代号① 客户方错误 100 继续 101 交换协议 ② 成功 ... FCKeditor的秘密哈哈。。由于项目的需要,这几天一直在搞FCKeditor。其实,FCKeditor配置很简单。但不知道怎么样。在我的项目里FC... 发表评论 |