JSP标签技术——自定义标签开发

自定义标签开发步骤:

1.创建标签处理类

new一个类实现SimpleTag接口或继承simpleTagSupport类的java类——(该文件放在web应用程序的\WEB-INF\classes目录下。要正确编译该文件,必须将<tomcat-install>\lib\jsp-api.jar文件添加到CLASSPATH路径中。)←括号里的这句话是在一本书上看到的,但是姑且我们可以让它作废,因为在eclipse中WEB-INF目录下并没有什么classes文件夹,而且我们只需要正常地在java sources下面建个包把它放进去就可以,和servlet之类的并没有什么两样。
编写简单标签处理类通常不需要实现SimpleTag接口,而是继承SimpleTagSupport类,这样的话就只要覆盖类的doTag方法就可以了。doTag方法是简单标签的核心方法,要在doTag中完成标签的功能。
示例:在页面中打印一个红色星号的标签处理类

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class RedStarTag extends SimpleTagSupport{
    public void doTag() throws JspException,IOException{
        JspWriter out = getJspContext().getOut();
        out.print("<font color='#FF0000'>*</font>");
    }
}

2.创建标签库描述文件TLD

(XML格式的文件,扩展名一般为.tld)——一般存放在web应用程序的WEB-INF目录或其子目录下,新建时右键选择File,然后拓展名打成.tld即可。注意一个TLD文件中可以有很多的标签(但不能同名)。其实tld文件在tomcat的安装目录下的webapps/examples/WEB-INF/jsp2下是有示例文件的,把第一行和taglib的copy到自己要写的地方即可。

示例:在页面中打印红色星号的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">
    <uri></uri>
    <tag>
        <name>star</name>
        <tag-class>com.mytag.RedStarTag</tag-class>
        <body-content>empty</body-content>
        <attribute></attribute>
    </tag>
    <tag></tag><!-- 可以有多个不同tag -->
</taglib>

TLD文件在tomcat启动时就会加载,因此设置有误可能会导致启动失败。

<taglib>元素是TLD文件的根元素。

taglib元素的子元素:

元素 说明
description 描述该标签库的文件
display-name 图形工具可显示的简短名称
icon 图形工具可显示的图标
tlib-version(必需) 指定标签库的版本
short-name(必需) 为库中的标签指定一个名称
uri 指定该标签库中标签的uri
validator 关于该库的TagLibraryValidator信息
listener 指定事件监听器类
tag 定义一个标签(一个taglib下可以定义多个tag)
function 定义一个在EL中使用的函数

其中uri可以:<uri>http://www.mydomain.com/sample</uri>,注意这个uri不与任何web资源对应,只是一个映射地址。这种写法是绝对地址,/开头表示服务器根目录,也可以不用/开头用当前相对路径。

tag元素

tag元素的子元素:

子元素 说明
description 指定针对标签的信息
display-name 开发工具用于显示的一个简短名称
icon 可被开发工具使用的图标
name 唯一的标签名,jsp页面中对应
tag-class 标签处理类的完整名称
body-content 标签体的内容类型,其值可以为scriptless、tagdependent或empty,默认值为empty
attribute 定义该标签可接受的属性
variable 定义一个作用域变量名称,它可以设置JspContext属性
example 使用该标签例子的可选的非正式描述
tei-class javax.servlet.jsp.tagext.TagExtraInfo类的一个可选子类
tag的属性attribute(带属性标签的开发)

attribute作为标签的属性(当然是可以没有属性的),也是有子元素的。
属性值可以是常量或EL表达式,也可以是jsp表达式。表达式是在请求时计算的,并传递给相应的标签处理类。

