JSP第六篇【自定义标签之传统标签】(修订版)

 
 

前言

只有光头才能变强。

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y

为什么要使用自定义标签?

JSTL标签库只提供了简单的输出等功能,没有实现任何的HTML代码封装,并且某些复杂类型转换,或者逻辑处理的时候,JSTL标签库完成不了,需要自定义标签!

编写自定义标签的步骤:

  1. 编写一个实现Tag接口的Java类【标签处理器类】

  2. 在WEB-INF目录下创建tld(Tag Library Descriptor)文件,在tld文件中对标签处理类(实现Tag接口的Java类)进行描述

快速入门

public class showIp implements Tag {    @Override    public void setPageContext(PageContext pageContext) {    }    @Override    public void setParent(Tag tag) {    }    @Override    public Tag getParent() {        return null;    }    @Override    public int doStartTag() throws JspException {        return 0;    }    @Override    public int doEndTag() throws JspException {        return 0;    }    @Override    public void release() {    }}class showIp implements Tag {

    @Override
    public void setPageContext(PageContext pageContext) {

    }

    @Override
    public void setParent(Tag tag) {

    }

    @Override
    public Tag getParent() {
        return null;
    }

    @Override
    public int doStartTag() throws JspException {
        return 0;
    }

    @Override
    public int doEndTag() throws JspException {
        return 0;
    }

    @Override
    public void release() {

    }
}
@Overridepublic void setPageContext(PageContext pageContext) {}
public void setPageContext(PageContext pageContext) {

}
private PageContext pageContext = null;@Overridepublic void setPageContext(PageContext pageContext) {    this.pageContext = pageContext;}null;

