天天看点

JSP之自定义标签

一,概述

在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!!!这就是我的总结......