深入分析JavaWeb Item24 -- jsp2.X自己定义标签开发进阶

一、简单标签(SimpleTag)

  由于传统标签使用三个标签接口来完毕不同的功能,显得过于繁琐。不利于标签技术的推广, SUN公司为减少标签技术的学习难度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。

  这里写图片描写叙述

实现SimpleTag接口的标签通常称为简单标签。

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

  • setJspContext方法
  • setParent和getParent方法
  • setJspBody方法
  • doTag方法(很重要)。简单标签使用这种方法就能够完毕全部的业务逻辑

二、SimpleTag方法介绍

2.1、setJspContext方法

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

2.2、setParent方法

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

2.3、getParent方法

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

2.4、setJspBody方法

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

2.5、doTag方法

  用于完毕全部的标签逻辑,包含输出、迭代、改动标签体内容等。在doTag方法中能够抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再运行JSP页面中位于结束标记后面的内容。这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况。

三、SimpleTag接口方法的运行顺序

  当web容器開始运行标签时,会调用例如以下方法完毕标签的初始化:

  1. WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象。

  2. WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。

    注意,仅仅有在标签存在父标签的情况下,WEB容器才会调用这种方法。

  3. 假设调用标签时设置了属性,容器将调用每一个属性相应的setter方法把属性值传递给标签处理器对象。假设标签的属性值是EL表达式或脚本表达式。则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。

  4. 假设简单标签有标签体。WEB容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来。

  5. 运行标签时WEB容器调用标签处理器的doTag()方法,开发者在方法体内通过操作JspFragment对象,就能够实现是否运行、迭代、改动标签体的目的。

这里写图片描写叙述

四、开发简单标签实现页面逻辑

  SUN公司针对SimpleTag接口提供了一个默认的实现类SimpleTagSupport。SimpleTagSupport类中实现了SimpleTag接口的全部方法,因此我们能够编写一个类继承SimpleTagSupport类,然后依据业务须要再重写doTag方法。

4.1、控制jsp页面某一部分内容是否运行

 编写一个类继承SimpleTagSupport,然后再重写doTag方法,在doTag方法里面不调用jspFrament.invoke方法就可以。

演示样例代码例如以下:

SimpleTagDemo1.java

package me.gacl.web.simpletag;

import java.io.IOException;

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

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo1类继承SimpleTagSupport
 */
public class SimpleTagDemo1 extends SimpleTagSupport {

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法。控制标签体是否运行
     */
    @Override
    public void doTag() throws JspException, IOException {
        //得到代表jsp标签体的JspFragment
        JspFragment jspFragment = this.getJspBody();

        //得到jsp页面的的PageContext对象
        //PageContext pageContext = (PageContext) jspFragment.getJspContext();
        //调用JspWriter将标签体的内容输出到浏览器
        //jspFragment.invoke(pageContext.getOut());

        //将标签体的内容输出到浏览器
        jspFragment.invoke(null);

    }
}

  在WEB-INF文件夹下新建一个simpletag.tld文件,然后在simpletag.tld文件里加入对该标签处理类的描写叙述,例如以下:

  这里写图片描写叙述

  simpletag.tld文件代码例如以下:

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    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"
    version="2.0">
    <!-- description用来加入对taglib(标签库)的描写叙述 -->
    <description>孤傲苍狼开发的SimpleTag自己定义标签库</description>
    <!--taglib(标签库)的版本 -->
    <tlib-version>1.0</tlib-version>
    <short-name>GaclSimpleTagLibrary</short-name>
    <!-- 
        为自己定义标签库设置一个uri,uri以/开头,/后面的内容随便写,如这里的/simpletag ,
        在Jsp页面中引用标签库时。须要通过uri找到标签库
        在Jsp页面中就要这样引入标签库:<%@taglib uri="/simpletag" prefix="gacl"%>
    -->
    <uri>/simpletag</uri>

    <!--一个taglib(标签库)中包含多个自己定义标签。每一个自己定义标签使用一个tag标记来描写叙述  -->
    <!-- 一个tag标记相应一个自己定义标签 -->
     <tag>
        <description>SimpleTag(简单标签)Demo1</description>
        <!-- 
            为标签处理器类配一个标签名。在Jsp页面中使用标签时是通过标签名来找到要调用的标签处理器类的
            通过demo1就能找到相应的me.gacl.web.simpletag.SimpleTagDemo1类
         -->
        <name>demo1</name>
        <!-- 标签相应的处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo1</tag-class>
        <!-- 
        tld文件里有四种标签体类型 :empty  JSP  scriptless  tagdepentend  
            在简单标签(SampleTag)中标签体body-content的值仅仅同意是empty和scriptless,不同意设置成JSP,假设设置成JSP就会出现异常
            在传统标签中标签体body-content的值仅仅同意是empty和JSP
            假设标签体body-content的值设置成tagdepentend,那么就表示标签体里面的内容是给标签处理器类使用的。
            比如:开发一个查询用户的sql标签。此时标签体重的SQL语句就是给SQL标签的标签处理器来使用的
            <gacl:sql>SELECT * FROM USER</gacl:sql>
            在这样的情况下,sql标签的<body-content>就要设置成tagdepentend,tagdepentend用得比較少。了解一下就可以
        -->
        <body-content>scriptless</body-content>
    </tag>