@Override
public void setPageContext(PageContext pageContext) {
    this.pageContext = pageContext;
}
@Overridepublic int doStartTag() throws JspException {    //获取到request对象    HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();    //获取到客户机的ip地址    String ip = httpServletRequest.getRemoteAddr();    //获取输出到浏览器的对象    JspWriter jspWriter = pageContext.getOut();    //下面的异常只能捕获,因为子类的异常不能比父类多    try {        jspWriter.write(ip);    } catch (IOException e) {        e.printStackTrace();    }    return 0;}
public int doStartTag() throws JspException {

    //获取到request对象
    HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();

    //获取到客户机的ip地址
    String ip = httpServletRequest.getRemoteAddr();

    //获取输出到浏览器的对象
    JspWriter jspWriter = pageContext.getOut();

    //下面的异常只能捕获,因为子类的异常不能比父类多
    try {
        jspWriter.write(ip);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return 0;
}
<?xml version="1.0" encoding="ISO-8859-1"?><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">    <tlib-version>1.0</tlib-version>    <short-name>zhongfucheng</short-name>    <uri>/zhongfucheng</uri>    <!-- Invoke 'Generate' action to add tags or functions -->    <tag>        <name>viewIp</name>        <tag-class>tag.showIp</tag-class>        <body-content>empty</body-content>    </tag></taglib>

<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">


    <tlib-version>1.0</tlib-version>
    <short-name>zhongfucheng</short-name>
    <uri>/zhongfucheng</uri>

    <!-- Invoke 'Generate' action to add tags or functions -->
    <tag>
        <name>viewIp</name>
        <tag-class>tag.showIp</tag-class>
        <body-content>empty</body-content>
    </tag>


</taglib>
640?wx_fmt=png

标签处理类详细说明

看完上面的程序,大部分人都是懵逼的。因为还不知道它具体是怎么用的,调用顺序是什么

public interface Tag extends JspTag {    int SKIP_BODY = 0;    int EVAL_BODY_INCLUDE = 1;    int SKIP_PAGE = 5;    int EVAL_PAGE = 6;    void setPageContext(PageContext var1);    void setParent(Tag var1);    Tag getParent();    int doStartTag() throws JspException;    int doEndTag() throws JspException;    void release();}interface Tag extends JspTag {
    int SKIP_BODY = 0;
    int EVAL_BODY_INCLUDE = 1;
    int SKIP_PAGE = 5;
    int EVAL_PAGE = 6;

    void setPageContext(PageContext var1);

    void setParent(Tag var1);

    Tag getParent();

    int doStartTag() throws JspException;

    int doEndTag() throws JspException;

    void release();
}

640?wx_fmt=png


@Overridepublic int doEndTag() throws JspException {    return SKIP_PAGE;}
public int doEndTag() throws JspException {
    return SKIP_PAGE;
}
640?wx_fmt=png
640?wx_fmt=png

tld文件详细说明

640?wx_fmt=png

640?wx_fmt=png


<tlib-version>1.0</tlib-version><short-name>myshortname</short-name><uri>http://mycompany.com</uri><tag>    <name></name>    <tag-class></tag-class>    <body-content></body-content></tag></tlib-version>
<short-name>myshortname</short-name>
<uri>http://mycompany.com</uri>

<tag>
    <name></name>
    <tag-class></tag-class>
    <body-content></body-content>
</tag>

TagSupport类

大部分时候我们都不需要实现Tag接口来编写自定义标签,TagSupport是Tag的一个模板类,实现了pageContext,parent的getter、setter方法以及一些其他的功能。我们要做的就是重写doStartTag()和doEndTag()方法

public class Demo1 extends TagSupport {    @Override    public int doStartTag() throws JspException {        //获取到request对象        HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();        String method = httpServletRequest.getMethod();        JspWriter jspWriter = pageContext.getOut();        try {            jspWriter.write(method);        } catch (IOException e) {            e.printStackTrace();        }        return 0;    }}class Demo1 extends TagSupport {

    @Override
    public int doStartTag() throws JspException {

        //获取到request对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();

        String method = httpServletRequest.getMethod();

        JspWriter jspWriter = pageContext.getOut();

        try {
            jspWriter.write(method);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 0;
    }
}
<tag>    <name>showMethod</name>    <tag-class>tag.Demo1</tag-class>    <body-content>empty</body-content></tag>
    <name>showMethod</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>empty</body-content>
</tag>
640?wx_fmt=png

带属性的标签

上面我们编写的自定义标签都没有附带属性的,我们在使用core标签库的时候,标签一般都带有属性

其实JSTL标签库的原理就是自定义标签,把自定义标签搞明白了,对JSTL标签库的使用就有更好的理解了

public class Demo1 extends TagSupport {    //创建成员对象,对应的setter、getter方法    private String format = null;    @Override    public int doStartTag() throws JspException {        //创建日期格式化对象        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);        //格式化日期并向浏览器输出        try {            pageContext.getOut().write(simpleDateFormat.format(new Date()));        } catch (IOException e) {            e.printStackTrace();        }        return 0;    }    public String getFormat() {        return format;    }    public void setFormat(String format) {        this.format = format;    }}class Demo1 extends TagSupport {


    //创建成员对象,对应的setter、getter方法
    private String format = null;


    @Override
    public int doStartTag() throws JspException {

        //创建日期格式化对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);

        //格式化日期并向浏览器输出
        try {
            pageContext.getOut().write(simpleDateFormat.format(new Date()));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return 0;
    }

    public String getFormat() {
        return format;
    }

    public void setFormat(String format) {
        this.format = format;
    }
}
<tag>    <name>formatDate</name>    <tag-class>tag.Demo1</tag-class>    <body-content>empty</body-content>    <attribute>        <name>format</name>        <required>true</required>        <rtexprvalue>true</rtexprvalue>    </attribute></tag>
    <name>formatDate</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>empty</body-content>
    <attribute>
        <name>format</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>
640?wx_fmt=png
640?wx_fmt=png

标签的继承关系

640?wx_fmt=png

IterationTag说明

public interface IterationTag extends Tag {    int EVAL_BODY_AGAIN = 2;    int doAfterBody() throws JspException;}interface IterationTag extends Tag {
    int EVAL_BODY_AGAIN = 2;

    int doAfterBody() throws JspException;
}
public class Demo1 extends TagSupport {    @Override    public int doStartTag() throws JspException {        try {            pageContext.getOut().write("hello");        } catch (IOException e) {            e.printStackTrace();        }        //执行标签体        return EVAL_BODY_INCLUDE;    }    @Override    public int doAfterBody() throws JspException {        //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY        return EVAL_BODY_AGAIN;    }}class Demo1 extends TagSupport {

    @Override
    public int doStartTag() throws JspException {

        try {
            pageContext.getOut().write("hello");
        } catch (IOException e) {
            e.printStackTrace();
        }

        //执行标签体
        return EVAL_BODY_INCLUDE;
    }

    @Override
    public int doAfterBody() throws JspException {

        //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY
        return EVAL_BODY_AGAIN;

    }
}
<tag>    <name>foreverEval</name>    <tag-class>tag.Demo1</tag-class>    <body-content>tagdependent</body-content></tag>
    <name>foreverEval</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>tagdependent</body-content>
</tag>
640?wx_fmt=png
//定义一个变量,规定标签体循环的次数int x = 0;@Overridepublic int doStartTag() throws JspException {    try {        pageContext.getOut().write("hello");    } catch (IOException e) {        e.printStackTrace();    }    //执行标签体    return EVAL_BODY_INCLUDE;}@Overridepublic int doAfterBody() throws JspException {    x++;    if (x >= 10) {        return SKIP_BODY;    }    //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY    return EVAL_BODY_AGAIN;}
int x = 0;

@Override
public int doStartTag() throws JspException {

    try {
        pageContext.getOut().write("hello");
    } catch (IOException e) {
        e.printStackTrace();
    }

    //执行标签体
    return EVAL_BODY_INCLUDE;
}

@Override
public int doAfterBody() throws JspException {

    x++;
    if (x >= 10) {
        return SKIP_BODY;
    }

    //标签体不断循环,直到doAfterBody()返回的是SKIP_BODY
    return EVAL_BODY_AGAIN;

}
640?wx_fmt=png

BodyTag说明

前面我们已经使用到了带标签体的自定义标签了,前面的都是只能直接输出而得不到标签体的内容,既然得不到标签体的内容,就更别说修改标签体了

public interface BodyTag extends IterationTag {    /** @deprecated */    int EVAL_BODY_TAG = 2;    int EVAL_BODY_BUFFERED = 2;    void setBodyContent(BodyContent var1);    void doInitBody() throws JspException;}interface BodyTag extends IterationTag {
    /** @deprecated */
    int EVAL_BODY_TAG = 2;

    int EVAL_BODY_BUFFERED = 2;

    void setBodyContent(BodyContent var1);

    void doInitBody() throws JspException;
}

BodyTagSupport说明

public class BodyTagSupport extends TagSupport implements BodyTag {    protected BodyContent bodyContent;    public BodyTagSupport() {    }    public int doStartTag() throws JspException {        return 2;    }    public int doEndTag() throws JspException {        return super.doEndTag();    }    public void setBodyContent(BodyContent b) {        this.bodyContent = b;    }    public void doInitBody() throws JspException {    }    public int doAfterBody() throws JspException {        return 0;    }    public void release() {        this.bodyContent = null;        super.release();    }    public BodyContent getBodyContent() {        return this.bodyContent;    }    public JspWriter getPreviousOut() {        return this.bodyContent.getEnclosingWriter();    }}class BodyTagSupport extends TagSupport implements BodyTag {
    protected BodyContent bodyContent;

    public BodyTagSupport() {
    }

    public int doStartTag() throws JspException {
        return 2;
    }

    public int doEndTag() throws JspException {
        return super.doEndTag();
    }

    public void setBodyContent(BodyContent b) {
        this.bodyContent = b;
    }

    public void doInitBody() throws JspException {
    }

    public int doAfterBody() throws JspException {
        return 0;
    }

    public void release() {
        this.bodyContent = null;
        super.release();
    }

    public BodyContent getBodyContent() {
        return this.bodyContent;
    }

    public JspWriter getPreviousOut() {
        return this.bodyContent.getEnclosingWriter();
    }
}
protected BodyContent bodyContent;public JspWriter getPreviousOut() {    return this.bodyContent.getEnclosingWriter();}

public JspWriter getPreviousOut() {
    return this.bodyContent.getEnclosingWriter();
}
public abstract class BodyContent extends JspWriter {    private JspWriter enclosingWriter;    protected BodyContent(JspWriter e) {        super(-2, false);        this.enclosingWriter = e;    }    public void flush() throws IOException {        throw new IOException("Illegal to flush within a custom tag");    }    public void clearBody() {        try {            this.clear();        } catch (IOException var2) {            throw new Error("internal error!;");        }    }    public abstract Reader getReader();    public abstract String getString();    public abstract void writeOut(Writer var1) throws IOException;    public JspWriter getEnclosingWriter() {        return this.enclosingWriter;    }}abstract class BodyContent extends JspWriter {
    private JspWriter enclosingWriter;

    protected BodyContent(JspWriter e) {
        super(-2false);
        this.enclosingWriter = e;
    }

    public void flush() throws IOException {
        throw new IOException("Illegal to flush within a custom tag");
    }

    public void clearBody() {
        try {
            this.clear();
        } catch (IOException var2) {
            throw new Error("internal error!;");
        }
    }

    public abstract Reader getReader();

    public abstract String getString();

    public abstract void writeOut(Writer var1) throws IOException;

    public JspWriter getEnclosingWriter() {
        return this.enclosingWriter;
    }
}
//将数据转变成Reader对象public abstract Reader getReader();//将数据转变成String对象public abstract String getString();
public abstract Reader getReader();

//将数据转变成String对象
public abstract String getString();
public class Demo1 extends BodyTagSupport {    @Override    public int doStartTag() throws JspException {        //想要获取到标签体的内容,就要返回EVAL_BODY_BUFFERED变量        return EVAL_BODY_BUFFERED;    }    @Override    public int doEndTag() throws JspException {        //获取到标签体的内容        String value = bodyContent.getString();        //将标签体的内容转成小写并输出        try {            this.getPreviousOut().write(value.toLowerCase());        } catch (IOException e) {            e.printStackTrace();        }        return super.doEndTag();    }}class Demo1 extends BodyTagSupport {

    @Override
    public int doStartTag() throws JspException {


        //想要获取到标签体的内容,就要返回EVAL_BODY_BUFFERED变量

        return EVAL_BODY_BUFFERED;

    }

    @Override
    public int doEndTag() throws JspException {

        //获取到标签体的内容
        String value = bodyContent.getString();

        //将标签体的内容转成小写并输出
        try {
            this.getPreviousOut().write(value.toLowerCase());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return super.doEndTag();
    }

}
<tag>    <name>BodyContentToLowerCase</name>    <tag-class>tag.Demo1</tag-class>    <body-content>tagdependent</body-content></tag>
    <name>BodyContentToLowerCase</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>tagdependent</body-content>
</tag>
640?wx_fmt=png

最后

乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!

640?wx_fmt=jpeg

有帮助?好看!转发! 640


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值