jsp(19)(二)(自定义标签)

自定义标签功能:

1.替换java脚本(目的为避免在页面中写java脚本。很多框架都有自定标签以更好的页面展示)
2.控制jsp某部分是否执行
3.控制整个页面是否执行
4.控制jsp页面内容重复执行
5.修改标签体的输出内容

传统自定义的标签(jsp2.0之前)处理器类需要实现Tag比较多的子接口(服务器会自动调用实现类,根据配置)

也可以继承Tag的多个实现类(比如:TagSupport,BodyTagSupport)

传统自定义标签执行过程:

1.请求jsp,会将jsp转换为servlet,如何解析标签如下:(可以通过查看解析后的servlet源码查看)
2.遇到自定义标签,首先实例化标签对应的处理器类。
3.调用setPageContex把页面对象(可以获得各个域的数据)传递给处理器类。
4.看标签是否有父标签,如果有,调用setParent方法将父标签(处理器类)对象传递给处理器类,如果没有传递null
5.完成上面的初始化,遇到开始标签,调用doStartTag方法
6.如果有标签体,一般执行标签体
7.遇到结束标签,执行doEndTag方法
8.整个标签执行完,一般不会调用release()方法释放标签所占资源。
9.继续执行jsp其他内容

自定义标签的发展历:(篮框表示过时接口jsp2.0之前的,又称传统标签接口)

新的替代标签接口是simpleTag又称为简单标签接口,自定义的标签处理器类只要继承接口的实现类SimpleTagSupport

执行过程:解析简单标签:

1.实例化标签处理器类
2.调用setJspContext()将页面对象传递给处理器类
3.调用setParent()将父标签处理器对象传递给处理器类
4.调用每个属性对应的set方法把属性值传递给标签处理器对象。(如果调用标签时设置了属性,需要给处理器类添加属性及对应的set方法。)

   (如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。)

5.调用setJspBody()将代表标签体的JspFragment对象传递给处理器类
6.执行标签,也就是调用doTag()方法

 doTag()方法通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

 

javax.servlet.jsp.tagext.JspFragment类,类中只定义了两个方法:

JSP2.0中定义,它的实例对象代表JSP页面中的一段符合语法规范不能包含JSP脚本元素的jsp代码片段。

getJspContext方法

用于返回代表调用页面的JspContext对象.

public abstract void invoke(java.io.Writer out) 

用于执行JspFragment对象所代表的JSP代码片段(即输出标签体的数据)
参数out用于指定结果写入到哪个输出流中,如果传递给参数out的值为null,则将执行结果写入到jspWritter(JspContext.getOut())对象中。(写给浏览器)

这个方法可以

