jsp tag学习

版权所有:(xiaodaoxiaodao)蓝小刀 http://blog.youkuaiyun.com/xiaodaoxiaodao/archive/2007/01/05/1474360.aspx

转载请注明来源/作者


在JSP2.0 中,对于自定义的标签有两种实现方法,实现接口或者继承现有的类

如下图,标注蓝色的是接口,其它是标签类(SimpleTagSupport只在JSP2.0中才有)


JspTag (蓝色为接口)

Tag ——〉IterationTag
SimpleTag


BodyTag


TagSupport
BodyTagSupport extends TagSupport implements BodyTag
SimpleTagSupport




在以上接口和类中,定义了一些静态常量,如下:

Tag中定义:

SKIP_BODY = 0; // 不处理标签体,直接调用doEndTag()方法

EVAL_BODY_INCLUDE = 1; // 解析标签体,但绕过doInitBody()和setBodyContent()方法

SKIP_PAGE = 5; // 不解析标签后面的JSP内容

EVAL_PAGE = 6; // 解析标签后,继续解析标签后面的JSP内容



IterationTag中定义:

EVAL_BODY_AGAIN = 2;



BodyTag中定义:

EVAL_BODY_TAG = 2; // deprecated

EVAL_BODY_BUFFERED = 2; //



特别的,对于EVAL_BODY_AGAIN和EVAL_BODY_BUFFERED:

在doAferBody中返回SKIP_BODY,表示终止标记正文处理;若返回的是EVAL_BODY_BUFFERED,将会再一次调用doAferBody方法,重新处理标记正文,直到返回SKIP_BODY为止。 // ①



下面是自定义tag的执行过程(由上至下),对于以上各常量的实际运用为:

注意其中的doInitBody/setBodyContent方法在自定义标签实现了BodyTag接口或继承BodyTagSupport才可以使用
Tag方法
可返回的静态常量

doStartTag
SKIP_BODY、EVAL_BODY_INCLUDE、

EVAL_BODY_AGAIN/EVAL_BODY_BUFFERED

doInitBody
做标签一些初始化工作,无返回值

setBodyContent
在doInitBody之后执行,使用setBodyContent得到JSP页面中标签体之间内容

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

}

}



自定义标签的开发包括:

1. 开发标签的处理程序(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:

根据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:标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释,

如下:

<test:myList>

select name,age from users

</test:myList>



JSP:接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:

<my:test>

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

</my:test>

具体可参考后面附源码。



empty:空标记,即起始标记和结束标记之间没有内容。

下面几种写法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>



scriptless:接受文本、EL和JSP动作。如上述②使用<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--;

}



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


注意!!:
EVAL_BODY_BUFFERED 和 EVAL_BODY_INCLUDE 区别是 是否调用 setBodyContent 对BodyContent进行填充~。
标题基于SpringBoot+Vue的社区便民服务平台研究AI更换标题第1章引言介绍社区便民服务平台的研究背景、意义,以及基于SpringBoot+Vue技术的研究现状和创新点。1.1研究背景与意义分析社区便民服务的重要性,以及SpringBoot+Vue技术在平台建设中的优势。1.2国内外研究现状概述国内外在社区便民服务平台方面的发展现状。1.3研究方法与创新点阐述本文采用的研究方法和在SpringBoot+Vue技术应用上的创新之处。第2章相关理论介绍SpringBoot和Vue的相关理论基础,以及它们在社区便民服务平台中的应用。2.1SpringBoot技术概述解释SpringBoot的基本概念、特点及其在便民服务平台中的应用价值。2.2Vue技术概述阐述Vue的核心思想、技术特性及其在前端界面开发中的优势。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue如何有效整合,以提升社区便民服务平台的性能。第3章平台需求分析与设计分析社区便民服务平台的需求,并基于SpringBoot+Vue技术进行平台设计。3.1需求分析明确平台需满足的功能需求和性能需求。3.2架构设计设计平台的整体架构,包括前后端分离、模块化设计等思想。3.3数据库设计根据平台需求设计合理的数据库结构,包括数据表、字段等。第4章平台实现与关键技术详细阐述基于SpringBoot+Vue的社区便民服务平台的实现过程及关键技术。4.1后端服务实现使用SpringBoot实现后端服务,包括用户管理、服务管理等核心功能。4.2前端界面实现采用Vue技术实现前端界面,提供友好的用户交互体验。4.3前后端交互技术探讨前后端数据交互的方式,如RESTful API、WebSocket等。第5章平台测试与优化对实现的社区便民服务平台进行全面测试,并针对问题进行优化。5.1测试环境与工具介绍测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值