1 . 什么是自定义标签
尽管JSP本身,以及第三方提供了很多标签库,但因为业务需要,我们有时还是需要自定义标签。因为JSP页面中不可以存在Java代码,所以我们需要自定义标签!
2 .标签的真身
其实我们现在应该可以了解了,真的是万物皆对象。JSP可以是一个对象,当然标签也可以是一个对象。其实在页面中使用的标签就是对一个对象的方法调用!
标签:
- 标签处理类:都有自己的标签处理类!所有标签处理类都必须去实现Tag或SimpleTag接口;
- TLD(Tag Library Description):一个TLD文件中可以部署多个标签!JSP会通过TLD文件找到标签! (webapps\examples\WEB-INF\jsp2,这里有模板)
3,SimpleTag
1) SimpleTag是什么
标签处理类必须实现JspTag接口,而JspTag接口有两个子接口:Tag和SimpleTag。更加确切的说:标签处理类必须实现Tag或SimpleTag接口。
JSP2.0之后,SUN提供了SimpleTag接口,通过SimpleTag接口来实现标签处理类要比Tag这种传统方式方便很多,所以现在我们可以大声与Tag说再见了。
SimpleTag接口内容如下:
void doTag():标签执行方法;
JspTag getParent():获取父标签;
void setParent(JspTag parent):设置父标签
void setJspContext(JspContext context):设置PageContext
void setJspBody(JspFragment jspBody):设置标签体对象;
4 .自定义标签方式一:实现SimpleTag接口的自定义标签
案例:定义一个Hello SimpleTag的简单标签
标签类的定义:
public class HelloTag implements SimpleTag {
private PageContext pageContext;
public void doTag() throws JspException, IOException {
pageContext.getOut().write("<p>Hello SimpleTag!</p>");
}
public void setJspContext(JspContext pc) {
this.pageContext = (PageContext) pc;
}
public void setParent(JspTag parent) {}
public JspTag getParent() {return null;}
public void setJspBody(JspFragment jspBody) {}
}
TLD文件的定义
注意: [把tld文件放到classes\META-INF\hello.tld路径]
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">
<tlib-version>1.0</tlib-version>
<short-name>kzkate</short-name>
<uri>http://www.kzkate.cn/kzkate-tags</uri>
<tag>
<name>hello</name>
<tag-class>cn.kzkate.simpletags.HelloTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
jsp中使用
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="kzkate" uri="http://www.kzkate.cn/kzkate-tags" %>
......
<body>
This is my JSP page. <br>
<kzkate:hello/>
</body>
5 .自定义标签方式二:继承SimpleTagSupport的自定义标签
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().write("<p>Hello SimpleTag!</p>");
}
}
6 .有标签体的标签
标签类
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
PageContext pc = (PageContext) this.getJspContext();
HttpServletRequest req = (HttpServletRequest) pc.getRequest();
String s = req.getParameter("exec");
if(s != null && s.endsWith("true")) {
JspFragment body = this.getJspBody()
JspWriter out = pc.getOut();
body.invoke(out);
}
}
}
TLD文件
<tag>
<name>hello</name>
<tag-class>cn.kzkate.simpletags.HelloTag</tag-class>
<body-content>scriptless</body-content>
</tag>
jsp中使用
<kzkate:hello>
<h1>哈哈哈~</h1>
</kzkate:hello>
body-content元素的可选值有:
empty:不能有标签体内容。
JSP:标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;但不建议使用Java代码段,SimpleTag已经不再支持使用JSP
scriptless:标签体内容不能是Java代码段,但可以是EL、JSTL等;
tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。
public class HelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
PageContext pc = (PageContext) this.getJspContext();
HttpServletRequest req = (HttpServletRequest) pc.getRequest();
String s = req.getParameter("exec");
if(s != null && s.endsWith("true")) {
JspFragment body = this.getJspBody();
JspWriter out = pc.getOut();
body.invoke(out);
}
}
}
<tag>
<name>hello</name>
<tag-class>cn.kzkate.simpletags.HelloTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<kzkate:hello>
<h1>哈哈哈~</h1>
</kzkate:hello>
7,不执行标签下面的页面内容
我们知道,在使用Tag接口来编写标签时,可以跳过标签下面的JSP页面内容。在SimpleTag中也是可以的,这需要在doTag()方法中抛出SkipPageException。
SkipPageException是JspException的子类,当doTag()方法抛出该异常时,JSP真身不会打印异常信息,而是跳转页面内容!
public class SkipTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().print("<h1>只能看到我!</h1>");
throw new SkipPageException();
}
}
<tag>
<name>skip</name>
<tag-class>cn.kzkate.simpletags.SkipTag</tag-class>
<body-content>empty</body-content>
</tag>
<kzkate:skip/>
<h1>看不见我!</h1>
8,带有属性的标签
- 在处理类中添加属性,以及getter/setter方法;
- 在TLD中部属相关属性。
public class DemoTag extends SimpleTagSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void doTag() throws JspException, IOException {
this.getJspContext().getOut().print("hello " + name);
}
}
<tag>
<name>demo</name>
<tag-class>cn.kzkate.simpletags.DemoTag</tag-class>
<body-content>empty</body-content>
<attribute>
//[tag>中可以有0~n个<attribute>元素,每个<attribute>表示一个属性。]
//[定属性名(必须给出<name>),当指定的属性为name时,那么标签处理类必须有setName()方法。getName()可以没
//有。因为Servlet会调用setName()传递值给标签处理类]
<name>name</name>
//[属性是否为必须的。默认值为false,表示属性不是必须的。]
<required>true</required>
//[属性是否可以是表达式。如EL表达式,以及<%=xxx%>。默认值为false,表示不能是表达式。]
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
<%
pageContext.setAttribute("name", "liSi");
String name = "wangWu";
%>
<kzkate:demo name="zhangSan"/><br/>
<kzkate:demo name="${name }"/><br/>
<%--[因为<rtexprvalue>为false,所以属性值为能否是动态表达式,所以${name}和<%=name%>都是非法的。]--%>
<kzkate:demo name="<%=name %>"/>
9,综合案例:自定义分页标签和时间格式化标签
分页标签类
public class PageTag extends SimpleTagSupport {
private int curPage;
private int pageSize;
private int total;
private String url;
private String className = "tres";
public void doTag() throws JspException, IOException {
JspWriter out = this.getJspContext().getOut();
StringBuffer str = new StringBuffer();
str.append("<div align='center' class='"+className+"'>");
if(curPage==1){
str.append("首页 上一页");
}else{
str.append("<a href='"+url+"&curPage=1'>首页 </a>");
str.append("<a href='"+url+"&curPage="+(curPage-1)+"'>上一页</a>");
}
str.append("当前第"+curPage+"页共"+total+"页");
if(curPage!=total){
str.append("<a href='"+url+"&curPage="+(curPage+1)+"'>下一页 </a>");
str.append("<a href='"+url+"&curPage="+total+"'>末页</a>");
}else{
str.append("下一页 末页");
}
str.append("<form action='listAction.do?method=list' method='post'>");
str.append("<input size='3' name='curPage'>");
str.append("<input type='submit' value='Go'>");
str.append("</form>");
str.append("</div>");
out.println(str);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
日期标签类
public class DateTag extends SimpleTagSupport {
private String parttern = "yyyy-MM-dd E";
private Date value ;
@Override
public void doTag() throws JspException, IOException {
JspWriter out = this.getJspContext().getOut();
SimpleDateFormat sf = new SimpleDateFormat(parttern);
String str = sf.format(value);
out.println(str);
}
}
分页标签和日期标签TLD
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<description>这是我们自定义的标签</description>
<display-name>My core</display-name>
<tlib-version>1.0</tlib-version>
<short-name>my</short-name>
<uri>/mytag</uri>
<tag>
<description>
这是一个日期标签
</description>
<name>date</name>
<tag-class>com.cshr.tag.DateTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>这个属性用来设置日期的格试</description>
<name>parttern</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>这个属性用来设置日期的值</description>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<description>
这是一个分页标签
</description>
<name>page</name>
<tag-class>com.cshr.tag.PageTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>这个属性用来设置当前页数</description>
<name>curPage</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>这个属性用来设置每页显示多少条数据</description>
<name>pageSize</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>这个属性用来设置总页数</description>
<name>total</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>这个属性用来设置请求的地址</description>
<name>url</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>这个属性用来设置CSS</description>
<name>className</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
jsp中测试
......
<%@ taglib uri="/mytag" prefix="my" %>
<%@ taglib uri="/mytag" prefix="my" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%
Date d = new Date(2012-1900,11,12);
request.setAttribute("d",d);
%>
.......
<my:date value="${d}" parttern="yyyy/MM/dd"/>
<fmt:formatDate value="${d}" pattern="yyyy/MM/dd" />
<my:page pageSize="${pageSize}" url="listAction.action?method=list" total="${total}" curPage="${curPage}" className="badoo"/>