使用的 uri 与标签库的对应关系。 将上面代 码加到 web.xml 文件的
元素下。 4. 在 JSP 文件中使用标签 最后,编写使用定制标签的 JSP 文件。 <%@ page contentType=”text/html” %> <%@ taglib uri=”/mytaglib” prefix=”test”> Using Custom Tag Hello Tag Example
在 JSP 页面要使用定制标签,需要通过 taglib 指令声明标签库的 uri 和前缀,如下所示: <%@ taglib uri=”/mytaglib” prefix=”test”> 这里的 uri 为 web.xml 文件中指定的 uri,前缀 test 表示在使用定制标签时需要使用 test: 开头。使用标签使用下面的形式: 其中,hello 为 TLD 中元素中元素定义的标签名称。标签使用的格式一般 包括其始标签和结束标签,中间可能还有标签体,如: … 由于该标签没有标签体, 因此也不需要使用结束标签。 JSP 页面的运行结果如图所示。 该
图 hello.jsp 的运行结果
二、创建标签处理类 上节中我们给出了开发和使用定制标签的完整过程。其中开发标签处理类是最重要的。 开发定制标签需要使用 Tag 扩展 API,这些 API 是由 javax.servlet.jsp.tagext 包中的接口和类 组成的。 任何标签处理类必须实现某一个 Tag 接口或 Tag 类。 常用的接口有 JspTag、 Tag、 SimpleTag、 IterationTag、 BodyTag, 常用的类有 TagSupport、 SimpleTagSupport、BodyTagSupport。这些接口和类的层次关系如图 1 所示。
JspTag
Tag
SimpleTag Simpl
eTagSupport
IterationTag
TagSupport
BodyTag
BodyTagSupport
图 1 标签扩展 API 的接口和类的层次关系
Tag 与 SimpleTag 接口都是 JspTag 的子接口,它们定义了类似的方法。Tag 接口是传统 的实现自定义标签的基接口, SimpleTag 是 JSP 2.0 增加的一个接口, 主要用于定义简单的标 签处理程序。 Tag 接口定义的方法有: public int doStartTag() throws JspException public int doEndTag() throws JspException public void setParent(Tag t) public Tag getParent() public setPageContext(PageContext pc) public release() 这些方法是定制标签的生命周期方法,下面按照方法被调用的顺序说明。 setPageContext()方法是标签的生命周期中第一个被调用的方法。JSP 容器在调用该方法 时将标签所在的 JSP 页面的隐含对象 pageContext 传递给该方法。一般在该方法中将 pageContext 保存在一个私有变量中以备以后使用。 setParent()与 getPatent()方法主要用于在嵌套的标签中。 如果标签嵌套, 外层标签叫做父 标签(parent tag),内层标签叫做子标签(child tag)。
带属性的标签: 许多 HTML 标签可以带属性,定制标签也可以带属性。如果要使一个标签接受属性, 我们必须在标签类中声明一个实例变量存放属性值, 同时如果标签属性可以缺省, 还要为标 签属性提供一个缺省值。另外在标签类中还要定义属性设置方法(setter)。 package demo;
import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class GreetTag implements Tag { private PageContext pageContext; private Tag parentTag; private String user; public void setUser(String user){ this.user = user; } public void setPageContext(PageContext pageContext){ this.pageContext = pageContext; } public void setParent(Tag parentTag){ this.parentTag = parentTag; } public Tag getParent(){ return this.parentTag; } public int doStartTag() throws JspException{ JspWriter out = pageContext.getOut(); try{ if(user==null) out.print("Hello! User"); else out.print("Hello "+user+" !"); }catch(Exception e){} return SKIP_BODY; } public int doEndTag() throws JspException{ return EVAL_PAGE; } public void release(){ } } greet
demo.GreetTag empty user false true TLD 文件中的元素是元素的子元素。元素的定义如下: 只有元素是必须的且只能出现一次,其他元素是可选的。 <%@ taglib uri="/demo" prefix="test" %>
Tag With Attribute Example
IterationTag 接口扩展了 Tag 接口。实现该接口的标签类可以多次包含标签体。该接口
比 Tag 接 口 多 定 义 了 一 个 doAfterBody() 方 法 和 一 个 EVAL_BODY_AGAIN 常 量 。 doAfterBody()方法的声明格式为: public int doAfterBody() throws JspException 在每次计算标签体后重新调用 doAfterBody()方法,决定是否重新计算标签体。如果方 法返回值为 Iteration.EVAL_BODY_AGAIN,将重新计算标签体,若返回 Tag.SKIP_BODY, 将跳过标签体,直接执行 doEndTag()方法。 package demo; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.*; public class LoopTag implements IterationTag { private PageContext pageContext; private Tag parentTag; private int count = 0; public void setCount(int count){ this.count = count; } public void setPageContext(PageContext pageContext){ this.pageContext = pageContext;
} public void setParent(Tag parentTag){ this.parentTag = parentTag; } public Tag getParent(){ return this.parentTag; } public int doStartTag() throws JspException{ if(count>0) return