JAVA tag学习

摘要:
EVAL_BODY_INCLUDE:将主体读取到现有输出流中。doStartTag()函数可以使用EVAL_PAGE:继续处理页面,doEndTag()功能可以使用SKIP_BODY:忽略正文的处理。doStartTag()和doAfterBody()函数可以使用SKIP_PAGE:忽略剩余页面的处理。doEndTag()函数可以使用EVAL_ BODY_ TAG:由EVAL_ BODY_ BUFF废除

EVAL_BODY_INCLUDE:把Body读入存在的输出流中,doStartTag()函数可用
EVAL_PAGE:继续处理页面,doEndTag()函数可用
SKIP_BODY:忽略对Body的处理,doStartTag()和doAfterBody()函数可用
SKIP_PAGE:忽略对余下页面的处理,doEndTag()函数可用
EVAL_BODY_TAG:已经废止,由EVAL_BODY_BUFFERED取代
EVAL_BODY_BUFFERED:申请缓冲区,由setBodyContent()函数得到的BodyContent对象来处理tag的body,如果类实现了BodyTag,那么doStartTag()可用,否则非法

=========================================================================

/**EVAL_BODY_INCLUDE计算正文内容,SKIP_BODY不计算Body。
书上说的具体是什么意思啊??我不明白什么???怎么用的?在什么情况下用?有什么作用*/
答案:
这两个返回值时针对标签的主体而言,tablig的目的是为了封装java脚本,如果在doStartTag执行后doEndTag执行前 还需要有元素则可以写在tag的主体中,一般tag没有主体,对于有主体的tag当返回SKIP_BODY则忽略掉主体,返回EVAL_BODY_INCLUDE时才会把主体输出到页面。
比如<<h:xx >hello</h:xx>
假设doStartTag是输出一个<a href="http://t.zoukankan.com/xx"></a>且返回SKIP_BODY,则页面最终为<a href="http://t.zoukankan.com/xx"></a>,
但若返回EVAL_BODY_INCLUDE,则页面效果<a href="http://t.zoukankan.com/xx"></a>hello
然后再执行doEndTag
=========================================================================

 

JSP tag 学习

 

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

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

 

 

 

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

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为止。  // 

 

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

BodyTagSupport 默认doStartTag()返回EVAL_BODY_BUFFERED / doInitBody()什么也不做 /doAfterBody()返回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--;

}

 

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

免责声明:文章转载自《JAVA tag学习》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇.NET中RabbitMq的使用Quartz中时间表达式的设置-----corn表达式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

supervisor的command执行两条命令

如下supervisor的进程的comand配置参数只能写一个命令 1、要执行多条命令,可以写个sh文件包含多条命令,然后sh -x xxxx.sh,但这样又多了一个文件, 2、把所有命令放在字符串,然后用eval来执行,这样在shell窗口可以执行,但放在supervisor报找不到eval命令。比如: command = eval "python -u...

IDE Eval Resetter:JetBrains 全家桶无限试用插件

JetBrains 系列  IDE,开源项目可以重置 JetBrains 试用 30 天的时间,实现“无限试用”,本文分享下使用方法。 一、IDE Eval Resetter 介绍 项目地址:https://gitee.com/pengzhile/ide-eval-resetter 项目功能:JetBrains 所有产品都有 30 天试用,这个插件的作用就...

JS学习笔记(一)JS处理JSON数据

【摘抄】将JSON字符串转换为json对象的方法。在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键。例如:JSON字符串: var str1 = '{ "name": "cxh", "sex": "man" }'; JSON对象: var str2 = { "na...

计蒜客:百度的科学计算器(简单)【python神解】

题目链接:https://nanti.jisuanke.com/t/15504 题解:python大法好啊,三行代码无人能敌啊! 下面给出AC代码: 1 b=input() 2 a=input() 3 print("%.6f"%eval(a))if '.' in a else print(int(eval(a)))...

深入探讨this指针

深入探讨this指针   为了写这篇文章,准备了好长时间,翻遍了箱底的书籍。可是如今还是不敢放开手来写,战战兢兢。不是操心自己写错,而是唯恐自己错误误导别人。同一时候也希望这篇文章能给你一点收获。既然是深入探讨this指针,所以建议刚開始学习的人,最好具有一定编译基础,调试基础。假设大家觉得这片文章有不满的地方,就给我发信批评一下,以便及时修正。 关于t...

php eval函数用法总结

可以在php.ini禁止此函数,结果失败了 eval定义和用法 eval() 函数把字符串按照 PHP 代码来计算。 该字符串必须是合法的 PHP 代码,且必须以分号结尾。 如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。 语法 eval(phpcode) 参数 描述 php...