自定义标签开发步骤:
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" %>