由自定义标签了解标签是如何起作用的

由自定义标签了解标签是如何起作用的


标签配置文件 tld

talk is cheap show me the code:

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

  <!-- 标签库的版本号 -->
  <tlib-version>1.2</tlib-version>
  <!-- 标签库的简写名称 -->
  <short-name>mytag</short-name>
  <!-- 标签库对应的唯一uri -->
  <uri>http://heyahui/taglib</uri>

  <!-- 自定义的标签 -->
  <tag>
    <!-- 标签名称 -->
    <name>hello</name>
    <!-- 实现标签功能的类的具体路径 -->
    <tag-class>a_tag.HelloTag</tag-class>
    <!-- 标签体内容的限制 scriptless:不支持jsp empty:内容为空 tagdependent:支持jsp,但当作文本 JSP:支持jsp,不建议 -->
    <body-content>scriptless</body-content>
    <!-- 标签中的属性 -->
    <attribute>
        <!-- 属性的名字 -->
        <name>num</name>
        <!-- 属性是否是必须的 -->
        <required>false</required>
        <!-- 属性是否支持EL表达式 -->
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>

</taglib>

有了这个配置文件,我们下面只需要一个类来实现标签的具体功能就行了

标签的实现类

talk is cheap show me the code:

package a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class HelloTag extends SimpleTagSupport {

    // 标签属性的具体实现
    private int num;

    // 标签属性的获取方法
    public void setNum(int num) {
        this.num = num;
    }

    @Override
    // 该方法是用于标签的具体功能实现的
    public void doTag() throws JspException, IOException {
        // 输出标签中的内容但无法对内容修改
        this.getJspBody().invoke(null);
        // 获取标签的内容并修改后输出
        JspFragment jspBody = this.getJspBody();
        StringWriter writer = new StringWriter();
        jspBody.invoke(writer);
        String content = writer.toString();
        content = content.subString(0,1);
        this.getContext().getOut().write(content);
        /*
         *这里讲一下直接输出的原理
         *invoke()方法的参数为null时其实是默认将JspWriter作为其对象的,并调用它的write()方法
         *直接将标签内容传给页面的输出流,我们无法做修改
         *要想修改这个内容,必须用一个其它流去接收它,然后再做修改
         */
    }

}

上面的代码省略了一些标签类的其它方法,这些方法主要是用于标签的具体创建等生命周期的,都在超类中进行了重写,所以我们一般只需要重写具体的逻辑即可

案例参考

这里,我们来模仿几个主流的标签的实现
talk is cheap show me the code

if 标签

<!-- tld文件中的标签部分 -->

  <!-- if -->
  <tag>
    <name>if</name>
    <tag-class>a_tag.IfTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
        <name>test</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>         
    </attribute>
  </tag>
package a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class IfTag extends SimpleTagSupport {

    private boolean test;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if (testValue) {
            this.getJspBody().invoke(null);
        }
    }

}

choose 标签

<!-- tld文件中的标签部分 -->

  <!-- choose -->
  <tag>
    <name>choose</name>
    <tag-class>a_tag.ChooseTag</tag-class>
    <body-content>scriptless</body-content>
  </tag>
  <!-- when -->
  <tag>
    <name>when</name>
    <tag-class>a_tag.WhenTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
        <name>test</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
  <!-- otherwise -->
  <tag>
    <name>otherwise</name>
    <tag-class>a_tag.OtherwiseTag</tag-class>
    <body-content>scriptless</body-content>
  </tag>
package a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ChooseTag extends SimpleTagSupport {

    private boolean flag;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void doTag() throws JspException, IOException {
        this.getJspBody().invoke(null);
    }

}
package a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class WhenTag extends SimpleTagSupport {

    private boolean test;

    public void setTest(boolean test) {
        this.test = test;
    }

    @Override
    public void doTag() throws JspException, IOException {
        if (test) {
            this.getJspBody().invoke(null);
        } 
        ((ChooseTag) this.getParent()).setFlag(test);
    }

}
package a_tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class OtherwiseTag extends SimpleTagSupport {

    @Override
    public void doTag() throws JspException, IOException {
        if (!((ChooseTag) this.getParent()).isFlag()) {
            this.getJspBody().invoke(null);
        }
    }

}

foreach标签

<!-- tld文件中的标签部分 -->

  <!-- foreach -->
  <tag>
    <name>foreach</name>
    <tag-class>a_tag.ForeachTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
        <name>items</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
        <name>var</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>
package a_tag;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class ForeachTag extends SimpleTagSupport {

    private Object items;

    private String var;

    public void setItems(Object items) {
        this.items = items;
    }

    public void setVar(String var) {
        this.var = var;
    }

    @Override
    public void doTag() throws JspException, IOException {
        PageContext context = (PageContext) this.getJspContext();
        if (items instanceof List) {
            List list = (List) items;
            for (Object object : list) {
                context.setAttribute(var, object);
                this.getJspBody().invoke(null);
            }
        } else if (items instanceof Map) {
            Map<String, Object> map = (Map) items;
            for (Map.Entry entry : map.entrySet()) {
                context.setAttribute(var, entry);
                this.getJspBody().invoke(null);
            }
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值