1.控制是否执行和输出标签体的内容(不调用JspFragment.invoke相当于忽略标签体内容,不输出标签体内容)
2.是否迭代执行标签体的内容或(重复调用JspFragment.invoke方法,标签体内容将会被重复执行
3.对标签体的执行结果进行修改后再输出。(调用invoke方法输出到StringWriter,然后获取修改后JspContext.getOut()得到jspWritter再输出。)

一个自定义标签有三部分组成:

1.标签处理器类,需要继承SimpleTagSupport类重写方法
2.一般在WEB-INF/目录下创建标签配置文档(自定义tld文件.tld,文件名一般和jsp标签前缀一致)
3.jsp中使用标签前,需要关联到标签文档,以及设置前缀。

补充:(tld:标签库描述符(Tag Library Descriptor)

关于标签的 url 值一种可以和配置对应的url 一致,一种是标签定义的实际目录

对于标签体输出默认invoke(null)参数null表示页面输出

属性赋值只支持8种基本类型自动转换(string转换成基本类型),如果有特殊类型需要使用脚本或者el表达式。

实例输出标签内容:

处理器类:

public class SimpleTagDemo1 extends SimpleTagSupport{  
    public void doTag() throws JspException, IOException {  
        JspFragment jf = this.getJspBody();  
        //相当于jf.invoke(null);  
        jf.invoke(this.getJspContext().getOut());  
        //这里如果不想输出标签体内容的话,只需要不调用invoke方法即可  
    }  

标签配置:custom.tld

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>2.0</jsp-version>
  <short-name>Example TLD with Body</short-name>
  <url>http://www.xxx.com/xxx</url>//可把该文件的标签和该地址绑定,使用该文件中的标签只需要在jsp中指定该url。  

<tag> <name>Hello</name> <tag-class>com.runoob.SimpleTagDemol</tag-class> <body-content>scriptless</body-content> </tag> </taglib>

jsp:

<%@ taglib prefix="ex" uri="WEB-INF/custom.tld"%>//url的内容也可以是上面定义的url地址http://www.xxx.com/xxx
<html>
  <head>
    <title>A sample custom tag</title>
  </head>
  <body>
    <ex:Hello>
xxxxxxxxxx
</ex:Hello> </body> </html>

实例:标签之后的内容不输出:

处理器类,其他部分略

public class SimpleTagDemo2 extends SimpleTagSupport{  
     public void doTag() throws JspException, IOException {  
         //直接抛出异常就不会执行余下的jsp内容  
         throw new SkipPageException();  
     }  

简略:

<body-content>empty</body-content> //配置 
<simpletag:demo2/>  //jsp

 

实例:标签体内容重复输出:

处理器类,其他部分略

public class SimpleTagDemo3 extends SimpleTagSupport{  
    public void doTag() throws JspException, IOException {  
        JspFragment jf = this.getJspBody();  
        for(int i=0;i<5;i++){  
            jf.invoke(null);  
        }  
    }  

实例:修改标签体内容输出:

处理器类,其他部分略

public class SimpleTagDemo3 extends SimpleTagSupport{    
     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);  
     }  

自定义标签属性的使用:

 public class PropertyTag extends SimpleTagSupport{
//属性必须在这定义和他的set方法(属性值是8种基本类型,会自动转换)
private int count = 0; public void setCount(int count){ this.count = count; } public void doTag() throws JspException, IOException { JspFragment jf = this.getJspBody(); for(int i=0;i<count;i++){ jf.invoke(null); } }

配置:

<tag>  
    <name>demo</name>  
    <tag-class>com.weijia.propertytag.PropertyTag</tag-class>  
    <body-content>scriptless</body-content>  
    <attribute>   
        <name>count</name>  //属性名字
        <required>true</required>  //是否是必须使用(在jsp中)
        <rtexprvalue>true</rtexprvalue> //属性是否支持表达式和java脚本
    </attribute>  
  </tag>  

jsp:

<propertytag:demo count="9">  
     aaaaa  
</propertytag:demo>  

如果使用其他类型的属性,需要使用表达式语言和脚本:

处理器类:

 public class PropertyTag extends SimpleTagSupport{
     //属性必须在这定义和他的set方法(属性值是8种基本类型,会自动转换)     
    private Date count = null;        
    public void setCount(Date count){  
         this.count = count;  
     }  

jsp页面的参数必须使用脚本语言:(ps:这个属性应该是一个地址,然后处理器类获得该地址的对象)

<propertytag:demo count="<%=new Date()%>">  
     aaaaa  
</propertytag:demo>  

如果有多个属性的配置:

 <attribute>
      <name>attribute_name1</name>
      <required>false</required>
      <type>java.util.Boolean</type>
      <fragment>false</fragment>
    </attribute>
    <attribute>
      <name>attribute_name2</name>
      <required>true</required>
      <type>java.util.Date</type>
    </attribute>

标签属性的一些补充:

 

补充:

JavaWeb学习篇之----自定义标签&&JSTL标签库详解

http://www.runoob.com/jsp/jsp-custom-tags.html

posted @ 2017-02-15 00:40  假程序猿  阅读(309)  评论(0)    收藏  举报