Jstl提供的功能已经非常强大,但是当它不能满足我们的需求时,我们还能够开发我们自己的标签。如何开发呢,首先看一下当我们在使用jstl的时候是如何引用标签的
使用<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>在页面中引入标签,
通过<c:out param1="">body</c>进行使用。
其中uri并不是一个链接,它代表唯一的一个标志,可以通过这个标志找到指定的TLD文件。prefix为前缀,引用这个tld文件中的标签时所使用的前缀。
c:out表示的就是已用的是c所对应的tld文件中的哪一个标签,param1为这个标签中所能够定义的属性,body是标签体。
所以当我们写自己的标签的时候需要做的内容就包括了写一个tld文件来定义标签,属性和body。
另外我们还需要编写tag handler类,即标签所对应的操作的类,这个类也会在tld文件中与标签关联。
开发自定义标签类有三种方式tag files ,tag handle(simple, classic),我们从最简单的开始说起。
tag files
主要的目的是动态的引入页面。
开发的时候我们可以先写好一个要引入的jsp页面,比如headers.jsp,然后重新命名为headers.tag放到WEB-INF目录下的tags目录下。内容如下:
<h1>This is my JSP page.</h1> <br>
${subTitle }<br>
为了使他真正成为一个标签,我们还需要定义其中的属性,body等等,然后代码更改成如下的样子:
<%@ attribute name="subTitle" required="true" rtexprvalue="true" %>
<%@ tag body-content="tagdependent" %>
<h1>This is my JSP page.</h1> <br>
${subTitle }<br>
<jsp:doBody/>
其中<jsp:doBody/>表示输出体的内容。
然后就是在页面中的引用
<%@ taglib tagdir="/WEB-INF/tags" prefix="myTag"%>
<myTag:headers subTitle="nihao"><%=123 * 123 %></myTag:headers>
这种方法并不常用,另外其中attribute和body-content的作用跟在tld中的作用是相同的,下面会统一的介绍。
SimpleTagSupport
最常用的就是继承SimpleTagSupport这个类来开发自定义的标签。他是JSP2.0为了简便开发新提供给我们的类,先来一个比较简单的,hello sombody。
先写tld文件:
- 其中taglib中的属性不用在意只是制定了schema和版本等信息。
- uri中是这个文件的唯一标识,一般使用一个网站地址来表示,因为一般网站地址是不会有重复的
- 可以有多个tag标签定义多个tag。
- name表示的是:后面的部分即标签名。tag-class指定了这个标签所关联的类。
- body-cotent表示标签body中可以包含的内容可以取值为;empty,scriptless,tagdependent,JSP因为2.0规范中不建议使用这一项,所以很多容器都没有实现它
- attribute表示标签可以包含的属性,required表示必须填写的项,rtexprvalue表示属性是否可以使用表达式来赋值
为了告诉去什么地方寻找这个tld文件,在jsp2.0之前我们需要在DD文件中进行配置:
在JSP2.0之后容器会自动在四个目录查找tld文件,WEB-INF的根目录,子目录。WEB-INF/lib中的jar包中的META-INFO目录及其子目录。
tld文件编写完成,第二步,写类
- 需要继承SimpleTagSupport 类
- 在tld文件中定义的attribute需要在这个类中作为实例变量,另外需要有seter和geter来供容器使用。
最后在需要在页面上进行引用:
<%@ taglib uri="myTestTag" prefix="myTag"%>
<myTag:simple1 somebody="小红"/>
rtexprvalue
表示属性是否能够使用脚本进行赋值,如果设置为true的话页面上就能能够使用多种方式进行赋值:
<% String somebody = "小白"; %>
<c:set var="somebody1" value="小黑" scope="session"></c:set>
<myTag:simple1 somebody="小红"/>
<myTag:simple1 somebody="${somebody1}"/>
<myTag:simple1 somebody="<%=somebody %>"/>
<myTag:simple1 ><jsp:attribute name="somebody" value="ddd"></myTag:simple1>
如果body不为空
在tld文件中有body-content配置项
- 为empty的时候表示body必须为空,以/>结尾
- 为scriptless的时候表示不能够使用脚本,但是能够使用action、自定义标签或者el表达式
- 为tagdependent时,表示body中的内容会作为普通文本,用户可以在自己的类里进行处理。
在类中对body进行处理时也比较的简单,可以直接加入getJspBody().invoke(null);的代码,来把body直接输出到页面上。
如果能够使用el表达式,我们还能够实现一些更复杂的功能,能够在类中更改或者是新建el表达式想要输出的变量。比比如加入:
getJspContext().setAttribute("somebody1", "小白");
如果body中有${somebody1 }就会被翻译成小白。
更甚至于,我们还能够循环输出body的内容,这非常有用,比如动态建立多行表格时等等。首先我们更改一下tld文件:
加入
<attribute>
<name>tastes</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
把类代码改为:
页面上的代码为:
<% String[] tastes = new String[]{"化学","游泳"};
request.setAttribute("tastes",tastes);%>
<table>
<myTag:simple1 tastes="${tastes }">
<tr>
<td>${taste }</td>
</tr>
</myTag:simple1>
执行结果会发现,我们打印出了一个表格。
TagSupport
在JSP2.0之前,是没有SimpleTagSupport来让我们使用的,下面就来看一下使用比较原始的方式该如何操作。
首先看一个比较简单的例子:
当然页面上还是要加入引用的内容的,看这个类我们会发现,可覆盖的方法变多了,另外是通过return的值来控制流转的.对于具体的流转过程,看下图:
从这个图中,我们还能够每个方法中都有哪些跳转变量
另外还能看出在什么地方能够处理body。下面就来看一个跟上面SimpleTagSupport中相同功能的打印循环的类应该如何写:
代码比较简单,主要是利用了return EVAL_BODY_AGIN来实现的循环