2.8.5 带标签体的标签

2.8.5 带标签体的标签

带标签体的标签,可以在标签内嵌入其他内容(包括静态的HTML内容和动态的JSP内容),通常用于完成一些逻辑运算,例如判断和循环等。下面以一个迭代器标签为示例,介绍带标签体标签的开发过程。

IteratorTag.java

一样先定义一个标签处理类,该标签处理类的代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package lee;

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

public class IteratorTag extends SimpleTagSupport {
// 标签属性,用于指定需要被迭代的集合
private String collection;
// 标签属性,指定迭代集合元素,为集合元素指定的名称
private String item;

// collection的setter和getter方法
public void setCollection(String collection) {
this.collection = collection;
}

public String getCollection() {
return this.collection;
}

// item的setter和getter方法
public void setItem(String item) {
this.item = item;
}

public String getItem() {
return this.item;
}

// 标签的处理方法,标签处理类只需要重写doTag()方法
public void doTag() throws JspException, IOException {
// 从page scope中获取名为collection的集合
Collection itemList = (Collection) getJspContext().getAttribute(collection);
// 遍历集合
for (Object s : itemList) {
// 将集合的元素设置到page范围内
getJspContext().setAttribute(item, s);
// 输出标签体
getJspBody().invoke(null);
}
}
}

上面的标签处理类与前面的处理类并没有太大的不同,该处理类包含两个成员变量(代表标签的属性),并为这两个成员变量提供了settrgetter方法。
标签处理类的doTage()方法首先从page范围内获取了指定名称的Collection对象,然后遍历Collection对象的元素,每次遍历都调用了getJspBody()方法,该方法返回该标签所包含的标签体:JspFragment对象,执行JspFragment对象的invoke()方法,即可输出标签体内容。
该标签的作用是:遍历指定集合,每遍历一个集合元素,即输出标签体一次。

因为该标签的标签体不为空,配置该标签时指定body-contentscriptless,该标签的配置代码片段如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 定义第三个标签 -->
<tag>
<!-- 定义标签名 -->
<name>iterator</name>
<!-- 定义标签处理类 -->
<tag-class>lee.IteratorTag</tag-class>
<!-- 定义标签体不允许出现JSP脚本 -->
<body-content>scriptless</body-content>
<!-- 配置标签属性:collection -->
<attribute>
<name>collection</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<!-- 配置标签属性:item -->
<attribute>
<name>item</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
</tag>

上面的配置片段中的代码:

1
<body-content>scriptless</body-content>

指定该标签的标签体可以是静态HTML内容,也可以是表达式语言,但不允许出现JSP脚本.
为了测试在JSP页面中使用该标签的效果,下面先将一个List对象设置成page范围的属性,然后使用该标签来迭代输出List集合的全部元素.

iteratorTag.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.util.*"%>
<!-- 导入标签库,指定mytag前缀的标签,
由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<!DOCTYPE html>
<html>
<head>
<title> 带标签体的标签-迭代器标签 </title>
</head>
<body>
<h2>带标签体的标签-迭代器标签</h2><hr/>
<%
//创建一个List对象
List<String> a = new ArrayList<String>();
a.add("疯狂Java");
a.add("www.crazyit.org");
a.add("www.fkit.org");
//将List对象放入page范围内
pageContext.setAttribute("a" , a);
%>
<table border="1" bgcolor="#aaaadd" width="300">
<!-- 使用迭代器标签,对a集合进行迭代 -->
<mytag:iterator collection="a" item="item">
<tr>
<td>${pageScope.item}</td>
<tr>
</mytag:iterator>
</table>
</body>
</html>

上面的页面代码中代码:

1
2
3
4
5
6
<!-- 使用迭代器标签,对a集合进行迭代 -->
<mytag:iterator collection="a" item="item">
<tr>
<td>${pageScope.item}</td>
<tr>
</mytag:iterator>

可实现通过Iterator标签来遍历指定集合,浏览该页面即可看到如图2.36所示的界面。
图2.36显示了使用Iterator标签遍历集合元素的效果,从iteratorTag.jsp页面的代码来看,使用Iterator标签遍历集合元素比使用JSP脚本遍历集合元素要优雅得多,这就是自定义标签的魅力。
实际上JSTL标签库提供了一套功能非常强大的标签,例如普通的输出标签,就像刚刚介绍的迭代器标签,还有用于分支判断的标签等,JSTL都有非常完善的实现。