先创建一个Web工程,因为在这里我们是使用了Maven管理项目,使用Eclipse创建一个叫为app的Maven Project。创建的过程可以看《使用Eclipse开发一个Servlet3.0的简单例子》,然后再加上一些我们需要的Jar包,在这里还需要加上JSP包,即在pom.xml的依赖中添加:
<!-- 需要使用JSP标签的需要引入的包 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>compile</scope> </dependency>
接着开发JSP自定义标签库:
1、在src/webapp/Web-INF下添加tld文件,即自定义标签文件,在这里我只会给出最终的文件:
<?xml version="1.0" encoding="GBK" ?> <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 web-jsptaglibrary_2_0.xsd" version="2.0"> <!-- TLD版本 --> <tlib-version>1.0</tlib-version> <!-- 标签库的名称 --> <short-name>mytaglib</short-name> <!-- 标签库的URI,唯一 --> <uri>http://www.crazyit.org/mytaglib</uri> <tag> <!-- 标签名 --> <name>helloWorld</name> <!-- 标签处理类 --> <tag-class>org.test.HelloWorldTag</tag-class> <!-- 标签体,当前是空的 --> <body-content>empty</body-content> <!-- 添加固定的属性 --> <attribute> <!-- 设置属性名,子元素的值是字符串内容,这个属性必须在处理类中有get,set方法 --> <name>content</name> <!-- 设置该属性是否为必需属性 --> <required>true</required> <!-- 设置该属性是否支持JSP脚本、表达式等动态内容 --> <fragment>true</fragment> </attribute> </tag> <tag> <name>iterator</name> <tag-class>org.test.IteratorTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>collection</name> <required>true</required> <fragment>true</fragment> </attribute> <attribute> <name>item</name> <required>true</required> <fragment>true</fragment> </attribute> </tag> <tag> <!-- 标签名,支持片段 --> <name>fragment</name> <tag-class>org.test.FragmentTag</tag-class> <body-content>empty</body-content> <attribute> <name>fragment</name> <required>true</required> <fragment>true</fragment> </attribute> </tag> <tag> <name>dynaAttr</name> <tag-class>org.test.DynaAttributesTag</tag-class> <!-- 这个属性是必须指定的,否则会出错 --> <body-content>empty</body-content> <!-- 指定支持动态属性 --> <dynamic-attributes>true</dynamic-attributes> </tag> </taglib>
2、创建处理这些对应自定义标签的处理类,自定义标签处理类都需要继承SimpleTagSupport。
public class HelloWorldTag extends SimpleTagSupport
{
private String content;
public String getContent()
{
return content;
}
public void setContent(String content)
{
this.content = content;
}
@Override
public void doTag() throws JspException, IOException
{
this.getJspContext().getOut().write("Hello World "+content);
}
}
public class IteratorTag extends SimpleTagSupport
{
private String collection;
private String item;
public String getCollection()
{
return collection;
}
public void setCollection(String collection)
{
this.collection = collection;
}
public String getItem()
{
return item;
}
public void setItem(String item)
{
this.item = item;
}
@Override
public void doTag() throws JspException, IOException
{
Collection itemList = (Collection)getJspContext().getAttribute(collection);
System.out.println(itemList == null);
for(Object s : itemList)
{
System.out.println(s);
getJspContext().setAttribute(item, s);
getJspBody().invoke(null);
}
}
}
public class FragmentTag extends SimpleTagSupport
{
private JspFragment fragment;
public JspFragment getFragment()
{
return fragment;
}
public void setFragment(JspFragment fragment)
{
this.fragment = fragment;
}
@Override
public void doTag() throws JspException, IOException
{
JspWriter out = getJspContext().getOut();
out.println("<h3>JSP片段</h3>");
fragment.invoke(null);
}
}
//动态属性的自定义标签还需要实现DynamicAttributes接口
public class DynaAttributesTag extends SimpleTagSupport implements DynamicAttributes
{
private List<String> keys = new ArrayList<String>();
private List<Object> values = new ArrayList<Object>();
@Override
public void doTag() throws JspException, IOException
{
JspWriter out = getJspContext().getOut();
out.println("<ol>");
for(int i = 0 ;i<keys.size();i++)
{
String key = keys.get(i);
Object value = values.get(i);
out.println("<li>"+key+" = "+ value + "</li>");
}
out.println("</ol>");
}
@Override
public void setDynamicAttribute(String uri, String localName, Object value) throws JspException
{
keys.add(localName);
values.add(value);
}
}
看到上面这些处理类,大家都会发现一个共同的地方,所有的处理类都是继承自SimpleTagSupport,
如果是动态属性,则还需要实现接口DynamicAttributes,还有就是属性都必须有Setter和Getter方法。
3、在JSP页面中使用这些自定义标签。
<!-- 指定错误页面error.jsp -->
<%@ page language="java" errorPage="error.jsp" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page import="org.test.*" %>
<!-- 如果想要支持EL语言必须把这个EL支持打开,否则默认是不支持的
如果想整个服务下都支持,则需要在Web服务器上设置
-->
<%@ page isELIgnored="false" %>
<!-- 1、引入需要使用的标签库,uri是标签库的唯一标识,prefix为前缀 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pageContext测试</title>
</head>
<body>
<!-- JSP脚本 -->
<%
List<String> a = new ArrayList<String>();
a.add("疯狂Java");
a.add("www.crazyit.org");
a.add("java");
pageContext.setAttribute("a",a);
List<User> users = new ArrayList<User>();
users.add(new User("test1",29));
users.add(new User("test2",30));
users.add(new User("test3",31));
pageContext.setAttribute("users", users);
%>
<br>
<!-- 2、下面就是使用自定义标签的例子 -->
<!-- 带属性,不带标签体的自定义标签 -->
<mytag:helloWorld content="test"/>
<table>
<!-- 带属性,带标签体的自定义标签 -->
<mytag:iterator item="item" collection="a">
<tr>
<!-- EL表达式 -->
<td>${pageScope.item}</td>
</tr>
</mytag:iterator>
</table>
<table>
<!-- 这个List是保存的是一个对象 -->
<mytag:iterator item="user" collection="users">
<tr>
<td>${user.name}</td><td>${user.age}</td>
</tr>
</mytag:iterator>
</table>
<!-- 页面片段作为属性的标签 -->
<mytag:fragment>
<jsp:attribute name="fragment">
<mytag:helloWorld content="test"/>
</jsp:attribute>
</mytag:fragment>
<!-- 使用动态属性 -->
<mytag:dynaAttr bookname="ddd" value="123" />
</body>
</html>
上面的3个步骤充分说明了如何创建JSP自定义标签,如何使用这些自定义标签。
在JSP2还提供另外一个更加简单的自定义标签的方式:
TagFile支持
Tag File 是自定义标签的简化用法,使用Tag File可以无须定义标签处理类和标签库文件,但仍然可以在JSP页面中使用自定义标签。
下面以Tag File一个最简单的标签,期步骤如下:
1)建立Tag文件,在JSP所支持Tag File规范下,Tag File代理了标签处理类,它的格式类似于JSP文件。可以这样理解:如同JSP可以代替Servlet作为表现层一样,Tag File则可以代替标签处理类。
Tag File具有如下5个编译指令。
taglib : 作用与JSP文件中的tablib指令效果相同,用于导入其他标签库
include : 作用与JSP文件中的include指令效果相同,用于导入其他JSP或静态页面
tag : 作用类似于JSP文件中的page指令,有pageEncoding,body-content等属性,用于设置页面编码等属性。
attribute : 用于设置自定义标签的属性,类似于自定义标签处理类中的标签属性
variable : 用于设置自定义标签的变量,这些变量将传给JSP页面使用。
下面是标签的Tag File,这个Tag File的语法与JSP语法非常相似。
自定义标签在页面上生成一个内容片段,同理,这个Tag File也只负责生成一个页面片段。
Tag File的命名必须遵守如下规则:tagName.tag。在这里,我们把这个文件放在/WEB-INF/tags文件夹下。
<%@ tag pageEncoding="UTF-8" import="java.util.*"%>
<!-- 导入EL的自定义函数 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<!-- 标签的属性 -->
<%@ attribute name="title"%>
<%@ attribute name="username"%>
<%@ attribute name="bean"%>
<h1>${title }</h1>
<!-- 调用自定义EL的函数 -->
<span>${mytag:reverse(username) }</span>
<!-- 根据从上面传递的bean的名称,从request获取对象,把user的age显示出来 -->
<h2>${requestScope[bean].age}</h2>
2)在页面中使用自定义标签时,也是需要先导入标签库,再使用标签。它与自定义标签导入的差别,就是它没有URI,只有标签库路径。因此导入标签时,语法如下:
<%@ taglib prefix="tagPrefix" tagdir="path"%>
<!-- 指定错误页面error.jsp -->
<%@ page language="java" errorPage="error.jsp" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page import="org.test.*" %>
<!-- 如果想要支持EL语言必须把这个EL支持打开,否则默认是不支持的
如果想整个服务下都支持,则需要在Web服务器上设置
-->
<%@ page isELIgnored="false" %>
<!-- 1、引入需要使用的标签库,uri是标签库的唯一标识,prefix为前缀 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pageContext测试</title>
</head>
<body>
<!-- 使用Tag File 自定义标签 -->
<%
User user = new User("Tag File",29);
request.setAttribute("user", user) ;
%>
<tags:test title="TagFile自定义标签的标题" username="lyndon" bean="user"/>
</body>
</html>