天天看點

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!!!這就是我的總結......

繼續閱讀