java EE开发之Servlet第十二课:简单自定标签

来源:互联网 发布:网络release是什么意思 编辑:程序博客网 时间:2024/06/01 09:16

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();            //[执行标签体。如果使用null来调用invoke()方法,那么默认是使用当前页面的输出流!即使用null与当前的效果相同。]            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();            //[执行标签体。如果使用null来调用invoke()方法,那么默认是使用当前页面的输出流!即使用null与当前的效果相同。]            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;    }    //[Servlet在执行标签时会先调用setName()方法把值传递给处理类,然后再调用doTag()方法。]    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("首页&nbsp;&nbsp;上一页");        }else{            str.append("<a href='"+url+"&curPage=1'>首页&nbsp;&nbsp;</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)+"'>下一页&nbsp;&nbsp;</a>");            str.append("<a href='"+url+"&curPage="+total+"'>末页</a>");        }else{            str.append("下一页&nbsp;&nbsp;末页");        }        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>");        /*str.append("<script>");        str.append("function validate(){");        str.append("}");        str.append("</script>");*/        out.println(str);       }    //省略get/set方法}

日期标签类

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);            //Date d = new Date();            String str = sf.format(value);            out.println(str);    }    //省略get/set方法}

分页标签和日期标签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>

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"/>
原创粉丝点击