一,概述
在jsp页面中,我们当然希望是<%Java代码%>jsp脚本越来越少,而自定义标签主要用于移除jsp页面中的jsp脚本.
二,自定义标签的步骤
1)编写标签处理器类,使它继承SimpleTagSupport类(SimpleTagSupport实现了SimpleTag接口),覆盖doTag()方法,在doTag()方法中实现标签的功能.
2)在WEB-INF目录下新建一个tld文件,在这个文件里面配置标签.必须放在WEB-INF目录下,这样tomcat启动,加载web应用时会将该目录下的所有文件加载.
3)使用taglib指令在jsp页面导入标签库.
4)在jsp页面中使用自定义标签库的标签.
三,实战之自定义带属性的if标签
按上面步骤贴代码如下(为什么这样自定义,后面解释...):
1)编写标签处理器类
package com.bighuan.b_tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定义if标签
*
* @author bighuan
*
*/
public class IfTag extends SimpleTagSupport {
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) this.getJspContext();
if (test) {
JspFragment jspFragment = this.getJspBody();
jspFragment.invoke(null);
}
}
}
2)在WEB-INF下新建一个bighuan.tld文件,可参照核心标签库(C标签库的tld文件的写法).这篇文章有介绍: JSP之jstl标签库
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 标签库版本 -->
<tlib-version>1.1</tlib-version>
<!-- 标签库前缀 -->
<short-name>bighuan</short-name>
<!-- uri:tld文件的唯一标记 -->
<uri>http://com.bighuan.definetag</uri>
<!-- 自定义if标签 -->
<tag> <!-- 标签名称 -->
<name>if</name> <!-- 标签处理器的全名 -->
<tag-class>com.bighuan.b_tags.IfTag</tag-class> <!-- 输出标签体内容格式 -->
<body-content>scriptless</body-content><attribute>
<!--属性名称-->
<name>test</name>
<!--属性是否必填-->
<required>true</required><!-- 支持EL表达式 --><rtexprvalue>true</rtexprvalue></attribute></tag>></taglib>
3)导入标签库(为什么这样写,请参照上面给出的文章)
<%@taglib uri="http://com.bighuan.definetag" prefix="bighuan"%>
4)使用
<bighuan:if test="${10 == 10 }">
自定义if标签成功了!!!
</bighuan:if>
输出结果就是标签体内容了.
四,自定义标签处理器类的生命周期
SimpleTag接口:
1)void setJspContext(JspContext pc):jsp引擎将代表jsp页面的pageContext对象传递给标签处理器对象.这个方法是一定会被调用的,相应的我们可以通过getJspContext()方法得到pageContext对象(要强转).
2)void setParent(JspTag parent):jsp引擎将父标签处理器对象传递给当前标签处理器对象.只有存在父标签时,jsp引擎才会调用该方法.上面示例中自定义if标签没有父标签,所以就没有执行该方法.
3)setXXX方法:设置标签属性,只有定义了标签属性才会调用该方法.这个方法是自己实现的,要多少个属性就自己定义多少个.上面示例中定义了一个属性,所以就自己动手写了一个setTest(boolean test)方法.
4)void setJspBody(JspFragment jspBody) :若存在标签体,jsp引擎就将标签体封装成一个JspFragment对象,调用setJspBody方法将JspFragment对象传递给标签处理器对象.若标签体为空,setJspBody()方法就不会被jsp引擎调用.
5)doTag():执行标签的具体逻辑,这个方法一定会执行.
五,自定义标签的执行过程
访问一个使用了自定义标签的jsp页面,自定义标签的执行过程是怎么样的呢?下面以自定义if标签为例:
1)jsp文件翻译成Java源文件-->编译成一个class字节码文件-->构造对象-->调用_jspService()方法(这些还是jsp的生命周期)
2)检查taglib指令,<%@taglib uri="http://com.bighuan.definetag" prefix="bighuan"%>,如果通过uri不能找到相应的tld文件,就会报错.没报错,就找到了,代表正确(这不废话吗).
3)上一步就已经读到bighuan.tld文件了,此时jsp页面读到<bighuan:if>后,就去相应的bighuan.tld文件中找有没有if这个<tag>标签,
4)找到对应的<tag>标签,再去读<tag-class>内容
5)得到IfTag对象,然后调用里面的方法,也就是执行IfTag的生命周期.
六,输出标签体<content-body>内容格式
JSP:表示支持jsp标本表达式取值,即<%= %>。只能在传统标签用,简单标签不支持!
empty:没有标签体
scriptless:标签体可以包含 el 表达式和 JSP 动作元素,但不能包含 JSP 的脚本元素
tagdependent:表示标签体交由标签本身去解析处理。若指定 tagdependent,在标签体中的所有代码都会原封不动的交给标签处理器,而不是将执行结果传递给标签处理器
七,简单标签的功能
控制执行标签体
控制不执行标签体
控制执行标签后面余下内容
控制不执行标签后面页面余下内容
重复执行标签体
修改标签体内容
八,高仿choose+when+otherwise标签
直接贴代码:
1)choose:
package com.bighuan.b_tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定义choose标签
*
* @author bighuan
*
*/
public class ChooseTag extends SimpleTagSupport {
private boolean flag;// 不是属性,而是临时变量
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void doTag() throws JspException, IOException {
// 直接执行标签体内容即可
this.getJspBody().invoke(null);
}
}
2)when
package com.bighuan.b_tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定义when标签
*
* @author bighuan
*
*/
public class WhenTag extends SimpleTagSupport {
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
ChooseTag parent = (ChooseTag) this.getParent();
parent.setFlag(test);
if (test) {
this.getJspBody().invoke(null);
}
}
}
3)otherwise
package com.bighuan.b_tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
* 自定义otherwise标签
*
* @author bighuan
*
*/
public class OtherwiseTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
// 得到父标签
ChooseTag chooseTag = (ChooseTag) this.getParent();
boolean test = chooseTag.isFlag();
// 如果when标签中test为false,则输出otherwise的标签体内容
if (!test) {
this.getJspBody().invoke(null);
}
}
}
4)配置tld文件
<!-- 自定义choose标签 -->
<tag>
<name>choose</name>
<tag-class>com.bighuan.b_tags.ChooseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<!-- 自定义when标签 -->
<tag>
<name>when</name>
<tag-class>com.bighuan.b_tags.WhenTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<!-- 支持EL表达式 -->
<rtexprvalue>true</rtexprvalue>
<type></type>
</attribute>
</tag>
<!-- 自定义otherwise标签 -->
<tag>
<name>otherwise</name>
<tag-class>com.bighuan.b_tags.OtherwiseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<!-- 自定义forEach标签 -->
<tag>
<name>forEach</name>
<tag-class>com.bighuan.b_tags.ForEachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
5)使用(记得导入标签库)
<bighuan:choose>
<bighuan:when test="${23<10 }">
条件成立,这是when标签!
</bighuan:when>
<bighuan:otherwise>
hey,这是otherwise标签!
</bighuan:otherwise>
</bighuan:choose>
十,总结
整理这篇博客花了好久时间呀,我的时间啊...坚持吧,bighuan!!!这就是我的总结......