对每个属性需要做的三件事情:
①在标签处理类中声明一个实例变量存放属性的值。(在标签处理类中创建私有变量,不可以不写私有变量名称和属性名必须保持一致
②如果属性不是必需的,那么需要提供默认值。如果没有默认值,则应该在dotag中做好它为null时的处理,要写if(XX == null)
③对每个属性必须实现适当的修改方法。(必须对该私有变量写setXXX,有些时候要注意set中对变量的异常处理,因为输入的时候是不可控类型的,只能保证是String,而比如说求平方根则必须保证是double类型,那么这个时候就算不是required也应该设置默认值
例:

double x;
public void setX(String x){
   double num =0;
   try{
          num = Double.parseDouble(x);
   }catch(NumberFormatException nfe){}
   this.x = num; 
}

带属性的标签tld文件增加<attribute>子标签,在jsp文件中的属性似乎是会自动调用setXXX的方法的,然后在dotag中就可以直接使用属性值

attribute的子元素:

子元素 说明
description 有关描述的文本信息
name 在jsp标签中使用的属性名称
required (true/false/yes/no)。默认为false,属性值可选。若为true则说明属性值必须,则jsp页面必须为其提供一个值
rtexprvalue (true/false/yes/no)。默认为false,表属性不能接受请求时表达式的值
type 属性的数据类型,默认为String.只能用在rtexprvalue设置为true时,指定使用的请求时表达式<%= %>的返回类型。
body-content元素值的说明(带标签体标签的开发)

body-content指定标签体的内容类型。标签体就是<>…<>中间省略号部分的内容

①empty——标签不带标签体
则在jsp中使用 标签时下列两种都是不合法的(假设规定标签的前缀为demo,标签名叫first)

<demo:first> </demo:first><!-- 中间有空格哦 -->
<!-- 回车也是不被允许的 -->
<demo:first>
</demo:first>



②scriptless——标签体中不含jsp脚本元素(jsp声明<%!>、表达式<%=>和小脚本<% >),但可以包含EL表达式、HTML等。
注意如果含有标签体(不为空),则就是不含jsp脚本元素的,所以就是scriptless,没有其他的能含jsp脚本元素的写法。且标签体与rtexprvalue的设定无关,rtexprvalue是设置标签属性值的,标签体就是不能含jsp脚本元素。

如果需要访问标签体的内容(这里和属性值就不一样了,属性值是会自动赋值到私有变量的,可以直接用,但是要用到标签体的内容就要对它进行访问),应该调用简单标签类的getJspBody(),它返回一个抽象类JspFragment对象,该类只定义了两个方法:
(1)public JspContext getJspContext();//返回与JspFragment有关的JspContext对象。
(2)public void invoke(Writer out);//执行标签体中代码的结果并将结果发送到Writer对象。如果将结果输出到JSP页面,参数应为null。

输出标签体内容的语句:getJspBody().invoke(null);当然是在doTag中调用,如果想要输出多次还可以在外面加for语句等。
如果需要对标签体进行处理,可将标签体内容保存到StringWriter对象中,然后将就该后的输出流对象发送到JspWriter对象。
以下是doTag内的语句:

JspWriter out = getJspContext().getOut();
StringWriter sw = new StringWriter();
getJspBody().invoke(sw);//将标签体内容存储到sw中
String text = sw.toString();
//然后就可以对text进行字符串的操作了,再把操作结果用out.print()输出即可

③tagdependent——容器不执行标签体,而是在请求时传递给标签处理类。
如果希望引进其他语言的代码片段,则需要将body-content设置为tagdependent

3.然后就可以在jsp中使用标签啦!

如果在TLD文件中URI写为:<uri>http://www.mydomain.com/sample</uri>
则在jsp文件中要写为:<%@taglib prefix="demo" uri="http://www.mydomain.com/sample" %>
注意这里的prefix是标签的前缀,是在jsp文件中这里才定义的,下文用到标签时要用
使用标签时:<上文规定的前缀:tag元素规定的name attribute中name规定的属性名="属性值">
当然TLD文件也可以不指定URI元素,这时taglib指令中的uri属性应该是TLD文件的实际路径(以”/”开头)
<%@taglib prefix="demo" uri="/WEB-INF/mytaglib.tld" %>

猜你喜欢

转载自blog.csdn.net/yogima/article/details/80444356