先创建一个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>