JSP自定义标签技术的分析与应用 ----Custom Tag 的分析与应用 周强 2009-4-9
Custom Tag 的概念和特点 Custom Tag 由用户自己定义并可以被其它JSP 使用。 在 JSP 中使用的 Custom Tag 会被转换成Servlet 程序。 Custom Tag 的优点是取代了JSP中的Java程序并且可以重复使用。
tag library JSP 中通过使用 taglib directive 定义所使用的标记库。 一个标记库是一组 custom tag 的集合,它在 Web 程序中由一个标记库描述文件(TLD) 定义。 <%@ taglib uri=“/WEB-INF/icsampes.tld” prefix=“ics” %>,其中 uri 属性指定了一个在 /WEB-INF 目录下面的 tld 文件,这个前缀为 ics。在 JSP 中使用属于这个标记库的 Custom Tag 都以这个前缀打头(ics:XXXX)。
Custom Tag 的格式 一个 Custom Tag 包括起始标记、终止标记和标记体。其中起始标记可以设置属性,标记体是可选的。格式如下: <ics:tagname> tagbody </ics:tagname>
Custom Tag 的格式 分为 4 类: 1、简单标记:最简单的 Custom Tag 标记,起始标记没有设置参数,没有标记体。 2、带属性标记:起始标记可以包括属性,这些属性可以被 JSP 赋值并用来在使用 Custom Tag 时提供设置信息。使用这种 Custom Tag,其属性的名称和类型需要在 tld 文件中指明。
Custom Tag 的格式 3、带标记体标记:在 Custom Tag 的起始标记和终止标记之间的为标记体(body)。Body 的内容可以是 JSP 中的标准标记、Html、脚本语言或其它Custom Tag。 4、可被Script使用的标记:Custom Tag 可以采用特定的格式定义对象(比如数据资源、EJB等),这些对象可以在标记后面的scriptlet 中使用。要实现这个功能,需要在一个Custom Tag 中使用 id 和 type 属性。 注:先讲 1 和 2。
Custom Tag 开发方法 1、采用特定的 API 编写实现标记处理的程序; 标记处理程序一般放在 /WEB-INF/classes目录下面,或者作为 jar 文件放在 /WEB-INF/lib 目录下面。 2、建立一个 tag library descriptor(TLD) 文件用来描述 Custom Tag。 TLD文件放在 /WEB-INF 下面某个指定目录内。
标记处理程序 标记处理程序,需要实现 tag handler 接口。 在 JSP 1.2 中定义了Tag、BodyTag、Iteration 接口。Web 容器会通过调用这些接口的特定方法调用Custom Tag 程序。 另外,JSP 提供了用来实现 tag handler 的方便类 TagSupport、BodyTagSupport 。
标记处理程序 一个 tag handler 可以通过 javax.servlet.jsp.PageContext 对象和 JSP 进行联系。在 tag handler 中有 setPageContext 设定其 PageContext。在运行中,tag handler 通过 PageContext 可以获得 JSP 的隐含对象(如 request、session、application等),并通过 setAttribute 和 getAttribute 方法读取和修改隐含对象的属性。
标记处理程序 如果 Custom Tag 套用另一个 Custom Tag,被套用的Custom Tag 的 tag handler 程序可以使用 getParent() 方法得到包含它的 tag 对象。
简单 Custom Tag-- tag handler 程序 public class TimeTag implements Tag { private PageContext pageContext; private Tag parent; private java.util.Calendar calendar; public TimeTag() { super(); } public int doStartTag() throws JspException { try { calendar = Calendar.getInstance(); pageContext.getOut().print( DateFormat.getDateInstance().format(calendar.getTime())+" "+ DateFormat.getTimeInstance().format(calendar.getTime()) ); } catch (IOException tage) { throw new JspException("TimeTag Error: "+ tage.getMessage()); return SKIP_BODY;
简单 Custom Tag-- tag handler 程序 public int doEndTag() throws JspException { return SKIP_PAGE; } public void release() { public void setPageContext(PageContext pageContext) { this.pageContext = pageContext; public void setParent(Tag parent) { this.parent = parent; public Tag getParent() { return parent;
简单 Custom Tag-- tag handler 程序 程序使用了 Tag 接口,它主要实现了 doStartTag 方法和 doEndTag 方法。 当 Web 容器运行这个标记时,它会在读到标记起 始位置时调用 doStartTag方法。 doStartTag方法返 回一个SKIP_BODY值表明不用处理标记体。 当 Web 容器遇到标记的结尾时,调用其 doEndTag方法。doEndTag方法返回EVAL_PAGE 或 SKIP_PAGE,前者表示接着处理标记后面的 JSP内容,后者表示忽略标记后面的 JSP 内容。
简单 Custom Tag--TLD <tag> <name>time</name> <tag- class>jwadbook.taglib.TimeTag</tag-class> <body-content>empty</body-content> </tag>
<ics:time/> 示例 timetag.jsp <%@ taglib uri="http://www.icconcept.com/taglibs/sampleTag" prefix="ics" %> <HTML> <HEAD> <TITLE>TimeTagJSP</TITLE> </HEAD> <BODY BGCOLOR=white> <CENTER> <FONT COLOR='#009999' SIZE='4' face='Arial'> <STRONG>Using Custom JSP Tag to List Current Time </STRONG> </FONT> </CENTER> <HR/> <CENTER><H3> Current Time is: <ics:time/> </H3></CENTER> </BODY> </HTML>
使用简单Custom Tag 的timetag.jsp运行效果
带属性 Custom Tag 对于带属性的标记,在 tag handler 程序中需要对标记的每个属性进行定义。 标记 <ics:wordcount inputname=“input” warnEmpty=“true” /> 有两个属性。在WorldCountTag.java 中有 setInputname方法和 setWarnEmpty 方法。Web 容器会在处理标记时,对这些属性进行赋值。 TagSupport 类已经定义了名为 id 的属性,如果标记的 tag handler 程序继承 TagSupport 类就不需要声明 setId 方法。
带属性 Custom Tag—tag handler 程序 public class WordCount extends TagSupport { String inputname; boolean warnEmpty; String inputword; public void setInputname(String _inputname) { this.inputname = _inputname; } public void setWarnEmpty(boolean _warnempty) { this.warnEmpty = _warnempty;
带属性 Custom Tag—tag handler 程序 public int doEndTag() throws JspException { JspWriter out = pageContext.getOut(); inputword = pageContext.getRequest().getParameter(inputname); try { If ((inputword==null)&&(warnEmpty==true)) { out.println("<FONT color = 'red'> None Input Found! Input Again </FONT>"); } else if (inputword==null) { out.println("0"); } else { StringTokenizer st = new StringTokenizer(inputword); int wordnumber = st.countTokens(); out.println(wordnumber); } } catch (IOException ioe) { System.out.println ("Error: " + ioe.getMessage()); return EVAL_PAGE;
带属性 Custom Tag—tag handler 程序 <ics:wordcount> 标记可以计算表单中输入的单词数目。 “inputname” 属性定义了一个输入表单请求变量名称, “warnEmpty” 规定了当用户没有输入文字时,是否给出警告。 这个 tag handler 程序在 doEndTag 方法中使用 request.getParameter 得到特定的请求参数,然后将这个字符串内的单词数目计算并显示出来。
带属性 Custom Tag—TLD 在<tag> 中有 <attribute> 元素, <attribute> 中的<name> 指出了属性的名称,<required> 表明属性是否必须被设定(默认为否),<rtextprvalue> 设定是否 Web 容器要计算属性表达式的值(默认为否),<type>代表了属性的类型(默认为String)。 <tag> <name>wordcount</name> <tag-class>jwadbook.taglib.WordCount</tag-class> <body-content>empty</body-content> <attribute> <name>inputname</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <name>warnEmpty</name> <rtexprvalue>true</rtexprvalue> <type>boolean</type> </tag>
带属性 Custom Tag—wordcounttag.jsp <%@ taglib uri="http://www.icconcept.com/taglibs/sampleTag" prefix="ics" %> … <form action="wordcounttag.jsp" method="post"> <TEXTAREA rows="10" cols="58" name="input">Enter A Brief Description Here</TEXTAREA> <BR></BR> Your have entered <ics:wordcount inputname="input" warnEmpty="true" /> words in the above text area. <INPUT type="submit" name="Submit" value="Count Words"></FORM> </form>
wordcounttag.jsp 输入界面
wordcounttag.jsp 输出统计结果
谢谢!