</taglib>

  在jsp页面中导入并使用自己定义标签。例如以下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%@taglib uri="/simpletag" prefix="gacl" %>
<!DOCTYPE HTML>
<html>
  <head>
    <title>用简单标签控制标签体是否运行</title>
  </head>

  <body>

  <%--在jsp页面中使用自己定义标签 demo1标签是带有标签体的,标签体的内容是"孤傲苍狼"这几个字符串--%>
    <gacl:demo1>
        孤傲苍狼
    </gacl:demo1>
  </body>
</html>

  运行效果例如以下:

  这里写图片描写叙述

4.2、控制jsp页面内容反复运行

  编写一个类继承SimpleTagSupport,然后再重写doTag方法,在doTag方法里面反复调用jspFrament.invoke方法就可以。

演示样例代码例如以下:

SimpleTagDemo2.java

package me.gacl.web.simpletag;

import java.io.IOException;

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

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo2类继承SimpleTagSupport
 */
public class SimpleTagDemo2 extends SimpleTagSupport {

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法,控制标签运行5次
     */
    @Override
    public void doTag() throws JspException, IOException {
        // 得到代表jsp标签体的JspFragment
        JspFragment jspFragment = this.getJspBody();
        for (int i = 0; i < 5; i++) {
            // 将标签体的内容输出到浏览器
            jspFragment.invoke(null);
        }
    }
}

  在WEB-INF文件夹下的simpletag.tld文件里加入对该标签处理类的描写叙述,例如以下:

<tag>
        <!-- 标签名 -->
        <name>demo2</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo2</tag-class>
        <!-- 标签体同意的内容 ,scriptless表示标签体的内容不同意是java脚本代码-->
        <body-content>scriptless</body-content>
</tag>

  在jsp页面中导入并使用自己定义标签,例如以下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%@taglib uri="/simpletag" prefix="gacl" %>
<!DOCTYPE HTML>
<html>
  <head>
    <title>用简单标签控制标签体运行5次</title>
  </head>

  <body>

  <%--在jsp页面中使用自己定义标签 --%>
    <gacl:demo2>
        孤傲苍狼<p/>
    </gacl:demo2>
  </body>
</html>

  运行效果例如以下:

 这里写图片描写叙述 

4.3、改动jsp页面内容输出

  编写一个类继承SimpleTagSupport,然后再重写doTag方法,在doTag方法调用jspFrament.invoke方法时,让运行结果写一个自己定义的缓冲中就可以,然后开发者能够取出缓冲的数据改动输出。

演示样例代码例如以下:

SimpleTagDemo3.java

package me.gacl.web.simpletag;

import java.io.IOException;
import java.io.StringWriter;

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

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo3类继承SimpleTagSupport
 */
