我们在jsp中总是会用到一些标签,比如
的一系列标签什么的。
但是有的时候我们希望用一些现有标签库没有的东西,可不可以自己定义一个标签呢?
当然可以!
一个tag就是一个普通的java类,它唯一特别之处是它必须继承 TagSupport或者BodyTagSupport类。这两个类提供了一些方法,负责jsp页面和你编写的类之间的交互,例如输入,输出。而这两个类 是由jsp容器提供的,无须开发人员自己实现。
如果我们想要自己定义一个tag需要做哪些工作呢?
“特别的工作”通常有以下几个步骤:
1)提供属性的set方法,此后这个属性就可以在jsp页面设置。以jstl标签为例 <c:out value=""/>
,这个value就是jsp数据到tag之间的入口。所以tag里面必须有一个setValue方法,具体的属性可以不叫value。
这个“value”的名称是在tld里定义的。取什么名字都可以,只需tag里提供相应的set方法即可。
2)处理 doStartTag 或 doEndTag 。这两个方法是 TagSupport提供的。 还是以<c:out value=""/>
为例,当jsp解析这个标签的时候,在“<”处触发 doStartTag 事件,在“>”时触发 doEndTag 事件。通常在 doStartTag 里进行逻辑操作,在 doEndTag 里控制输出。
3)编写tld文件。
4)在jsp页面导入tld。
这里提到了tld文件,那我们就看看这又是个什么文件。
扩展名为tld的文件是存放标签名字和类的映射用的。
标签库,他把页面标签和后面的Java类影射起来.减少了页面中的代码。使页面清晰。其实标签最后还是被解释成后台的Java代码。
原理是,在用户在jsp页面中使用标签时,系统首先会先到xml文件中的
标签中的
和
这两对标签找到相对应的扩展名为tld文件,然后在 tld文件中的映射再找到相对应的taglib类。
GitHub项目地址
项目结构图
从底层一点一点介绍吧。
首先是我们自定义的tag处理类
DateTag
package com.yubotao.Tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
* Created by Administrator on 2017/08/18.
*/
public class DateTag extends TagSupport {
private String value;
@Override
public int doStartTag() throws JspException {
String vv = "" + value;
long time = Long.valueOf(vv);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(time);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = dateFormat.format(c.getTime());
try{
pageContext.getOut().write(s);
}catch (IOException e){
e.printStackTrace();
}
return super.doStartTag();
}
public void setValue(String value){
this.value = value;
}
}
这里面主要的逻辑就是将传入的Long型数据经过一番处理,最后转化成date格式展示时间。
整个类里面最关键的一行代码就是
pageContext.getOut().write(s);
这句的意思就是使用pageContext对象向jsp页面写入输入流,也就是我们刚转换的date格式的String字符串。
接下来我们需要定义tld文件
dateTag.tld
<taglib>
<tlib-version>1.0tlib-version>
<jsp-version>1.2jsp-version>
<tag>
<name>datename>
<tag-class>com.yubotao.Tag.DateTagtag-class>
<body-content>JSPbody-content>
<attribute>
<name>valuename>
<required>truerequired>
<rtexprvalue>truertexprvalue>
attribute>
tag>
taglib>
这里IDEA会在
那里报红,不过并不影响使用。
我们主要在
标签中对各个标签进行定义,比如
就是我们使用的标签名,在jsp页面有对应;
就是我们自定义的tag类;
设置为JSP,表示接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。
BodyContent类继承了JspWriter,同时又对JspWriter实现了包装模式(wrapper),实质就是JspWriter的层层包装,你可以把这种结构想象成一个洋葱。这个有点深入了,可以参考这篇文章,这里暂不介绍。
在配置完tld文件后,我们还需要在web.xml
中引入tld文件。
web.xml
<jsp-config>
<taglib>
<taglib-uri>/tagstaglib-uri>
<taglib-location>/WEB-INF/tld/dateTag.tldtaglib-location>
taglib>
jsp-config>
这里对jsp中的taglib进行了定义,定义了
,这个在jsp页面中会用到,然后定义了
,这里面的值就是你的tld文件路径。
然后看一下在jsp页面中如何引用的
<%@taglib uri="/tags" prefix="date"%>
<date:date value="${date}"/>
这里的uri和之前的web.xml
文件中定义的对应上了。prefix
中的值和
中的第一个”date”对应上了,而第二个”date”对应的是之前tld文件中设置的
下的
值。
最后梳理一下自定义标签的处理过程:
首先如果我们的jsp页面有一个自定义标签;然后会通过jsp中的
中对应的uri去找我们自定义的tld文件,而这步是通过web.xml
文件中对于taglib标签的配置完成的;然后再通过tld找到对应的自定义tag处理类,因为我们自定义的tag标签做的最后一件事就是打印,所以感觉还有交互,其实并没有了,到这里该tag标签工作就完毕了。
通过如上的梳理,我们自定义tag标签的时候需要做的就是:
1.自定义tag处理类;
2.配置对应的tld文件;
3.在web.xml
中对tld文件进行配置;
4.在jsp中引用到自定义的tag标签。