JavaWeb学习记录(十九)——jstl自定义标签之简单标签

时间:2023-11-13 18:24:26

一、简单标签共定义了5个方法:

setJspContext方法
setParent和getParent方法
setJspBody方法
doTag方法
二、方法介绍
osetJspContext方法

用于把JSP页面的pageContext对象传递给标签处理器对象

osetParent方法

用于把父标签处理器对象传递给当前标签处理器对象

ogetParent方法

用于获得当前标签的父标签处理器对象

osetJspBody方法

用于把代表标签体的JspFragment对象传递给标签处理器对象

odoTag方法

用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容等。在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。

三、接口方法的执行顺序

1.当web容器开始执行标签时,会调用如下方法完成标签的初始化
WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。
WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法。
如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。
2.执行标签时:
容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。
四、JspFragment类
¨javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段,这段JSP片段中不能包含JSP脚本元素。
¨WEB容器在处理简单标签的标签体时,会把标签体内容用一个JspFragment对象表示,并调用标签处理器对象的setJspBody方法把JspFragment对象传递给标签处理器对象。JspFragment类中只定义了两个方法,如下所示:
¨getJspContext方法
用于返回代表调用页面的JspContext对象.
public abstract void invoke(java.io.Writer out)
用于执行JspFragment对象所代表的JSP代码片段
参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)
五、invoke方法详解 
¨JspFragment.invoke方法是JspFragment最重要的方法,利用这个方法可以控制是否执行和输出标签体的内容、是否迭代执行标签体的内容或对标签体的执行结果进行修改后再输出。例如:
o在标签处理器中如果没有调用JspFragment.invoke方法,其结果就相当于忽略标签体内容;
o在标签处理器中重复调用JspFragment.invoke方法,则标签体内容将会被重复执行;
o若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的。
六、案例分析
  方法分析:
    public class DemoTag1 implements SimpleTag {
    private PageContext pageContext;
    private String name;

/**
     * 用于完成所有的标签逻辑,包括输出、迭代、修改标签体内容。在doTag方法中可以抛出javax.servelt.jsp.
     * SkipPageException异常
     * ,用于通知web容器不再执行JSP页面中位于结束标记后面的内容,者等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况
     * *
     */
    @Override
    public void doTag() throws JspException, IOException {
        System.out.println("doTag");
    }

/**
     * 用于获得当前标签的父标签的处理器对象
     */
    @Override
    public JspTag getParent() {
        System.out.println("getParent");
        return null;
    }

/**
     * 用于吧代表标签体的JspFragment对象传递给标签处理器对象
     */
    @Override
    public void setJspBody(JspFragment jspBody) {
        System.out.println("setJspBody");

}

/**
     * 用于把JSP页面的pageContext对象传递给标签处理器对象
     */
    @Override
    public void setJspContext(JspContext pc) {
        this.pageContext = (PageContext) pc;
        System.out.println("setJspContext");

}
    /**
     * 用于把父标签处理器对象传递给当前标签处理器对象
     */
    @Override
    public void setParent(JspTag parent) {
        System.out.println("setParent");

}

/**
     * 属性是通过这个setter方法设置进来
     */
    public void setName(String name) {
        System.out.println("设置name属性"+name);
        this.name = name;
    }

}

  1.//控制标签体是否执行
public class TagDemo1 extends SimpleTagSupport {

@Override
    public void doTag() throws JspException, IOException {
        JspFragment jf = this.getJspBody();
    }
}

页面:
<html>
  <head>    
    <title>控制标签体是否执行</title>
  </head>
 
  <body>
       <hytc:demo1>
           xxxx
       </hytc:demo1>
  </body>
</html>

2.//控制标签体是否执行
public class TagDemo2 extends SimpleTagSupport {

@Override
    public void doTag() throws JspException, IOException {
        JspFragment jf = this.getJspBody();
        for(int i=0;i<10;i++){
            jf.invoke(null);
        }    
    }
}
页面:
<html>
  <head>    
    <title>控制标签体重复执行</title>
  </head>
 
  <body>
       <hytc:demo2>
           xxxx
       </hytc:demo2>
  </body>
</html>
3.//修改标签体
public class TagDemo3 extends SimpleTagSupport {

@Override
    public void doTag() throws JspException, IOException {
        
        JspFragment jf = this.getJspBody();
        StringWriter sw = new StringWriter();
        jf.invoke(sw);
        
        String content = sw.toString();
        content = content.toUpperCase();
        
        this.getJspContext().getOut().write(content);
    }
    
}
页面:
<html>
  <head>    
    <title>修改标签体</title>
  </head>
 
  <body>
       <hytc:demo3>
           xxxx
       </hytc:demo3>
  </body>
</html>

4.//控制整个jsp是否执行
public class TagDemo4 extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        throw new SkipPageException();
    }
}
页面:
<hytc:demo4/>
<html>
  <head>    
    <title>修改标签体</title>
  </head>
 
  <body>

</body>
</html>
5.//
public class TagDemo5 extends SimpleTagSupport {
    
    private int count;
    private Date date;

public void setCount(int count) {
        this.count = count;
    }
    
    public void setDate(Date date) {
        this.date = date;
    }

@Override
    public void doTag() throws JspException, IOException {
        
        System.out.println(date);
        for(int i=0;i<count;i++){
            this.getJspBody().invoke(null);
        }
    }
}
页面:
<html>
  <head>    
    <title>My JSP '5.jsp' starting page</title>
  </head>
 
  <body>
    
    <hytc:demo5 count="5" date="<%=new Date() %>">
        aaaaaaa
    </hytc:demo5>    
    
  </body>
</html>
6.配置文件:
  <tag>
        <name>demo1</name>
        <tag-class>web_16.simpletag.TagDemo1</tag-class>
        <body-content>scriptless</body-content>
    </tag>
     
    <tag>
        <name>demo2</name>
        <tag-class>web_16.simpletag.TagDemo2</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    
     <tag>
        <name>demo3</name>
        <tag-class>web_16.simpletag.TagDemo3</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    
     <tag>
        <name>demo4</name>
        <tag-class>web_16.simpletag.TagDemo4</tag-class>
        <body-content>scriptless</body-content>
    </tag>
    
     <tag>
        <name>demo5</name>
        <tag-class>web_16.simpletag.TagDemo5</tag-class>
        <body-content>scriptless</body-content>
        
        <attribute>
            <name>count</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
        
        <attribute>
            <name>date</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
      </tag>