public class SimpleTagDemo3 extends SimpleTagSupport {

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法,改动标签体里面的内容,将标签体的内容转换成大写
     */
    @Override
    public void doTag() throws JspException, IOException {
        // 得到代表jsp标签体的JspFragment
        JspFragment jspFragment = this.getJspBody();
        StringWriter sw = new StringWriter();
        //将标签体的内容写入到sw流中
        jspFragment.invoke(sw);
        //获取sw流缓冲区的内容
        String content = sw.getBuffer().toString();
        content = content.toUpperCase();
        PageContext pageContext = (PageContext) this.getJspContext();
        //将改动后的content输出到浏览器中
        pageContext.getOut().write(content);
    }
}

  在WEB-INF文件夹下的simpletag.tld文件里加入对该标签处理类的描写叙述。例如以下:

<tag>
        <!-- 标签名 -->
        <name>demo3</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo3</tag-class>
        <!-- 标签体同意的内容 。scriptless表示标签体的内容不同意是java脚本代码-->
        <body-content>scriptless</body-content>
</tag>

  在jsp页面中导入并使用自己定义标签,例如以下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%--<%@taglib uri="/simpletag" prefix="gacl" %>--%>
<%--在jsp页面中也能够使用这样的方式导入标签库。直接把uri设置成标签库的tld文件所在文件夹 --%>
<%@taglib uri="/WEB-INF/simpletag.tld" prefix="gacl"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>用简单标签改动jsp页面内容输出</title>
  </head>

  <body>

  <%--在jsp页面中使用自己定义标签 --%>
    <gacl:demo3>
        gacl_xdp
    </gacl:demo3>
  </body>
</html>

  运行效果例如以下:

 这里写图片描写叙述 

4.4、控制整个jsp页面是否运行

  编写一个类继承SimpleTagSupport,然后再重写doTag方法。在doTag方法抛出SkipPageException异常就可以,jsp收到这个异常,将忽略标签余下jsp页面的运行。

演示样例代码例如以下:

SimpleTagDemo4.java

package me.gacl.web.simpletag;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.SkipPageException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo4类继承SimpleTagSupport
 */
public class SimpleTagDemo4 extends SimpleTagSupport {

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法,控制标签余下的Jsp不运行
     */
    @Override
    public void doTag() throws JspException, IOException {
        //抛出一个SkipPageException异常就能够控制标签余下的Jsp不运行
        throw new SkipPageException();
    }
}

  在WEB-INF文件夹下的simpletag.tld文件里加入对该标签处理类的描写叙述,例如以下:

复制代码

<tag>
        <!-- 标签名 -->
        <name>demo4</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo4</tag-class>
        <!-- 标签体同意的内容 ,empty表示该标签没有标签体-->
        <body-content>empty</body-content>
</tag>

  在jsp页面中导入并使用自己定义标签,例如以下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%--<%@taglib uri="/simpletag" prefix="gacl" %>--%>
<%--在jsp页面中也能够使用这样的方式导入标签库。直接把uri设置成标签库的tld文件所在文件夹 --%>
<%@taglib uri="/WEB-INF/simpletag.tld" prefix="gacl"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>用简单标签控制标签余下的Jsp不运行</title>
  </head>

  <body>
      <h1>孤傲苍狼</h1>
       <%--在jsp页面中使用自己定义标签 --%>
       <gacl:demo4/>
       <!-- 这里的内容位于 <gacl:demo4/>标签后面。因此不会输出到页面上 -->
       <h1>白虎神皇</h1>
  </body>
</html>

  运行效果例如以下:

 这里写图片描写叙述 

五、简单标签开发的一些注意细节

5.1、标签类编写细节

  开发标签类时,不要直接去实现SimpleTag接口,而是应该继承SimpleTagSupport类。SimpleTagSupport类是SimpleTag接口的一个默认实现类。通过继承SimpleTagSupport类,就能够直接使用SimpleTagSupport类已经实现的那些方法。假设SimpleTagSupport类的方法实现不满足业务要求。那么就能够依据具体的业务情况将相应的方法进行重写。

5.2、tld文件里标签体类型设置细节

  我们开发好一个简单标签后,须要在tld文件里加入对该标签的描写叙述。比如:

 <tag>
         <!-- 标签名 -->
         <name>demo2</name>
         <!-- 标签处理器类-->
         <tag-class>me.gacl.web.simpletag.SimpleTagDemo2</tag-class>
         <!-- 标签体同意的内容 ,scriptless表示标签体的内容不同意是java脚本代码-->
         <body-content>scriptless</body-content>
 </tag>

  开发好一个标签后,在tld文件里使用<tag>来描写叙述一个标签,描写叙述的内容包含标签名(name)。标签处理器类(tag-class),标签体的内容(body-content)。

  tld文件里有四种标签体(body-content)类型 :empty、JSP、scriptless、tagdependent

