1、JSP自定义标签:
当jsp的内置标签和jstl标签库内的标签都满足不了需求,这时候就需要开发者自定义标签。
2、JDK为我们提供了自定义标签的接口:图来自网络
实现Tag接口的我们叫做传统式标签库开发,这种开发模式略显发复杂,
因此,为了简化标签开发的复杂度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。
一般来说,实现了SimpeTag接口的标签称之为简单标签,我们只要继承SimpleTagSupport类即可。
SimpleTagSupport类的执行顺序:
1)WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象
2)WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。【注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法】
3)如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
4)如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来
5)执行标签时:容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的
3、自定义简单标签的开发步骤:
1)编写标签功能的java类(标签处理器)
2)编写标签库描述文件(.tld)
3)jsp页面中导入和使用自定义的标签库
一、自定义带属性的标签
1、java标签处理器类, 继承SimpleTagSupport类即可
package cn.jq.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class MaxTag extends SimpleTagSupport{
private Integer num1;
private int num2;
@Override
public void doTag() throws JspException, IOException {
//getJspContext() 返回使用自定义标签的jsp页面的page域对象
getJspContext().getOut().println(num1>num2 ? num1 : num2);
}
public Integer getNum1() {
return num1;
}
public void setNum1(Integer num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
}
2、编写标签库描述文件 jq-tags.tld
创建jq-tags.tld文件。Tomcat服务器的webapps/examples/WEB-INF/jsp2中复制一个过来,删除标签内容,保留模板样式,自定义自己的标签内容,修改名字存放到项目中WEB-INF的任意子路径下。
<?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>A tag library exercising SimpleTag handlers.</description>
<!-- 标签的版本信息 -->
<tlib-version>1.0</tlib-version>
<!-- 自定义标签的名字 -->
<short-name>jq</short-name>
<!-- 自定义标签的uri值,是该标签库的唯一标识 ,jsp页面引用自定义标签库的标识-->
<uri>/jq-tags</uri>
<!-- 自定义标签描述 -->
<tag>
<!-- 标签描述 -->
<description>Max <![CDATA[最大值]]> </description>
<!-- 自定义标签名 -->
<name>max</name>
<!-- 标签处理的java类包全名 -->
<tag-class>cn.jq.tag.MaxTag</tag-class>
<!-- 定义标签体 empty\jsp\scriptless -->
<body-content>empty</body-content>
<!-- 自定义定义标签属性 -->
<attribute>
<name>num1</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue><!--可以接受表达式 -->
</attribute>
<attribute>
<name>num2</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3、jsp页面中导入和使用自定义的标签库
<!-- uri是自定义标签的uri值 -->
<%@ taglib uri="/jq-tags" prefix="jq"%>
<!-- 只能基本数据类型 -->
最大值:<jq:max num1="5" num2="3"/><br><br>
二、自定义带标签体的标签
作为对比, 写了一个不带标签体和带标签体的简单标签。
1、java标签处理器类
getJspBody()表示获取整个标签体的所有内容,返回的是一个fragment对象,这个对象的一个方法invoke就是用于输出整个内容到jsp页面,如果参数为null表示直接输出。
Datalist1Tag
public class Datalist1Tag extends SimpleTagSupport{
private String sql ;
@Override
public void doTag() throws JspException, IOException {
System.out.println(sql);
//getJspContext() 返回使用自定义标签的jsp页面的page域对象
PageContext pageContext = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
Map<String, Object> maps = (Map<String, Object>) request.getAttribute("map");
for(String key : maps.keySet()) {
pageContext.getOut().println("<table border=\"1\" >");
pageContext.getOut().println("<tr>");
pageContext.getOut().println("<td>");
pageContext.getOut().println(key);
pageContext.getOut().println("</td>");
pageContext.getOut().println("<td>");
pageContext.getOut().println(maps.get(key));
pageContext.getOut().println("</td>");
pageContext.getOut().println("</tr>");
pageContext.getOut().println("</table>");
}
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
Datalist2Tag
public class Datalist2Tag extends SimpleTagSupport{
private String sql ;
@Override
public void doTag() throws JspException, IOException {
System.out.println(sql);
//getJspContext() 返回使用自定义标签的jsp页面的page域对象
PageContext pageContext = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
//request 获取作用域中的数据
Map<String, Object> maps = (Map<String, Object>) request.getAttribute("map");
for(String key : maps.keySet()) {
getJspContext().setAttribute("name", key);
getJspContext().setAttribute("sex", maps.get(key));
getJspBody().invoke(null); //直接写入
}
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
2、编写标签库描述文件 jq-tags.tld
<tag>
<description>datalist1 Repeats<![CDATA[使用empty]]> </description>
<name>datalist1</name>
<tag-class>cn.jq.tag.Datalist1Tag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>sql</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue><!--可以接受表达式 -->
</attribute>
</tag>
<tag>
<description>datalist2 aa <![CDATA[使用scriptless]]> </description>
<name>datalist2</name>
<tag-class>cn.jq.tag.Datalist2Tag</tag-class>
<!-- 定义标签体 empty\jsp\scriptless -->
<body-content>scriptless</body-content>
<attribute>
<name>sql</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue><!--可以接受表达式 -->
</attribute>
</tag>
3、jsp页面中导入和使用自定义的标签库
<body>
<h1>自定义标签</h1>
<!-- 只能基本数据类型 -->
最大值:<jq:max num1="5" num2="3"/><br><br>
datalist1:
<jq:datalist1 sql="select * from tablename1" />
datalist2:<br>
<table border="1" >
<jq:datalist2 sql="select * from tablename2">
<tr>
<td>${name }</td>
<td>${sex }</td>
</tr>
</jq:datalist2>
</table>
</body>
4、servlet类, 并在web.xml 中注入映射
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String, Object> map = new HashMap<>();
map.put("张三", "女");
map.put("李斯", "男");
map.put("王武", "男");
req.setAttribute("map", map);
req.getRequestDispatcher("/mytag.jsp").forward(req, resp);
}
访问:http://127.0.0.1/myservlet/tag
总结:自定义标签形式很多,比如动态属性标签,有父标签的标签等,明白自定义标签的流程即可,需要时查文档。
参考文章:https://blog.csdn.net/java_3y/article/details/79276402