概述 |
<nobr>第 1 页(共4 页)</nobr> |
有时,可能希望根据一些特定于应用程序的显示逻辑有条件地调用方法的正文。可以通过从 doStartTag()
返回一个值做到这一点:SKIP_BODY
跳过标签的正文,而 EVAL_BODY
对它进行判断。
迭代标签需要实现 IterationTag
接口。容器调用 doAfterBody()
方法以确定是否要重新判断正文。这个方法返回 EVAL_BODY_AGAIN
时表明容器应当继续对正文进行判断。doAfterBody()
方法返回 SKIP_BODY
时表明迭代操作已经结束。TagSupport 类和 BodyTagSupport
类都实现了 IterationTag
接口。
回到 map 主题,在下面几小节我们将创建一个自定义标签处理程序,它迭代一组 map 并打印出它们的值。
控制流程序示例 |
<nobr>第 2 页(共4 页)</nobr> |
在开始实现自定义标签处理程序之前,让我们看看示例标签是如何使用的。首先,用上面的例子中的 map
标签定义两个 map:
<%@taglib uri="map" prefix="map"%> <map:map id="employee1"> { firstName=Jennifer, lastName=Wirth, age=33 } </map:map> <map:map id="employee2"> { firstName=Kiley, lastName=McKeon, age=27 } </map:map>
然后,创建一个名为 list
的集合,加入上面定义的两个 map (employee1
和 employee2
)。
<jsp:usebean id="list" class="java.util.ArrayList"></jsp:usebean> <% list.add(employee1); list.add(employee2); %>
下面展示了如何用自定义标签迭代这个集合:
<map:printmaps name="list"> </map:printmaps>First Name | ${firstName} |
Last Name | ${lastName} |
Age | ${age} |
map:printMaps
标签迭代 list
集合。 在每一次迭代时,它使用其正文,通过搜索以 ${key}
开始的子字符,在 map 中搜索当前迭代的键。它从字符串 ${}
中解析出键,并用从 map 得到的这个键的值(即 map.get(key)
)替换它。
实现 doStartTag() 方法 |
<nobr>第 3 页(共4 页)</nobr> |
doStartTag()
方法从范围中抓取集合,然后从集合中抓取迭代器。 如果迭代器中没有任何项(iter.hasNext()
),那么 doStartTag()
方法就返回 SKIP_BODY
,从而实现了逻辑 if
。在这种情况下,这个 if
等同于“如果集合为空,则跳过正文判断”。 然后迭代器从集合中抓取第一个 map。
public class MapPrintMapsTag extends BodyTagSupport { private String name; private Iterator iter; private Map map; private String scope; public int doStartTag() throws JspException { Collection collection = null; /* Grab the collection out of scope using the scope attribute. */ if (scope == null){ collection = (Collection) pageContext.findAttribute(name); }else if("page".equalsIgnoreCase(scope)){ collection = (Collection) pageContext.getAttribute(name); }else if("request".equalsIgnoreCase(scope)){ collection = (Collection) pageContext.getRequest().getAttribute(name); }else if("session".equalsIgnoreCase(scope)){ collection = (Collection) pageContext.getSession().getAttribute(name); }else if("application".equalsIgnoreCase(scope)){ collection = (Collection) pageContext.getServletContext().getAttribute(name); } /* Get the iterator from the collection. */ iter = collection.iterator(); /* If the collection is empty skip the body evaluation. */ if (iter.hasNext()==false) return SKIP_BODY; /* Grab the first map out of the collection. */ map = (Map)iter.next(); return EVAL_BODY_BUFFERED; }
实现 doAfterBody() 方法 | <nobr>第 4 页(共4 页)</nobr> |
doAfterBody()
通过在没有可迭代的项时返回 SKIP_BODY
实现了迭代。如果还有项,那么它就返回 EVAL_BODY_AGAIN
。只要 doAfterBody()
返回 EVAL_BODY_AGAIN
,容器就会继续对正文进行判断,如下所示:
public int doAfterBody() throws JspException { /** Process body */ ... /** Write the processed buffer to the previous out */ ... if (iter.hasNext() == false) { return SKIP_BODY; } else { map = (Map) iter.next(); return EVAL_BODY_AGAIN; } }
doAfterBody()
方法用 getBodyContent()
抓取正文,然后用正文内容的 getString()
方法得到字符串形式的内容。 下一步它清除正文内容缓冲区,用 StringTokenizer
查找以 ${
开始的字符串。 它还创建一个名为 buffer
的 StringBuffer
。 当它迭代 tokenizer 中的字符串时,将它们附加到缓冲区中。
如果 tokenizer 中的字符串以 ${
, doAfterBody()
开始,那么它就从字符串中提取键,并用这个键在 map 中查找值。它调用值对象的 toString()
方法将 map 中的值转换为字符串,并将结果附加到缓冲区中。下面的清单展示了这个过程是如何进行的。
/** Process body */ /* Get and clear the body */ BodyContent body = this.getBodyContent(); String content = body.getString(); body.clearBody(); /* Process the body with a String tokenizer */ StringTokenizer token = new StringTokenizer(content); /* Create an output buffer of the processed body */ StringBuffer buffer = new StringBuffer(content.length() * 2); /* Iterate over the strings from the tokenizer and put them into the output buffer. */ while (token.hasMoreTokens()) { String tok = token.nextToken(); /* See if the String contains the special substring "${" */ if (tok.startsWith("${")) { /* Parse the key out of the string */ String key = tok.substring(2, tok.length() - 1); /* Use the key to look up the object in the map */ Object value = (String) map.get(key); String svalue = tok; /* If the value is not null, get the value's string representation */ if (value != null) { svalue = value.toString(); } /* Add the string representation of the value to the output buffer */ buffer.append(svalue + " "); } else { buffer.append(tok + " "); } }
doAfterBody()
方法在构建了输出缓冲区后,就将它输出到前面的 out
中,如下所示:
try { this.getPreviousOut().print(buffer.toString()); } catch (IOException e) { throw new JspException(e); }
这样,每一次迭代都处理正文并将它输出到前面的 out
中。如果前面的 out
是根 JspWriter
,那么它就会写到浏览器中。
结束语 |
<nobr>第 1 页(共3 页)</nobr> |
学 完本教程,您对自定义标签有了更深入的理解。如果您学完了本教程,即便是刚接触自定义标签,也应当可以开始在正在开发的项目中使用这种强大的工具了。您将 再也无法忍受在 JSP 页散布的那些难以维护和和不可重用的普通 Java scriptlet 了。即使不准备创建自已的自定义标签,本教程也会帮助您理解在由其他开发人员编写的代码中遇到的自定义标签。
参考资料 |
<nobr>第 2 页(共3 页)</nobr> |
分享到:
相关推荐
JSP自定义标签JSP自定义标签JSP自定义标签JSP自定义标签JSP自定义标签JSP自定义标签
jsp自定义标签jsp自定义标签jsp自定义标签
本人自行研究JSP自定义标签的学习笔记 目录如下: 目录 一、概述 1 1.1 使用简单标签机制 2 1.2 使用标签文件 3 二 、自定义标签简介 3 2.1 自定义标签概念 3 2.2 标签相关概念 3 2.3 如何创建自定义标签 3 三、自...
jsp自定义标签jsp自定义标签jsp自定义标签jsp自定义标签
jsp 自定义标签 一个简单的自定义标签实现
使用jsp自定义标签的功能实现权限的控制。(如果用户没有某个模块的删除权限,就不现实这个删除按钮) 在整个项目中所有的页面都可以引入自定义的标签去做到权限的控制。 自定义标签文件 删除 可以控制页面中的每...
在网上学习jsp自定义标签的时候, 出现了异常, 在网上寻找了好久, 都没有找到合适的答案, 自己通过摸索最后成功, 分享给大家, 希望能够帮助到你, 自定义标签不能放在java Project中, 只能在java web Project中才可以.
java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp...
创建JSP自定义标签.doc 创建JSP自定义标签.doc 创建JSP自定义标签.doc
JSP自定义标签。在自定义标签的起始和结束标签之间的部分为标签体(Body)。 标签处理程序类:定义标签的行为,并在JSP引擎遇到自定义标签时调用执行。 标签库描述符(TLD)文件:描述标签库的XML文档,向JSP引擎...
JSP自定义Table标签demo JSP自定义Table标签demo JSP自定义Table标签demo
jsp、jstl自定义标签实现的分页,实现的还是比较好的,没有在request、session等范围保存过数据,在pageContext范围内保存过集合的数据, 实现的方法还是比较简单的,适用性还是比较广的,我是实在是没分了,平时也...
jsp自定义迭代标签 jsp自定义迭代标签
jsp自定义标签库实现数据列表显示,包括代码,文档,希望对大家有帮助.
jsp自定义嵌套标签 自定义嵌套标签的定义和使用
是用jsp自定义标签编写的一个非常不错的分页,扩展性非常不错,不依赖于数据库。