简单标签标签体的细节注意问题:
在简单标签(SampleTag)中标签体body-content的值仅仅同意是empty、scriptless、tagdependent,不同意设置成JSP,假设设置成JSP就会出现异常:

 The TLD for the class me.gacl.web.simpletag.SimpleTagDemo1 specifies an invalid body-content (JSP) for a SimpleTag

  body-content的值假设设置成empty,那么就表示该标签没有标签体。假设是设置成scriptless。那么表示该标签是有标签体的。可是标签体中的内容不能够是<%java代码%>。比如:

 <gacl:xdpdemo1>
    <%
            //嵌套在标签体中的java代码
         int i= 0;
     %>
       孤傲苍狼
 </gacl:xdpdemo1>

  否则运行标签时就会出现例如以下错误:

 Scripting elements ( &lt;%!, &lt;jsp:declaration, &lt;%=, &lt;jsp:expression, &lt;%, &lt;jsp:scriptlet ) are disallowed here

  jsp标签技术出现的目的就是为了移除在jsp页面上编写的java代码的。假设在jsp标签中同意出现java代码,那么就违背了jsp标签技术设计时的初衷了,所以在简单标签的标签体中是不同意出现java代码的。

传统标签标签体的细节注意问题:

在传统标签中标签体body-content的值同意是empty、JSP、scriptless、tagdependent,body-content的值假设是设置成JSP,那么表示该标签是有标签体的,而且标签体的内容能够是随意的。包含java代码,假设是设置成scriptless,那么表示该标签是有标签体的。可是标签体的内容不能是java代码

  假设传统标签和简单标签的标签体body-content的值设置成tagdependent。那么就表示标签体里面的内容是给标签处理器类使用的。tagdependent用得比較少,了解一下就可以

5.3、tld文件里标签库的uri设置细节

  假设在一个项目中使用或者开发了多个标签库,比如:

  这里写图片描写叙述

  那么标签库的uri不能设置成同样的,否则在Jsp页面中通过uri引用标签库时就不知道引用哪一个标签库了,假设真的有那么巧,两个标签库的uri是刚好一样的,例如以下图所看到的:

  这里写图片描写叙述

  那么在jsp页面中引用标签库时假设“<%@taglib uri=”/gacl” prefix=”gacl” %>“这样引用。那么就无法推断当前引用的标签库究竟是gacl.tld标签库中的标签还是simpletag.tld标签库中的标签。由于两个标签库的uri刚好都是"/gacl"。在两个标签库的引用uri一样的情况下。为了能够在jsp中差别究竟引用的是哪个标签库。能够换一种引用方式:<%@taglib uri=”要引用的标签库的tld文件文件夹” prefix=”gacl”%>。使用taglib指令引入标签库时。taglib指令的uri属性指定为标签库的tld文件文件夹。这样就能够差别开了,比如:

  引用gacl.tld标签库:<%@taglib uri="/WEB-INF/gacl.tld" prefix="gacl"%>、

  引用simpletag.tld标签库:<%@taglib uri="/WEB-INF/simpletag.tld" prefix="gacl"%>

  所以当在项目中引用了多个标签库,假设标签库的uri刚好是一样的。就能够用这样的方式解决。

六、简单标签开发步骤总结

  1、编写一个类继承SimpleTagSupport类。然后依据业务须要重写SimpleTagSupport类中已经实现了的方法,普通情况下仅仅须要重写doTag()方法就可以。

  2、在WEB-INF文件夹下创建一个tld文件,在tld文件里加入对该标签的描写叙述。tld文件不一定放在WEB-INF文件夹下,也能够放在别的文件夹,习惯是放在WEB-INF文件夹下。

七、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()方法返回的输出流对象中。

(简而言之,能够理解为写给浏览器)

7.1、invoke方法具体解释

  JspFragment.invoke方法是JspFragment最重要的方法。利用这种方法能够控制是否运行和输出标签体的内容、是否迭代运行标签体的内容或对标签体的运行结果进行改动后再输出。

