一,概述
在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!!!這就是我的總結......