浅谈JSP自定义标签实现过程
(一) 没有正文的JSP自定义标签实现
(1):定义JSP自定义标签处理类
- import?java.io.IOException; ?
- import?java.util.Date; ?
- import?javax.servlet.http.HttpServletRequest; ?
- import?javax.servlet.jsp.JspException; ?
- import?javax.servlet.jsp.JspWriter; ?
- import?javax.servlet.jsp.tagext.Tag; ?
- import?javax.servlet.jsp.tagext.TagSupport; ?
- //无正文标签类继承的是TagSupport类?实现的接口是Tag。?如果有正文的标签类继承的是BodyTagSupport类?实现的接口是BodyTag ?
- public?class?DateTagNoBody?extends?TagSupport?{ ?
- ?@Override ?
- ?public?int?doStartTag()?throws?JspException?{ ?
- ??HttpServletRequest?request; ?
- ??//?是TagSupport类中定义的一个属性,它是javax.servlet.jsp.PageContext的对象 ?
- ??request?=?(HttpServletRequest)?pageContext.getRequest(); ?
- ??java.text.SimpleDateFormat?formater?=?new?java.text.SimpleDateFormat("yyyy-MM-dd"); ?
- ??String?date?=?formater.format(new?Date()); ?
- ??JspWriter?out?=?pageContext.getOut(); ?
- ??try?{ ?
- ???out.print(date); ?
- ??}?catch?(IOException?e)?{ ?
- ???e.printStackTrace(); ?
- ??} ?
- ??//?doStartTag()?方法返回?SKIP_BODY?。当然其原因是我们的简单日期标记没有正文。 ?
- ??return?Tag.SKIP_BODY; ?
- ?} ?
- }?
(2) 定义tld文件
- <?xml?version="1.0"?encoding="UTF-8"?>?
- <taglib>?
- ???<tlibversion>1.0</tlibversion>?
- ???<jspversion>1.1</jspversion>?
- ??<tag>?
- ????<name>displayDate</name>?
- ????<tagclass>cn.com.chenlly.tag.DateTagNoBody</tagclass>?
- ????<bodycontent>empty</bodycontent>?
- ??</tag>????????? ?
- </taglib>?
(3) JSP页面动态引用
- <%@?page?language="java"?pageEncoding="UTF-8"%>?
- <%@?taglib?uri="/WEB-INF/datetag.tld"?prefix="c"%>?
- <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN">?
- <html>?
- ??<head>?
- ??</head>?
- ??<body>?
- ???<c:displayDate/>?
- ??</body>?
- </html>?
注意:动态引用和静态引用的区别。
为了进行静态引用,首先必须将下面的项加入到web.xml 文件中:
- <?xml?version="1.0"?encoding="ISO-8859-1"??>?
- <Web-app>??????? ?
- ???<taglib>?
- ??????<taglib-uri>myTags</taglib-uri>?
- ??????<taglib-location>/WEB-INF/lib/DateTagLib.tld</taglib-location>?
- ???</taglib>??????????????? ?
- </Web-app>?
然后,将JSP 声明加入到所有需要使用自定义标记库的页面中:
- <%@?taglib?uri="myTags"?prefix="c"?%>?
指定的uri 属性与在web.xml 文件中指定的taglib-uri 值相匹配。
在进行标记库的静态引用时,JSP 声明必须查询 web.xml 文件以执行库查询。这意味着如果移动或者重命名了库,或者希望在 web.xml 文件中加入更多的库,就必须停止服务器、更新 web.xml 文件、然后重新启动服务器。动态方法让JSP页直接指向 TLD 位置,因而是在解释JSP页面时进行处理。
(二)? 没有正文的但带有属性的JSP自定义标签标签实现
(1):定义JSP自定义标签处理类
- import?java.io.IOException; ?
- import?java.util.Date; ?
- import?javax.servlet.http.HttpServletRequest; ?
- import?javax.servlet.jsp.JspException; ?
- import?javax.servlet.jsp.JspWriter; ?
- import?javax.servlet.jsp.tagext.Tag; ?
- import?javax.servlet.jsp.tagext.TagSupport; ?
- //无正文标签类继承的是TagSupport类?实现的接口是Tag。?如果有正文的标签类继承的是BodyTagSupport类?实现的接口是BodyTag ?
- public?class?DateTagNoBody?extends?TagSupport?{ ?
- ? ?
- ?private?String?pattern; ?
- ?@Override ?
- ?public?int?doStartTag()?throws?JspException?{ ?
- ??HttpServletRequest?request; ?
- ??//?是TagSupport类中定义的一个属性,它是javax.servlet.jsp.PageContext的对象 ?
- ??request?=?(HttpServletRequest)?pageContext.getRequest(); ?
- ??java.text.SimpleDateFormat?formater?=?new?java.text.SimpleDateFormat(pattern); ?
- ??String?date?=?formater.format(new?Date()); ?
- ??JspWriter?out?=?pageContext.getOut(); ?
- ??try?{ ?
- ???out.print(date); ?
- ??}?catch?(IOException?e)?{ ?
- ???e.printStackTrace(); ?
- ??} ?
- ??//?doStartTag()?方法返回?SKIP_BODY?。当然其原因是我们的简单日期标记没有正文。 ?
- ??return?Tag.SKIP_BODY; ?
- ?} ?
- ? ?
- ?//必须实现setXX()方法 ?
- ?public?void?setPattern(String?pattern){ ?
- ??this.pattern?=?pattern; ?
- ?} ?
- }?
(2) 定义tld文件
- <?xml?version="1.0"?encoding="UTF-8"?> ?
- <taglib> ?
- ???<tlibversion>1.0</tlibversion> ?
- ???<jspversion>1.1</jspversion> ?
- ??<tag> ?
- ????<name>displayDate</name> ?
- ????<tagclass>cn.com.chenlly.tag.DateTagNoBody</tagclass> ?
- ????<bodycontent>empty</bodycontent> ?
- ????<!--?定义属性?--> ?
- ????<attribute> ?
- ???????<name>pattern</name>?<!--?属性名字?--> ?
- ???????<type>String</type>??<!--?属性类型?--> ?
- ???????<requried>false</requried>?<!--?是否必须?--> ?
- ???????<rtexprvale>false</rtexprvale>?<!--?表示是否可以使用JSP表达式??--> ?
- ??</attribute> ?
- ??</tag> ?
- </taglib>?
(3)JSP页面动态引用
- <%@?page?language="java"?pageEncoding="UTF-8"%>?
- <%@?taglib?uri="/WEB-INF/datetag.tld"?prefix="c"%>?
- <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN">?
- <html>?
- ??<head>?
- ??</head>?
- ??<body>?
- ???<c:displayDate?pattern='yyyy-MM-dd'/>?
- ???</br>?
- ???<c:displayDate?pattern='MM/dd?HH:mm:ss'/>?
- ??</body>?
- </html>?
(三) 有正文的且带有属性的JSP自定义标签实现
(1):定义JSP自定义标签处理类
- import?java.io.IOException; ?
- import?java.util.Date; ?
- import?javax.servlet.http.HttpServletRequest; ?
- import?javax.servlet.jsp.JspException; ?
- import?javax.servlet.jsp.JspWriter; ?
- import?javax.servlet.jsp.tagext.BodyContent; ?
- import?javax.servlet.jsp.tagext.BodyTagSupport; ?
- ?
- public?class?BodyTag?extends?BodyTagSupport?{ ?
- ? ?
- ?private?int?count; ?
- ?
- ?private?HttpServletRequest?reqeust; ?
- ?
- ?private?JspWriter?out; ?
- ?
- ? ?
- ?public?void?init()?{ ?
- ??reqeust?=?(HttpServletRequest)?pageContext.getRequest(); ?
- ??out?=?pageContext.getOut(); ?
- ?} ?
- ?
- ?@Override ?
- ?public?int?doStartTag()?throws?JspException?{ ?
- ??init(); ?
- ??return?this.EVAL_BODY_INCLUDE; ?
- ?} ?
- ? ?
- ?//设置当前标签体 ?
- ?@Override ?
- ?public?void?setBodyContent(BodyContent?bodyContent)?{ ?
- ??this.bodyContent?=?bodyContent; ?
- ??System.out.println("setBodyContent...");? ?
- ?} ?
- ? ?
- ?
- //需要初始化bodyContent ?
- ?@Override ?
- ?public?void?doInitBody()?throws?JspException?{ ?
- ??System.out.println("init....."); ?
- ?}? ?
- ?
- ?
- ?@Override ?
- ?public?int?doAfterBody()?throws?JspException?{ ?
- ??if?(count?>=?1)?{ ?
- ???try?{ ?
- ????out.println(count); ?
- ????out.println("<Br>"); ?
- ???}?catch?(IOException?e)?{ ?
- ????e.printStackTrace(); ?
- ???} ?
- ???count?--; ?
- ???return?this.EVAL_BODY_AGAIN; ?
- ??}?else?{ ?
- ???return?this.SKIP_BODY; ?
- ??} ?
- ?} ?
- ?
- ?@Override ?
- ?public?int?doEndTag()?throws?JspException?{ ?
- ??java.text.SimpleDateFormat?formater?=?new?java.text.SimpleDateFormat( ?
- ????"yyyy-MM-dd"); ?
- ??String?date?=?formater.format(new?Date()); ?
- ??try?{ ?
- ???out.print(date); ?
- ??}?catch?(IOException?e)?{ ?
- ???e.printStackTrace(); ?
- ??} ?
- ??return?this.EVAL_PAGE; ?
- ?} ?
- ?
- ?//?必须实现setXX()方法 ?
- ?public?void?setCount(int?count)?{ ?
- ??this.count?=?count; ?
- ?} ?
- }?
(2) 定义tld文件
- <?xml?version="1.0"?encoding="UTF-8"?>?
- <taglib>?
- ???<tlibversion>1.0</tlibversion>?
- ???<jspversion>1.1</jspversion>?
- ??<tag>?
- ????<name>iterator</name>?
- ????<tagclass>cn.com.chenlly.tag.BodyTag</tagclass>?
- ????<bodycontent>jsp</bodycontent>?
- ????<!--?定义属性?-->?
- ????<attribute>?
- ???????<name>count</name>?<!--?属性名字?-->?
- ???????<type>int</type>??<!--?属性类型?-->?
- ???????<requried>false</requried>?<!--?是否必须?-->?
- ???????<rtexprvale>false</rtexprvale>?<!--?表示是否可以使用JSP表达式??-->?
- ??</attribute>?
- ??</tag>?
- </taglib>?
(3) jsp 页面动态引用
- <%@?page?language="java"?pageEncoding="UTF-8"%>?
- <%@?taglib?uri="/WEB-INF/bodytag.tld"?prefix="c"%>?
- <!DOCTYPE?HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Transitional//EN">?
- <html>?
- ??<head>?
- ??</head>?
- ??<body>?
- ???<c:iterator?count="10">HelloWorld!</c:iterator>?
- ???<% ?
- ????out.println("Bye?Bye"); ?
- ????%>?
- ??</body>?
- </html>?
效果图:

执行顺序
doStartTag()->setBodyContent()->doInitBody()->doAfterTag()->doEndTag()
如果doStartTag()返回的是EVAL_BODY_INCLUDE执行doAfterTag()方法,
如果它返回SKIP_BODY就执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,如果在计算BodyContent时需要进行一些初始化工作,
则在doInitBody()方法中完成。标签体内容执行完后,会调用doAfterBody()方法
在doAfterTag()方法中返回EVAL_BODY_AGAIN来重复执行doAfterTag()方法
返回SKIP_BODY值则执行doEndTag()方法。
在doEndTag()方法中返回EVAL_PAGE值,则执行此标签的后的其它代码,
返回SKIP_PAGE则不执行此页面的其它代码。