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

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"/>
发布了26 篇原创文章 · 获赞 13 · 访问量 7021

猜你喜欢

转载自blog.csdn.net/womeia331416/article/details/78053953