比如:
  
  在标签处理器中假设没有调用JspFragment.invoke方法。其结果就相当于忽略标签体内容;
  在标签处理器中反复调用JspFragment.invoke方法,则标签体内容将会被反复运行。

若想在标签处理器中改动标签体内容。仅仅需在调用invoke方法时指定一个可取出结果数据的输出流对象(比如StringWriter)。让标签体的运行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行改动后再输出到目标设备。就可以达到改动标签体的目的。

八、开发带属性的标签

  自己定义标签能够定义一个或多个属性,这样,在JSP页面中应用自己定义标签时就能够设置这些属性的值,通过这些属性为标签处理器传递參数信息,从而提高标签的灵活性和复用性。
  要想让一个自己定义标签具有属性,通常须要完毕两个任务:

  1. 在标签处理器中编写每一个属性相应的setter方法
  2. 在TLD文件里描术标签的属性

      为自己定义标签定义属性时。每一个属性都必须依照JavaBean的属性命名方式,在标签处理器中定义属性名相应的setter方法,用来接收 JSP页面调用自己定义标签时传递进来的属性值。

    比如属性url,在标签处理器类中就要定义相应的setUrl(String url)方法。


      
      在标签处理器中定义相应的set方法后。JSP引擎在解析运行開始标签前。也就是调用doStartTag方法前,会调用set属性方法。为标签设置属性。

8.1、开发带属性的标签范例

范例1:通过标签的属性控制标签体的运行次数

演示样例代码例如以下:

SimpleTagDemo5.java

package me.gacl.web.simpletag;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo5类继承SimpleTagSupport
 * 通过标签的属性控制标签体的运行次数
 */
public class SimpleTagDemo5 extends SimpleTagSupport {

    /**
     * 定义标签的属性
     */
    private int count;

    /**count属性相应的set方法
     * @param count
     */
    public void setCount(int count) {
        this.count = count;
    }

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法,通过标签的属性控制标签体的运行次数
     */
    @Override
    public void doTag() throws JspException, IOException {
        for (int i = 0; i < count; i++) {
            this.getJspBody().invoke(null);
        }
    }

}

  在WEB-INF文件夹下的tld文件里加入对该标签的描写叙述,例如以下所看到的:

<tag>
        <!-- 标签名 -->
        <name>demo5</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo5</tag-class>
        <!-- 标签体同意的内容-->
        <body-content>scriptless</body-content>

        <!-- 标签的属性描写叙述 -->
        <attribute>
            <description>描写叙述标签的count属性</description>
            <!-- 标签的count属性 -->
            <name>count</name>
            <required>true</required>
            <!-- rtexprvalue用来指示标签的属性值能否够是一个表达式,
            一般设置为true,true就表示同意标签的属性值能够是一个表达式-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
</tag>

  在jsp页面引入标签库并使用自己定义标签

<%@ page language="java" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%--<%@taglib uri="/simpletag" prefix="gacl" %>--%>
<%--在jsp页面中也能够使用这样的方式导入标签库,直接把uri设置成标签库的tld文件所在文件夹 --%>
<%@taglib uri="/WEB-INF/simpletag.tld" prefix="gacl"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>通过标签的属性控制标签体的运行次数</title>
  </head>

  <body>
       <%--在jsp页面中使用自己定义标签。标签有一个count属性 --%>
          <gacl:demo5 count="2">
              <h1>孤傲苍狼</h1>
          </gacl:demo5>
  </body>
</html>

  运行效果例如以下:

  这里写图片描写叙述

  假设标签的属性值是8种基本数据类型,那么在JSP页面在传递字符串时,JSP引擎会自己主动转换成相应的类型,但假设标签的属性值是复合数据类型。那么JSP引擎是无法自己主动转换的

范例2:标签接收的属性值是一个复合数据类型。该怎样给标签的属性赋值

演示样例代码例如以下:

SimpleTagDemo6.java

package me.gacl.web.simpletag;

import java.io.IOException;
import java.util.Date;

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

/**
 * @author gacl
 * SimpleTagSupport类实现了SimpleTag接口,
 * SampleTagDemo6类继承SimpleTagSupport
 * 标签的属性说明
 */
