一、自訂標籤入門之無參數自訂標籤
1.開發自訂標籤類
當我們在JSP頁面使用一個簡單的標籤時,底層實際上由標籤處理類提供支援,從而可以使用簡單的標籤來封裝複雜的功能,從而使團隊更好地協作開發(能讓美工人員更好地參與JSP頁面的開發)。
自訂標籤類都必須繼承一個父類:javax.servlet.jsp.tagext.SimpleTagSupport,或者TagSupport除此之外,JSP自訂標籤類還有如下要求。
如果標籤類包含屬性,每個屬性都有對應的getter和setter方法。
重寫doTag()或者doStartTag()或doEndTag()方法方法,這個方法負責產生頁面內容。
首先介紹是不帶屬性的標籤以HelloWorld為例:
Java代碼如下:
public class HelloWorldTag extends TagSupport { private static final long serialVersionUID = -3382691015235241708L; @Override public int doEndTag() throws JspException { try { pageContext.getOut().write("Hello World !"); return super.doEndTag(); } catch (JspException e) { e.printStackTrace(); return 0; } catch (IOException e) { e.printStackTrace(); return 0; } } @Override public int doStartTag() { try { pageContext.getOut().write("Hello World"); return super.doStartTag(); } catch (JspException e) { e.printStackTrace(); return 0; } catch (IOException e) { e.printStackTrace(); return 0; } }}
注意:
問題1:tagsupport中的dostartTag和doEndTag這兩個方法有什麼區別
doStartTag是在掃描到起始標籤時調用,doEndTag是在掃描到結束標籤是調用。
例如:<helloWorld> helloWorld</helloWorld>
則jsp引擎分析到<helloWorld> 時調用doStratTag, 分析到</helloWorld>時調用doEndTag
2、建立TLD檔案
TLD是Tag Library Definition的縮寫,即標籤庫定義,檔案的尾碼是tld,每個TLD檔案對應一個標籤庫,一個標籤庫中可包含多個標籤,TLD檔案也稱為標籤庫定義檔案。
標籤庫定義檔案的根項目是taglib,它可以包含多個tag子項目,每個tag子項目都定義一個標籤。通常我們可以到Web容器下複製一個標籤庫定義檔案,並在此基礎上進行修改即可。例如Tomcat6.0,在webapps\examples\WEB-INF\jsp2路徑下包含了一個jsp2-example-taglib.tld檔案,這就是示範用的標籤庫定義檔案。
將該檔案複製到Web應用的WEB-INF/路徑,或WEB-INF的任意子路徑下,並對該檔案進行簡單修改,修改後的helloworld.tld檔案代碼如下:
<?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 web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <short-name>myhelloworld</short-name> <!-- 定義該標籤庫的URI 必須添加但可以空--> <uri></uri> <!-- 定義第一個標籤 --> <tag> <!-- 定義標籤名 --> <name>helloWorld</name> <!-- 定義標籤處理類 --> <tag-class>org.lxh.taglib.HelloWorldTag</tag-class> <!-- 定義標籤體為空白 --> <body-content>empty</body-content> </tag></taglib>
問題1: 為什麼要用TagSupport與BodyTagSupport的區別主要是標籤處理類是否需要與標籤體互動,如果不需要互動的就用TagSupport,否則就用BodyTagSupport。
互動就是標籤處理類是否要讀取標籤體的內容和改變標籤體返回的內容。用TagSupport實現的標籤,都可以用BodyTagSupport來實現,因為BodyTagSupport繼承了TagSupport而不去實現IterationTag介面的,因為BodyTagSupport繼承了TagSupport類,並且該類已經實現了IterationTag介面並且實現了功能.
doStartTag()方法在標籤開始時執行,要記住每次都要對類進行初始化,避免上一次的遺留資料對操作造成影響。然後判斷是否有資料需要處理,如果有,則返回EVAL_BODY_INCLUDE開始處理標籤裡的內容,如果沒有,返回 EVAL_PAGE跳過標籤內容執列標籤下面的內容。
doAfterBody()方法在每次處理完標籤內部內容後執行,判斷迴圈是否已經結束,如果可以繼續迴圈,返回EVAL_BODY_AGAIN用迴圈得到新的資料再次處理標籤內部內容,如果迴圈結束就返回EVAL_PAGE結束標籤。
二、自訂JSP標籤的處理過程:
1.在JSP中引入標籤庫:
2.在JSP中使用標籤庫標籤
3.Web容器根據第二個步驟中的prefix,獲得第一個步驟中聲明的taglib的uri屬性值
4.Web容器根據uri屬性在web.xml找到對應的元素
5.從元素中獲得對應的元素的值
6.Web容器根據元素的值從WEB-INF/目錄下找到對應的.tld檔案
7.從.tld檔案中找到與tagname對應的元素
8.湊元素中獲得對應的元素的值
9.Web容器根據元素的值建立相應的tag handle class的執行個體
10. Web容器調用這個執行個體的doStartTag/doEndTag方法完成相應的處理
三、建立和使用一個Tag Library的基本步驟:
1.建立標籤的處理類(Tag Handler Class)
2.建立標籤庫描述檔案(Tag Library Descrptor File)
3.在web.xml檔案中配置元素
4.在JSP檔案中引人標籤庫
四、TagSupport類簡介:
1.處理標籤的類必須擴充javax.servlet.jsp.TagSupport.
2.TagSupport類的主要屬性:
A.parent屬性:代表嵌套了當前標籤的上層標籤的處理類
B.pageContex屬性:代表Web應用中的javax.servlet.jsp.PageContext對象
3.JSP容器在調用doStartTag或者doEndTag方法前,會先調用setPageContext和setParent方法,設定pageContext和parent。因此在標籤處理類中可以直接存取pageContext變數
4.在TagSupport的構造方法中不能訪問pageContext成員變數,因為此時JSP容器還沒有調用setPageContext方法對pageContext進行初始化
五、TagSupport處理標籤的方法:
1.TagSupport類提供了兩個處理標籤的方法:
public int doStartTag() throws JspException
public int doEndTag() throws JspException
2.doStartTag:但JSP容器遇到自訂標籤的起始標誌,就會調用doStartTag()方法,doStartTag()方法返回一個整數值,用來決定程式的後續流程。
A.Tag.SKIP_BODY:表示跳過了開始和結束標籤之間的代碼
B.Tag.EVAL_BODY_INCLUDE:表示標籤之間的內容被正常執行
C.Tag.EVAL_BODY_BUFFERED :對包含的內容進行解析
3.doEndTag:但JSP容器遇到自訂標籤的結束標誌,就會調用doEndTag()方法。doEndTag()方法也返回一個整數值,用來決定程式後續流程。
A.Tag.SKIP_PAGE:表示立刻停止執行網頁,網頁上未處理的靜態內容和JSP程式均被忽略任何已有的輸出內容立刻返回到客戶的瀏覽器上。
B.Tag.EVAL_PAGE:表示按照正常的流程繼續執行JSP網頁
4.doAfterTag:遇到標籤體執行
A.Tag.EVAL_BODY_AGAIN;// 如果集合中還有對像,則迴圈執列標籤體,對標籤體迴圈處理,(存在於javax.servlet.jsp.tagext.IterationTag介面中)
B.Tag.SKIP_BODY
六、建立含有欄位的標籤:
1.建立標籤處理器類FieldTag
package com.able.tag; import java.io.IOException; import javax.servlet.jsp.JspException;import javax.servlet.jsp.JspWriter;import javax.servlet.jsp.tagext.TagSupport; public class FieldTag extends TagSupport { private static final long serialVersionUID = 1540529069962423355L; private String field; private Integer count; @Override public int doEndTag() throws JspException { try { JspWriter out = pageContext.getOut(); out.print(field); out.print(count); } catch (IOException e) { e.printStackTrace(); } return super.doEndTag(); } public String getField() { return field; } public void setField(String field) { this.field = field; } public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } }
2.在tag.tld檔案中天劍tag標籤
<tag> <!-- 定義標籤名 --> <name>field</name> <!-- 定義標籤處理類 --> <tag-class>com.able.tag.FieldTag</tag-class> <!-- 定義標籤體為空白 --> <body-content>empty</body-content> <attribute> <name>field</name> <required>true</required> <!-- 是否必須賦值 --> <rtexprvalue>true</rtexprvalue><!-- 表示是否接受jsp文法或者el語言或其他動態語言,預設false --> </attribute> <attribute> <name>count</name> <rtexprvalue>true</rtexprvalue> </attribute></tag>
3.jsp中定義標籤:
<tm:field field="11" count="22"/>
七、如何建立標籤處理類
1、引入必需的資源
import javax.servlet.jsp.*; import javax.servlet.http.*; import java.util.*; import java.io.*;
2、繼承TagSupport類並覆蓋doStartTag()/doEndTag()方法
3、從ServletContext對象中擷取java.util.Properties對象
4、從Properties對象中擷取key對應的屬性值
5、對擷取的屬性進行相應的處理並輸出結果
建立標籤庫描述檔案(Tag Library Descriptor)
1、標籤庫描述檔案,簡稱TLD,採用XML檔案格式,定義了使用者的標籤庫。TLD檔案中的元素可以分成3類:
A.標籤庫元素
B.標籤元素
C.標籤屬性元素
2、標籤庫元素用來設定標籤庫的相關資訊,它的常用屬性有:
A.shortname:指定Tag Library預設的首碼名(prefix);
B.uri:設定Tag Library的惟一訪問表示符。
3、標籤元素用來定義一個標籤,它的常見屬性有:
A.name:設定Tag的名字;
B.tagclass:設定Tag的處理類;
C.bodycontent:設定標籤的主體(body)內容。
1)empty:表示標籤中沒有body;
2)JSP:表示標籤的body中可以加入JSP程式碼;
3)tagdependent:表示標籤中的內容由標籤自己去處理。
4、標籤屬性元素用來定義標籤的屬性,它的常見屬性有:
A.name:屬性名稱;
B.required:屬性是否必需的,預設為false;
C.rtexprvalue:屬性值是否可以為request-time運算式,也就是類似於< %=…% >的運算式。
八、在Web應用中使用標籤
1、如果Web應用中用到了自訂JSP標籤,則必須在web.xml檔案中加入元素,它用於聲明所引用的標籤所在的標籤庫
/sometaglib
/WEB-INF/someTLD.tld
2、設定Tag Library的惟一標示符,在Web應用中將根據它來引用Tag Libray;
3、指定和Tag Library對應的TLD檔案的位置;
4、在JSP檔案中需要加入<!-- taglib% >指令來聲明對標籤庫的引用。
5、prefix表示在JSP網頁中引用這個標籤庫的標籤時的首碼,uri用來指定Tag Library的標識符,它必須和web.xml中的屬性保持一致。
九、案例:
4.1.建立標籤描述符檔案
在WEB-INF檔案下建立*.tld標籤描述符檔案:如
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>eRedLab JSPTag Library</shortname>
<uri>/testTag</uri>
<info>自訂標籤測試</info>
<tag>
<name>hello</name>
<tagclass>com.eredlab.taglib.test.TestTld</tagclass>
<bodycontent>empty</bodycontent>
<info>自訂標籤測試</info>
<attribute>
<name>begin</name>
<required>true</required>
</attribute>
<attribute>
<name>end</name>
<required>true</required>
</attribute>
</tag>
</taglib>
4.2.建立標籤處理器
/**
* @desc 自訂標籤測試類別 實現一個簡單的Hello World標籤
* @author 夏中偉
* @version eRedLab 2007-9-10
*/
public class TestTld extends TagSupport{
//標籤屬性begin
private String begin = null;
//標籤屬性end
private String end = null;
//建構函式
public TestTld(){
}
/* 標籤初始方法 */
public int doStartTag() throws JspTagException{
return super.EVAL_BODY_INCLUDE;
}
/* 標籤結束方法 */
public int doEndTag() throws JspTagException{
JspWriter out = pageContext.getOut();
String sum = begin + end;
try{
//標籤的傳回值
out.println(sum);
}catch(IOException e){
e.printStackTrace();
}
return super.SKIP_BODY;
}
/* 釋放資源 */
public void release(){
super.release();
}
/********************************************
屬性get()、set()方法
*******************************************/
}
在Web.XML中載入標籤描述符檔案.
<!-- 載入標籤描述符檔案 -->
<taglib>
<taglib-uri>/WEB-INF/test.tld</taglib-uri>
<taglib-location>/WEB-INF/test.tld</taglib-location>
</taglib>
5.2.在JSP中使用此標籤
<%@ taglib uri="/testTag" prefix="mytag"%>
<mytag:hello end="夏中偉!" begin="自訂標籤輸出資料流:Hello,"/>
<mytag:hello end="World!" begin="Hi,"/>
WEB頁面輸出結果如下:
自訂標籤輸出資料流:Hello,夏中偉! Hi,World!
迴圈標籤體類:ForEach.java 1import java.util.Collection; 2import java.util.Iterator; 3 4import javax.servlet.jsp.JspException; 5import javax.servlet.jsp.tagext.BodyContent; 6import javax.servlet.jsp.tagext.BodyTagSupport; 7 8public class ForEach extends BodyTagSupport 9{10 private String id;11 private String collection;12 private Iterator iter;13 14 public void setCollection(String collection)15 {16 this.collection = collection;17 }18 public void setId(String id)19 {20 this.id = id;21 }22 23 //遇到開始標籤執行24 public int doStartTag() throws JspException25 {26 Collection coll = (Collection) pageContext.findAttribute(collection);27 // 表示如果未找到指定集合,則不用處理標籤體,直接調用doEndTag()方法。28 if(coll==null||coll.isEmpty()) return SKIP_BODY;29 30 iter = coll.iterator();31 pageContext.setAttribute(id, iter.next());32 // 表示在現有的輸出資料流對象中處理標籤體,但繞過setBodyContent()和doInitBody()方法33 // 這裡一定要返回EVAL_BODY_INCLUDE,否則標籤體的內容不會在網頁上輸出顯示34 return EVAL_BODY_INCLUDE;35 }36 37 //在doInitBody方法之前執行,在這裡被繞過不執行38 @Override39 public void setBodyContent(BodyContent arg0)40 {41 System.out.println("setBodyContent");42 super.setBodyContent(arg0);43 }44 //此方法被繞過不會被執行45 @Override46 public void doInitBody() throws JspException47 {48 System.out.println("doInitBody");49 super.doInitBody();50 }51 52 //遇到標籤體執行53 public int doAfterBody() throws JspException54 {55 if(iter.hasNext()) 56 {57 pageContext.setAttribute(id, iter.next());58 return EVAL_BODY_AGAIN;// 如果集合中還有對像,則迴圈執列標籤體59 }60 return SKIP_BODY;//迭代完集合後,跳過標籤體,調用doEndTag()方法。61 }62 63 //遇到結束標籤執行64 public int doEndTag() throws JspException65 {66 System.out.println("doEndTag");67 return EVAL_PAGE;68 }6970} 擷取VO屬性類:GetProperty.java 1import java.lang.reflect.Method; 2 3import javax.servlet.jsp.JspException; 4import javax.servlet.jsp.tagext.BodyTagSupport; 5 6public class GetProperty extends BodyTagSupport 7{ 8 9 private String name;10 private String property;1112 public void setName(String name)13 {14 this.name = name;15 }1617 public void setProperty(String property)18 {19 this.property = property;20 }2122 @SuppressWarnings("unchecked")23 public int doStartTag() throws JspException24 {25 try26 {27 Object obj = pageContext.findAttribute(name);28 29 if (obj == null) return SKIP_BODY;30 31 Class c = obj.getClass();32 //構造GET方法名字 get+屬性名稱(屬性名稱第一個字母大寫)33 String getMethodName = "get" + property.substring(0, 1).toUpperCase() 34 + property.substring(1, property.length());35 Method getMethod = c.getMethod(getMethodName, new Class[]{});36 37 pageContext.getOut().print(getMethod.invoke(obj));38 System.out.print(property + ":" + getMethod.invoke(obj) + "t");39 } catch (Exception e)40 {41 e.printStackTrace();42 }43 return SKIP_BODY;44 }4546 public int doEndTag() throws JspException47 {48 return EVAL_PAGE;49 }50}5152運算式直接存取此類中靜態方法:ELFunction.java53public class ELFunction 54{55 public static int add( int i,int j )56 {57 return i+j;58 }59} 寫一個測試用的VO類:UserVo.java 1public class UserVo 2{ 3 private String name; 4 private String password; 5 6 public String getName() 7 { 8 return name; 9 }10 public void setName(String name)11 {12 this.name = name;13 }14 public String getPassword()15 {16 return password;17 }18 public void setPassword(String password)19 {20 this.password = password;21 }22} 建好TLD檔案tag.tld,放在WEB-INF目錄下 1<?xml version="1.0" encoding="utf-8"?> 2<taglib version="2.0" 3 xmlns="http://java.sun.com/xml/ns/j2ee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xmlns:shcemalocation="http://java.sun.com/xml/ns/j2ee 6 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 7 8 <description>自訂標籤</description> 9 <display-name>JSTL core</display-name>10 <tlib-version>1.1</tlib-version>11 <short-name>firstLabel</short-name>12 <uri>http://java.sun.com/jsp/jstl/core</uri>1314 <!-- 建立自訂 迭代標籤 -->15 <tag>16 <name>forEach</name>17 <tag-class>exercise.taglib.ForEach</tag-class>18 <!-- 如果沒有標籤體,設定empty , 如果有標籤休必須設定JSP-->19 <body-content>JSP</body-content>20 <attribute>21 <name>id</name>22 <required>true</required><!-- 識別屬性是否是必須的 -->23 <rtexprvalue>true</rtexprvalue><!-- 識別屬性值是否可以用運算式語言 -->24 </attribute>25 <attribute>26 <name>collection</name>27 <required>true</required>28 <rtexprvalue>true</rtexprvalue>29 </attribute>30 </tag>3132 <!-- 建立自訂獲得屬性標籤 -->33 <tag>34 <name>getProperty</name>35 <tag-class>exercise.taglib.GetProperty</tag-class>36 <body-content>empty</body-content>37 <attribute>38 <name>name</name>39 <required>true</required>40 <rtexprvalue>true</rtexprvalue>41 </attribute>42 <attribute>43 <name>property</name>44 <required>true</required>45 <rtexprvalue>true</rtexprvalue>46 </attribute>47 </tag>4849 <!-- 配置一個運算式調用 的函數 -->50 <function>51 <name>add</name><!-- 配置一個標籤,在JSP頁面通過引用首碼調用 -->52 <function-class>exercise.taglib.ELFunction</function-class><!-- 實作類別 -->53 <function-signature>int add(int,int)</function-signature><!-- 靜態方法:包括傳回型別,方法名,入參的類型 -->54 </function>55</taglib>
在web.xml檔案中配置自訂標籤
<jsp-config> <taglib> <taglib-uri>firstTag</taglib-uri> <taglib-location>/WEB-INF/tag.tld</taglib-location> </taglib></jsp-config> 在jsp檔案中使用標籤:tag.jsp<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%@ taglib uri="firstTag" prefix="my"%><jsp:useBean id="userVo1" class="exercise.vo.UserVo" scope="request"> <jsp:setProperty name="userVo1" property="name" value="Hackiller"/> <jsp:setProperty name="userVo1" property="password" value="123"/></jsp:useBean><jsp:useBean id="userVo2" class="exercise.vo.UserVo" scope="request"> <jsp:setProperty name="userVo2" property="name" value="YangYang"/> <jsp:setProperty name="userVo2" property="password" value="456"/></jsp:useBean><% List list = new ArrayList(); list.add(userVo1); list.add(userVo2); pageContext.setAttribute("voList",list);%><html> <head> <title>My JSP 'tag.jsp' starting page</title> </head> <body> <h2 align="center">This is my JSP page:測試taglib.</h2> <hr> <h2>自訂迭代標籤:</h2> <table> <tr><td>姓名</td><td>密碼</td></tr> <my:forEach collection="voList" id="uservo"> <tr> <td><my:getProperty name="uservo" property="name"/></td> <td><my:getProperty name="uservo" property="password"/></td> </tr> </my:forEach> </table> <hr> <h2>運算式調用類的靜態方法:</h2> 2+5=${my:add(2,5)} </body></html>
以上就是小編為大家帶來的jsp中自訂Taglib詳解全部內容了,希望大家多多支援雲棲社區~