今天还是讲解自定义标签。
首先介绍了IterationTag接口、以及迭代输出标签体内容的标签实现原理和应用。在讲解迭代输出集合中的元素的例子时,先讲解用普通程序代码迭代输出集合的情况:for(String user : users){System.out.println("姓名:" + user)}
上面的程序代码包含三个信息:迭代变量、集合对象、显示格式,用自定义标签进行迭代输出时,其格式如下:
<it315:iterate var="user" collections="<%= users %>">姓名:${user}</it315:iterate>。
jsp页面需要将迭代变量和集合对象作为参数传递给自定义标签,自定义标签内部对集合进行迭代,在每次迭代时,将结果存入page域中并输出标签体内容,JSP页面中的标签体按一定格式引用迭代标签存入到page域中的变量。JSP页面的标签体中怎么知道page域中的变量名称的呢?这就是通过属性传递给自定义标签的那个迭代名称。
接下来讲解了如何通过自定义标签来定义JSP脚本变量。首先帮助学员比较下面这些语句的区别:
<%= abc %>
${abc}
前者是一个脚本变量,要“先定义、后使用”。而后者相当于<%= pageContext./*get*/findAttribute("abc")%>。
要想理解自定义标签是如何定义出JSP脚本变量的,首先就要知道:对于<it315:var />,千万不要认为仅仅只有jsp页面调用这个标签对应的处理类的功能,还要知道这个标签具有告诉JSP引擎生成一段怎样的Servlet Java代码的功能,其中包括定义新的变量。如果在标签定义文件中用了variable,会生成变量定义和变量赋值的代码(这个会自动吗?还是需要标签处理类自己写,我想是要自己写,但没做自己不写的实验)。
接着讲解了如何用TagExtraInfo类定义JSP脚本变量,这由涉及到了VariableInfo和TagData这两个类。如果想让一个标签可以定义出任何类型的java对象,当对象类型不确定时,TLD文件中的<variable-class>元素内容就无法确定,这时候就可以使用TagExtraInfo类。
接着讲解了BodyTag接口和如何让自定义标签控制标签体内容,学员们应记住两个重要的细节:在什么方法之中,BodyCotent对象中才有标签体部分的内容;pageContext.getOut()返回的对象不是永恒不变的,在doStartTage、doInitBody、doAfterBody、doEndTag等方法中获得的对象不相同。
最后讲解了Tomcat下的自定义标签的缓存和线程安全问题,关于自定义标签缓存的实验:先打开原始的JSP文件翻译成的Servlet java源文件和jsp源文件,用ultraedit复制一份Servlet java源文件,保存到另外一个文件中。再修改web.xml文件,让Tomcat不要对自定义标签进行缓存,启动tomcat后访问jsp,ultraedit没有提示servlet java源文件更改的信息,所以,用ultraedit打开并修改jsp文件(增空格后删除空格),重新访问jsp文件,ultraedit提示Servlet java源文件更改,将原来复制的Servlet源文件拖动到它的旁边,然后使用比较工具进行比较,可以发现两者的显著区别。据方立勋和王泽佑的实验,在不对标签进行缓存的情况下生成的Servlet源文件有问题,在_service方法中new了标签对象,而在_jspDestroy方法中才进行释放,这将导致只有最后一次service方法被调用时产生的标签对象才会被释放,他们用的tomcat是tomcat 5.5.9,看来又抓住了tomcat以前的一个bug。要留一个tomcat 5.5.9的版本。
学员王泽佑发现jsp的问题:
<%!
int count = 0;
public void jspInit()
{
System.out.println("jspInit!");
}
%>
<%= ++count %>
如果赶在第一次访问jsp时,快速刷新,刷新到一定时机后,jsp生成的servlet会重新被加载,我想这是在编译jsp时没有处理好并发的问题。另外一个问题,通过运行对话框启动浏览器访问jsp页面,多次重复这一操作,即快速启动多个浏览器进程来访问jsp页面,由于速度很快,其中一些浏览器直接从缓存中抓取数据,而不向服务器发出访问请求。
学员田湘东发现下面例子中的一个问题:
public class IterateMessages extends TagSupport
{
String name;
String [] s;
int i = 1;//缓存问题
public void setName(String name)
{
this.name = name;
}
public void setMessages(String[] s)
{
this.s = s;
}
public int doStartTag() throws JspException
{
if(s.length > 0)
{
pageContext.setAttribute(name,s[0]);
return EVAL_BODY_INCLUDE;
}
else
{
return SKIP_BODY;
}
}
public int doAfterBody() throws JspException
{
if(i < s.length)
{
pageContext.setAttribute(name,s[i]);
i++;
return EVAL_BODY_AGAIN;
}
else
{
return SKIP_BODY;
}
}
}
考虑到标签处理器对象的缓存问题,i成员变量不能在定义时赋值,而应该在doStartTag方法中赋值。
作业:
1.在doStartTag方法中返回EVAL_BODY_INCLUDE的情况下,在doInitBody方法中、doAfterBody方法中、oEndTag方法中分别向PageContext.getOut获得的out对象中写入内容,看看有怎样的区别?
2.对于书稿中的10.6.3的例子,如果在doStartTag方法中不返回EVAL_BODY_INCLUDE,那么嵌套在它里面的子标签向out中输出的内容就应该是直接传递给浏览器,并且原来程序中调用的bodyContent应该无效导致异常,做个实验看看。
分享到:
相关推荐
里面有thinkphp自定义标签的方法和使用文档
在vue中使用antv/x6和element组件,实现自定义流程的编写,使用antv/x6实现画布绘制和流程绘制,通过拖动节点到画布的方式进行节点的添加,使用element组件实现鼠标移入节点后的自定义功能,使用antv/x6自带的api和...
本文实例讲述了ThinkPHP分组下自定义标签库的实现方法。分享给大家供大家参考。具体如下: 自定义标签库应该位于ThinkPHP\\Extend\\Driver\\TagLib目录下 1 新建标签类库文件名为TagLibBlog.class.php。 2 编辑刚才...
主要介绍了ThinkPHP模板自定义标签使用方法,需要的朋友可以参考下
g2自定义 3d柱状图、分割柱状图及g6 自定义卡片
此分页标签总共有7个属性,都是必有的属性, 1、pageSize(每页显示的条数);...(注:使用时一定要导入标签的路径,会写自定义标签的应该知道,此标签写着玩的,没什么商业价值,有什么问题可以一起讨论哈)
主要介绍了Angular6 用户自定义标签开发的实现方法,下面我们就通过一个简单的例子演示Angular6中的这一新功能,小编觉得挺不错的,现在分享给大家,需要的朋友可以参考下
********** TP自定义模板pc标签(Pctag:pc) ************ 功能类似PHPcms的pc标签功能。模板标签主动的调用数据源,获取数据后再自行组织展示。支持取模板assign的赋值变量,支持$_GET,$_SERVER等
VB6当中自定义过程和函数以及参数类型
VB多风格自定义的ToolTip气泡信息提示,VB多风格自定义的ToolTip气泡信息提示
ps6教程 如何创建自定义工作区 实战 swf 如何创建自定义工作区 实战
1.使用vue3+antv x6+tsx制作自定义流程图 2.实现自定义拖拉组件。 3.支持自定义拓展。
在iOS6下实现自定义UI控件效果,替换原生效果
自定义消息 更多内容见:vcshare.net和http://www.hedanwang.cn/bbs/
tOutlet.py是基于PySide6框架实现的自定义控件——插座控件。PySide6作为Qt for Python的官方绑定,提供了强大的GUI开发能力,使得开发者能够轻松创建出丰富、交互性强的桌面应用程序。 tOutlet.py插座控件作为一个...
VBA自定义函数. 6个简单而有用的VBA自定义函数.
vc6自定义控件大全源码大全 1.BrowseFolder :浏览选择文件夹控件 2.BtnST:图标按钮控件 3.ListCtrl:check列表控件 4.trview:check树状图控件 5.toolbar:工具栏控件 6.print: 打印浏览控件 7.checkbox:复选框...
stm32f103c8t6 自定义usb hid收发通讯
列举了VB6开发EXCEL自定义函数加载宏,这是一本不错的资源