public class SimpleTagDemo6 extends SimpleTagSupport {

    /**
     * 定义标签的属性
     */
    private Date date;

    /**date属性相应的set方法
     * @param date
     */
    public void setDate(Date date) {
        this.date = date;
    }

    /* 简单标签使用这种方法就能够完毕全部的业务逻辑
     * @see javax.servlet.jsp.tagext.SimpleTagSupport#doTag()
     * 重写doTag方法。输出date属性值
     */
    @Override
    public void doTag() throws JspException, IOException {
        this.getJspContext().getOut().write(date.toLocaleString());
    }
}

  在WEB-INF文件夹下的tld文件里加入对该标签的描写叙述。例如以下所看到的:

<tag>
        <!-- 标签名 -->
        <name>demo6</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo6</tag-class>
        <!-- 标签体同意的内容-->
        <body-content>empty</body-content>

        <!-- 标签的属性描写叙述 -->
        <attribute>
            <description>描写叙述标签的date属性</description>
            <!-- 标签的date属性。复合数据类型 -->
            <name>date</name>
            <required>true</required>
            <!-- rtexprvalue用来指示标签的属性值能否够是一个表达式。
            一般设置为true,true就表示同意标签的属性值能够是一个表达式-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
</tag>

  在jsp页面引入标签库并使用自己定义标签

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%--在jsp页面中导入自己定义标签库 --%>
<%--<%@taglib uri="/simpletag" prefix="gacl" %>--%>
<%--在jsp页面中也能够使用这样的方式导入标签库。直接把uri设置成标签库的tld文件所在文件夹 --%>
<%@taglib uri="/WEB-INF/simpletag.tld" prefix="gacl"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>假设标签接收的属性值是一个复合数据类型,该怎样给标签的属性赋值</title>
  </head>

  <body>
     <%--
     在jsp页面中使用自己定义标签。标签有一个date属性 。是一个复合数据类型
       假设标签的属性值是8种基本数据类型,那么在JSP页面在传递字符串时。JSP引擎会自己主动转换成相应的类型
       但假设标签的属性值是复合数据类型,那么JSP引擎是无法自己主动转换的,
       这里将一个字符串赋值给demo6标签的date属性。在运行标签时就会出现例如以下错误:
     Unable to convert string "1988-05-07" to class "java.util.Date" for attribute "date": 
     Property Editor not registered with the PropertyEditorManager
          <gacl:demo6 date="1988-05-07">
          </gacl:demo6>
      --%>
      <%--假设一定要给标签的复合属性赋值。那么能够採用表达式的方式给复合属性赋值,例如以下所看到的: --%>

      <%
          Date d = new Date();
        request.setAttribute("date", d);
      %>

      <gacl:demo6 date="${date}"/>
      <hr/>
      <gacl:demo6 date="<%=new Date()%>"/>
  </body>
</html>

  运行效果例如以下:

  这里写图片描写叙述

8.2、tld文件里用于描写叙述标签属性的元素说明

  <tag>元素的<attribute>子元素用于描写叙述自己定义标签的一个属性。自己定义标签所具有的每一个属性都要相应一个<attribute>元素

比如:

<tag>
        <!-- 标签名 -->
        <name>demo5</name>
        <!-- 标签处理器类-->
        <tag-class>me.gacl.web.simpletag.SimpleTagDemo5</tag-class>
        <!-- 标签体同意的内容-->
        <body-content>scriptless</body-content>

        <!-- 标签的属性描写叙述 -->
        <attribute>
            <description>描写叙述标签的count属性</description>
            <!-- 标签的count属性 -->
            <name>count</name>
            <required>true</required>
            <!-- rtexprvalue用来指示标签的属性值能否够是一个表达式,
            一般设置为true,true就表示同意标签的属性值能够是一个表达式-->
            <rtexprvalue>true</rtexprvalue>
        </attribute>
</tag>

<attribute>元素的子元素说明:

  这里写图片描写叙述

  到此,简单标签的开发技术就算是全部讲完了,在下一篇博文中会编写一些自己定义标签的案例来加深自定标签技术的学习和理解。

posted @ 2017-08-04 13:24  clnchanpin  阅读(357)  评论(0编辑  收藏  举报