JSP自定义标签是一种扩展JSP功能的高级技巧,它允许开发者定义自己的标签,以便在JSP页面中重复使用。自定义标签使得在JSP中可以使用更高级的抽象,从而提高了代码的可重用性、可维护性和可读性,开发自定义标签包含如下步骤:
.tld
对应一个标签库,每个标签库可以包含多个标签这篇笔记我们介绍如何在JSP中自定义标签。
自定义标签需要有一个对应的Java类包含自定义标签的代码逻辑,这个类需要实现JspTag
接口,我们一般直接继承SimpleTagSupport
类。自定义标签中最重要的方法就是doTag()
,其中包含了自定义标签的渲染逻辑。
HelloTag.java
package com.gacfox.demoweb.demo.taglib;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
public class HelloTag extends SimpleTagSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void doTag() throws JspException, IOException {
getJspContext().getOut().write("hello," + name);
}
}
代码中,name
是该标签的一个属性,doTag()
方法则是具体的渲染逻辑,这里我们通过getJspContext()
方法获取JSP上下文并写入一些内容。
mytaglib.tld
<?xml version="1.0" encoding="UTF-8" ?>
<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 http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>My demo tag lib</description>
<tlib-version>1.0</tlib-version>
<short-name>MyTagLib</short-name>
<uri>https://gacfox.com/mytaglib</uri>
<tag>
<description>show hello</description>
<name>hello</name>
<tag-class>com.gacfox.demoweb.demo.taglib.HelloTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>true</required>
</attribute>
</tag>
</taglib>
TLD包含一些重要的属性设置。
TLD文件需要被放置在WEB-INF
或其子目录下,通常我们会建立一个WEB-INF/tlds
目录来放置所有的自定义标签库TLD。上述XML代码中,我们配置了标签库的描述信息、标签对应的类、标签的属性字段等。
引入自定义标签库需要通过uri
来关联,下面是一个例子。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="m" uri="https://gacfox.com/mytaglib"%>
<html>
<head>
<title>demo tag</title>
</head>
<body>
<m:hello name="admin" />
</body>
</html>
上面代码中我们设置了自定义标签库的前缀是m
,我们自定义的标签hello
即可通过<m:hello>
引用,上述代码运行后会输出hello,admin
字样。
前面的例子比较简单,我们的自定义标签只有一个属性字段,而没有标签体,带有标签体的自定义标签会稍微复杂一些。下面例子中,我们编写了一个用于迭代List对象的自定义标签。
package com.gacfox.demoweb.demo.taglib;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.util.Collection;
public class IterTag extends SimpleTagSupport {
/**
* 迭代集合的属性名
*/
private String collectionStr;
/**
* 用于迭代的元素
*/
private String item;
public String getCollectionStr() {
return collectionStr;
}
public void setCollectionStr(String collectionStr) {
this.collectionStr = collectionStr;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) getJspContext();
Collection collection = (Collection) pageContext.getRequest().getAttribute(collectionStr);
for (Object o : collection) {
getJspContext().setAttribute(item, o);
getJspBody().invoke(null);
}
}
}
该标签有两个属性,collectionStr
用于指定迭代集合的变量名,item
用于指定迭代变量的变量名,doTag()
中我们编写了循环渲染的逻辑,其中invoke()
方法用于执行包含在自定义标签体中的JSP片段,对于带标签体的自定义标签该方法至关重要。
该标签的TLD定义如下:
<tag>
<name>iter</name>
<tag-class>com.gacfox.demoweb.demo.taglib.IterTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>collectionStr</name>
<required>true</required>
</attribute>
<attribute>
<name>item</name>
<required>true</required>
</attribute>
</tag>
在JSP页面中我们可以通过如下方式使用该自定义标签。
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="m" uri="https://gacfox.com/mytaglib" %>
<html>
<head>
<title>tag demo</title>
</head>
<body>
<%
List<String> myList = new ArrayList<>();
myList.add("Item 1");
myList.add("Item 2");
request.setAttribute("myList", myList);
%>
<table>
<m:iter collectionStr="myList" item="i">
<tr>
<td>${i}</td>
</tr>
</m:iter>
</table>
</body>
</html>
上述代码最终会被渲染为一个HTML表格。