【實例109】? 開發帶屬性的標簽:helloTagHaveProp
本實例中開發的標簽在實例108的helloTag標簽上作出改進,開發目標是在helloTag標簽上增加兩個屬性fontSize和fontColor,fontSize用于設置字體大小,fontColor用于設置文字的顏色。
(1)第一步:開發標簽實現類。
helloTagHaveProp.java
package hello;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
public class helloTagHaveProp extends TagSupport {
??? private String fontSize="3";//字體大小,默認3號
??? private String fontColor="#000000";//字體顏色,默認黑色
??? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽開始了。<font color=\""+fontColor +
???????????????? "\" size=\""+fontSize+"\">hello!</font>");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_BODY_INCLUDE;
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽結束了。");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public String getFontColor() {?
??????? return fontColor;
??? }
??? public void setFontColor(String fontColor) {
??????? this.fontColor = fontColor;
??? }
??? public String getFontSize() {
??????? return fontSize;
??? }
??? public void setFontSize(String fontSize) {
??????? this.fontSize = fontSize;
?? }
}
?。?)第二步:編寫標簽描述tld文件。這里在myTag.tld文件中增加內容,在<taglib>與</taglib>之間增加的內容如下:
<!-- helloTagHaveProp-->
<tag>
???? <!-- 標簽名稱-->
???? <name>helloTagHaveProp</name>
???? <!-- 標簽對應的處理類-->
???? <tag-class>hello.helloTagHaveProp</tag-class>
???? <!-- 標簽體內容,沒有標簽體則設為empty-->
???? <body-content>empty</body-content>
???? <!-- 標簽的屬性聲明-->
???? <attribute>
????? <name>fontSize</name>
????? <required>false</required>
???? </attribute>
???? <attribute>
????? <name>fontColor</name>
????? <required>false</required>
???? </attribute>
</tag>
其中,name為屬性的名稱,required設置此屬性是否必須設置,如果為true則在JSP頁面中使用此標簽時,必須給標簽的這個屬性賦值。
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。本例與實例108使用同一個tld文件,故不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
useHelloTagHaveProp.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<html>
? <head>
<title>一個簡單的自定義標簽</title>
</head>
<body>
?? 下面是應用這個簡單的自定義標簽的結果:<br>
? <myTag:helloTagHaveProp fontSize="5"/><br>
? <myTag:helloTagHaveProp fontSize="4" fontColor="red"/>
? </body>
</html>
程序的運行結果如圖13-3所示。
三、 開發帶標簽體的標簽
要開發帶標簽體的標簽,可實現BodyTag接口,也可從BodyTag接口的實現類BodyTagSupport繼承,為簡化開發,推薦從BodyTagSupport類繼承開發。
編寫標簽對應的實現類時,需要重載BodyTagSupport類幾個方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),他們執行順序如下:doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_ INCLUDE則繼續執行;如果返回SKIP_BODY則接下來的doInitBody(),setBodyContent(), doAfterBody()三個方法不會被執行,而直接執行doEndTag()方法。
setBodyContent()方法用于設置標簽體內容,如果在此之前要作一些初始化工作,則在doInitBody()方法中完成。標簽體內容執行完后,會調用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY,
EVAL_PAGE或SKIP_PAGE。如果返回EVAL_BODY_TAG則會再次設置標簽體內容,直到返回SKIP_BODY;如果返回EVAL_PAGE則標簽體執行完后會繼續執行JSP頁面中接下來的部分;如果返回SKIP_PAGE,則JSP頁面的后續內容將不再執行。
【實例110】? 開發帶標簽體的標簽:bodyTag1
本實例將要開發一個帶標簽體的標簽bodyTag1,這個標簽有一個屬性countNum,用于設置輸出標簽體內容的次數,輸出內容為當前的系統時間。
(1)第一步:開發標簽實現類。
BodyTag1.java
package body;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class bodyTag1 extends BodyTagSupport{
??? private int countNum=0;//循環顯示時間的次數
??? private int currentNum=1;//當前執行次數
??? //----標簽開始時調用此方法-------
?? public int doStartTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽開始了:<br>");
??????????? if(countNum>0)
??????????????? return EVAL_BODY_TAG;
??????????? else
??????????????? return SKIP_BODY;
???????????
??????? }catch(Exception e){
??????????? System.out.println(e);
??????????? return SKIP_BODY;
??????? }
??? }
??? //----標簽體執行完后調用此方法----
??? public int doAfterBody(){
??????? try{
???????? JspWriter out=pageContext.getOut();
???????? out.print("第"+currentNum+"次執行標簽體。標簽體執行完畢。<br>");
???????? if(countNum>1){//如果還需要執行標簽體
???????????? countNum--;
???????????? currentNum++;
???????????? return EVAL_BODY_TAG;
???????? }else return SKIP_BODY;
??????? }catch(Exception e){
??????????? System.out.println(e);
??????????? return SKIP_BODY;
??????? }
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? //----輸出標簽體的內容----
??????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????????? out.print("標簽結束了。");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public int getCountNum() {
??????? return countNum;
??? }
??? public void setCountNum(int countNum) {
??????? this.countNum = countNum;
??????? this.currentNum=1;
? ? }
}
執行標簽體并不會直接輸出標簽體中的內容,因此本實例在doEndTag()方法中一次性把執行的結果輸出。
?。?)第二步:編寫標簽描述tld文件。
因為本章所有實例共用一個Web應用,故本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加的內容如下:
<!-- bodyTag1-->
<tag>
? <!-- 標簽名稱-->
? <name>bodyTag1</name>
? <!-- 標簽對應的處理類-->
? <tag-class>body.bodyTag1</tag-class>
? <!-- 標簽體內容,有標簽體則設為jsp-->
? <body-content>jsp</body-content>
? <!-- 標簽的屬性聲明-->
? <attribute>
?? <name>countNum</name>
?? <required>true</required>
?? <rtexprvalue>true</rtexprvalue>
? </attribute>
</tag>
對于屬性countNum的聲明中,<required>設置為true,表示此屬性為必輸項;<rtexprvalue>設置為true,表示標簽體支持運行時的表達式取值,如果為false則表示標簽體為一個靜態文本,默認情況下設置為true。
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。
同樣,本例與實例108使用同一個tld文件,不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
UseBodyTag1.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.Date" %>
<html>
? <head>
? <title>開發帶有標簽體的標簽</title>
? </head>
? <body>
? 下面是應用這個帶有屬性的自定義標簽的結果:<br>
? <myTag:bodyTag1 countNum="6">
?? 現在的時間是:<%=new Date()%><br>
? </myTag:bodyTag1>
</body>
</html>
該程序的運行結果如圖13-4所示。
【實例111】? 開發嵌套的標簽:haveChildTag
實際工程中往往需要多個標簽來配合完成一定的功能,嵌套的標簽存在父子關系,其中,父為外層標簽,子為內層標簽。本實例將用兩個簡單的標簽來演示,父標簽則作出邏輯判斷,如果isOutput屬性為true,則輸出實例108中的標簽helloTag;如果為false,則不輸出。
(1)第一步:開發標簽實現類。
內層的標簽helloTag在實例108中已有,此處不再列出。
haveChildTag.java
package hello;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class haveChildTag extends BodyTagSupport {
?? private boolean isOutput;//是否輸出子標簽內容
??? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? if(isOutput)
??????????? return EVAL_BODY_INCLUDE;
??????? else return SKIP_BODY;
?? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
????? ? try{
?????????? if(bodyContent!=null)
??????????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public boolean getIsOutput() {
??????? return isOutput;
?? }
??? public void setIsOutput(boolean isOutput) {
?????? this.isOutput = isOutput;
??? }
}
?。?)第二步:編寫標簽描述tld文件。
本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加的如下內容:
<!-- haveChildTag-->
<tag>
? <!-- 標簽名稱-->
? <name>haveChildTag</name>
? <!-- 標簽對應的處理類-->
? <tag-class>hello.haveChildTag</tag-class>
? <!-- 標簽體內容,有標簽體則設為jsp-->
? <body-content>jsp</body-content>
? <!-- 標簽的屬性聲明-->
? <attribute>
?? <name>isOutput</name>
?? <required>true</required>
?? <rtexprvalue>true</rtexprvalue>
? </attribute>
</tag>
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。
同樣,本例與本章前面的實例使用同一個tld文件,此處不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
useHaveChildTag.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.Date" %>
<html>
<head>
<title>開發嵌套的標簽</title>
</head>
? <body>
? 輸出子標簽時的結果:<br>
? <myTag:haveChildTag isOutput="true">
?? <myTag:helloTag/>
? </myTag:haveChildTag><br>
? 不輸出子標簽時的結果:<br>
? <myTag:haveChildTag isOutput="false">
?? <myTag:helloTag/>
? </myTag:haveChildTag><br>
</body>
</html>
該程序的運行結果如圖13-5所示。
《JSP網絡編程從實踐到實踐》原碼下載地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575????
五、 開發迭代的標簽
【實例112】? 開發迭代的標簽:iterateTag
對于集合對象的Iterator類對象,在JSP的Java代碼中需要用while循環或for循環來輸出,難于維護,且可復用性不好,程序員總是在大量地做這樣的工作,這時可以考慮用迭代的標簽來開發,需要輸出數據時只須在JSP頁面中聲明標簽即可。
開發迭代的標簽,需要設計兩個Java類:標簽實現類和表示標簽信息的類。本實例中標簽實現類為iterateTag.java,表示標簽信息的類為IterateTEI.java。開發迭代的標簽可實現IterationTag接口,也可從TagSupport類或BodyTagSupport類繼承,由于BodyTagSupport類繼承自TagSupport類,而TagSupport類又實現了IterationTag接口,為簡化開發,直接從BodyTagSupport類繼承即可。
?。?)第一步:開發標簽實現類和表示標簽信息的類。
iterateTag.java
package body;
import java.util.Collection;
import java.util.Iterator;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class iterateTag extends BodyTagSupport{
??? private String name;//在pageContext中標識的一個屬性名
??? private Iterator it;//要迭代的對象
??? private String type;//it中對象的類型
?? public void setCollection(Collection collection){
?????? if(collection.size()>0)
?????????? it=collection.iterator();
?? }
???
?? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? if(it==null) return SKIP_BODY;
??????? else return continueNext(it);
??? }
??? //----標簽體執行完后調用此方法----
??? public int doAfterBody(){
??????? return continueNext(it);
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? if(bodyContent!=null)
??????????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????? }catch(Exception e){
??????????? System.out.println(e);
????? ? }
????? ? return EVAL_PAGE;
?? }?
??? //----迭代----
??? protected int continueNext(Iterator it){
??????? if(it.hasNext()){
??????????? pageContext.setAttribute(name,it.next(),pageContext.PAGE_SCOPE);
?????????? return EVAL_BODY_TAG;
??????? }else return SKIP_BODY;
??? }
?? public String getName() {
?????? return name;
??? }
??? public void setName(String name) {
???? ?? this.name = name;
?? }
?? public String getType() {
??? ??? return type;
??? }
??? public void setType(String type) {
???? ?? this.type = type;
?? }
}
在標簽實現類中,有3個屬性:name、type和it。其中,name代表在pageContext中標識一個屬性的名字;type代表待迭代內容的數據類型;it為要迭代的內容。在doStartTag()方法中,如果it不為null,就開始迭代,迭代時調用continueNext()方法。
IterateTEI.java
package body;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;
//----提供標簽翻譯時的一些相關信息----
public class IterateTEI extends TagExtraInfo {
? ? public IterateTEI() {
?????? super();
?? }
?? public VariableInfo[] getVariableInfo(TagData data){
???? ?? return new VariableInfo[]{
??????? ??????? new VariableInfo(data.getAttributeString("name"),
??????????????????????? data.getAttributeString("type"),
??????????????????????? true,VariableInfo.NESTED)?????????????
??????? };
??? }
}
VariableInfo類中有幾個常量,具體的含義為:
NESTED:標簽中的參數在標簽開始到標簽結束之間是有效的。
AT_BEGIN:標簽中的參數在標簽開始到使用它的JSP頁面結束是有效的。
AT_END:標簽中的參數在標簽的結束到使用它的JSP頁面結束是有效的。
?。?)第二步:編寫標簽描述tld文件。本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加如下內容:
?? <!-- iterateTag-->
?? <tag>
????? <!-- 標簽名稱-->
????? <name>iterateTag</name>
????? <!-- 標簽對應的處理類-->
????? <tag-class>body.iterateTag</tag-class>
????? <tei-class>body.IterateTEI</tei-class>
????? <!-- 標簽體內容,有標簽體則設為jsp-->
????? <body-content>jsp</body-content>
????? <!-- 標簽的屬性聲明-->
????? <attribute>
?????? <name>collection</name>
?????? <required>true</required>
?????? <rtexprvalue>true</rtexprvalue>
????? </attribute>
????? <attribute>
?????? <name>name</name>
?????? <required>true</required>
????? </attribute>
????? <attribute>
?????? <name>type</name>
?????? <required>true</required>
????? </attribute>
? ? </tag>
</taglib>
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。同樣,本例與本章前面的實例使用同一個tld文件,因此不必再修改。
(4)第四步:在JSP頁面中聲明并調用標簽。
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.ArrayList"%>
? <head>
? <title>開發迭代的標簽</title>
? </head>
<body>
? 開發一個迭代的標簽,輸出結果:<br>
? <%//----------設置一個ArrayList對象的初始值----------
?? ArrayList testCol=new ArrayList();
?? testCol.add("鄧佳容");
?? testCol.add("黃婧");
?? testCol.add("鄧子云");
?? request.setAttribute("testCol",testCol);
%>
? <myTag:iterateTag name="testColOne" collection="<%=testCol%>" type="String">
?? 輸出一個值:<%=testColOne.toString()%><br>
</myTag:iterateTag>
</body>
</html>
該程序的運行結果如圖13-6所示。
本實例中開發的標簽在實例108的helloTag標簽上作出改進,開發目標是在helloTag標簽上增加兩個屬性fontSize和fontColor,fontSize用于設置字體大小,fontColor用于設置文字的顏色。
(1)第一步:開發標簽實現類。
helloTagHaveProp.java
package hello;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
public class helloTagHaveProp extends TagSupport {
??? private String fontSize="3";//字體大小,默認3號
??? private String fontColor="#000000";//字體顏色,默認黑色
??? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽開始了。<font color=\""+fontColor +
???????????????? "\" size=\""+fontSize+"\">hello!</font>");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_BODY_INCLUDE;
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽結束了。");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public String getFontColor() {?
??????? return fontColor;
??? }
??? public void setFontColor(String fontColor) {
??????? this.fontColor = fontColor;
??? }
??? public String getFontSize() {
??????? return fontSize;
??? }
??? public void setFontSize(String fontSize) {
??????? this.fontSize = fontSize;
?? }
}
?。?)第二步:編寫標簽描述tld文件。這里在myTag.tld文件中增加內容,在<taglib>與</taglib>之間增加的內容如下:
<!-- helloTagHaveProp-->
<tag>
???? <!-- 標簽名稱-->
???? <name>helloTagHaveProp</name>
???? <!-- 標簽對應的處理類-->
???? <tag-class>hello.helloTagHaveProp</tag-class>
???? <!-- 標簽體內容,沒有標簽體則設為empty-->
???? <body-content>empty</body-content>
???? <!-- 標簽的屬性聲明-->
???? <attribute>
????? <name>fontSize</name>
????? <required>false</required>
???? </attribute>
???? <attribute>
????? <name>fontColor</name>
????? <required>false</required>
???? </attribute>
</tag>
其中,name為屬性的名稱,required設置此屬性是否必須設置,如果為true則在JSP頁面中使用此標簽時,必須給標簽的這個屬性賦值。
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。本例與實例108使用同一個tld文件,故不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
useHelloTagHaveProp.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<html>
? <head>
<title>一個簡單的自定義標簽</title>
</head>
<body>
?? 下面是應用這個簡單的自定義標簽的結果:<br>
? <myTag:helloTagHaveProp fontSize="5"/><br>
? <myTag:helloTagHaveProp fontSize="4" fontColor="red"/>
? </body>
</html>
程序的運行結果如圖13-3所示。
三、 開發帶標簽體的標簽
要開發帶標簽體的標簽,可實現BodyTag接口,也可從BodyTag接口的實現類BodyTagSupport繼承,為簡化開發,推薦從BodyTagSupport類繼承開發。
編寫標簽對應的實現類時,需要重載BodyTagSupport類幾個方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag(),他們執行順序如下:doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_ INCLUDE則繼續執行;如果返回SKIP_BODY則接下來的doInitBody(),setBodyContent(), doAfterBody()三個方法不會被執行,而直接執行doEndTag()方法。
setBodyContent()方法用于設置標簽體內容,如果在此之前要作一些初始化工作,則在doInitBody()方法中完成。標簽體內容執行完后,會調用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY,
EVAL_PAGE或SKIP_PAGE。如果返回EVAL_BODY_TAG則會再次設置標簽體內容,直到返回SKIP_BODY;如果返回EVAL_PAGE則標簽體執行完后會繼續執行JSP頁面中接下來的部分;如果返回SKIP_PAGE,則JSP頁面的后續內容將不再執行。
【實例110】? 開發帶標簽體的標簽:bodyTag1
本實例將要開發一個帶標簽體的標簽bodyTag1,這個標簽有一個屬性countNum,用于設置輸出標簽體內容的次數,輸出內容為當前的系統時間。
(1)第一步:開發標簽實現類。
BodyTag1.java
package body;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class bodyTag1 extends BodyTagSupport{
??? private int countNum=0;//循環顯示時間的次數
??? private int currentNum=1;//當前執行次數
??? //----標簽開始時調用此方法-------
?? public int doStartTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? out.print("標簽開始了:<br>");
??????????? if(countNum>0)
??????????????? return EVAL_BODY_TAG;
??????????? else
??????????????? return SKIP_BODY;
???????????
??????? }catch(Exception e){
??????????? System.out.println(e);
??????????? return SKIP_BODY;
??????? }
??? }
??? //----標簽體執行完后調用此方法----
??? public int doAfterBody(){
??????? try{
???????? JspWriter out=pageContext.getOut();
???????? out.print("第"+currentNum+"次執行標簽體。標簽體執行完畢。<br>");
???????? if(countNum>1){//如果還需要執行標簽體
???????????? countNum--;
???????????? currentNum++;
???????????? return EVAL_BODY_TAG;
???????? }else return SKIP_BODY;
??????? }catch(Exception e){
??????????? System.out.println(e);
??????????? return SKIP_BODY;
??????? }
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? JspWriter out=pageContext.getOut();
??????????? //----輸出標簽體的內容----
??????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????????? out.print("標簽結束了。");
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public int getCountNum() {
??????? return countNum;
??? }
??? public void setCountNum(int countNum) {
??????? this.countNum = countNum;
??????? this.currentNum=1;
? ? }
}
執行標簽體并不會直接輸出標簽體中的內容,因此本實例在doEndTag()方法中一次性把執行的結果輸出。
?。?)第二步:編寫標簽描述tld文件。
因為本章所有實例共用一個Web應用,故本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加的內容如下:
<!-- bodyTag1-->
<tag>
? <!-- 標簽名稱-->
? <name>bodyTag1</name>
? <!-- 標簽對應的處理類-->
? <tag-class>body.bodyTag1</tag-class>
? <!-- 標簽體內容,有標簽體則設為jsp-->
? <body-content>jsp</body-content>
? <!-- 標簽的屬性聲明-->
? <attribute>
?? <name>countNum</name>
?? <required>true</required>
?? <rtexprvalue>true</rtexprvalue>
? </attribute>
</tag>
對于屬性countNum的聲明中,<required>設置為true,表示此屬性為必輸項;<rtexprvalue>設置為true,表示標簽體支持運行時的表達式取值,如果為false則表示標簽體為一個靜態文本,默認情況下設置為true。
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。
同樣,本例與實例108使用同一個tld文件,不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
UseBodyTag1.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.Date" %>
<html>
? <head>
? <title>開發帶有標簽體的標簽</title>
? </head>
? <body>
? 下面是應用這個帶有屬性的自定義標簽的結果:<br>
? <myTag:bodyTag1 countNum="6">
?? 現在的時間是:<%=new Date()%><br>
? </myTag:bodyTag1>
</body>
</html>
該程序的運行結果如圖13-4所示。
【實例111】? 開發嵌套的標簽:haveChildTag
實際工程中往往需要多個標簽來配合完成一定的功能,嵌套的標簽存在父子關系,其中,父為外層標簽,子為內層標簽。本實例將用兩個簡單的標簽來演示,父標簽則作出邏輯判斷,如果isOutput屬性為true,則輸出實例108中的標簽helloTag;如果為false,則不輸出。
(1)第一步:開發標簽實現類。
內層的標簽helloTag在實例108中已有,此處不再列出。
haveChildTag.java
package hello;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class haveChildTag extends BodyTagSupport {
?? private boolean isOutput;//是否輸出子標簽內容
??? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? if(isOutput)
??????????? return EVAL_BODY_INCLUDE;
??????? else return SKIP_BODY;
?? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
????? ? try{
?????????? if(bodyContent!=null)
??????????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????? }catch(Exception e){
??????????? System.out.println(e);
??????? }
??????? return EVAL_PAGE;
??? }??
??? public boolean getIsOutput() {
??????? return isOutput;
?? }
??? public void setIsOutput(boolean isOutput) {
?????? this.isOutput = isOutput;
??? }
}
?。?)第二步:編寫標簽描述tld文件。
本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加的如下內容:
<!-- haveChildTag-->
<tag>
? <!-- 標簽名稱-->
? <name>haveChildTag</name>
? <!-- 標簽對應的處理類-->
? <tag-class>hello.haveChildTag</tag-class>
? <!-- 標簽體內容,有標簽體則設為jsp-->
? <body-content>jsp</body-content>
? <!-- 標簽的屬性聲明-->
? <attribute>
?? <name>isOutput</name>
?? <required>true</required>
?? <rtexprvalue>true</rtexprvalue>
? </attribute>
</tag>
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。
同樣,本例與本章前面的實例使用同一個tld文件,此處不必再修改。
?。?)第四步:在JSP頁面中聲明并調用標簽。
useHaveChildTag.jsp
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.Date" %>
<html>
<head>
<title>開發嵌套的標簽</title>
</head>
? <body>
? 輸出子標簽時的結果:<br>
? <myTag:haveChildTag isOutput="true">
?? <myTag:helloTag/>
? </myTag:haveChildTag><br>
? 不輸出子標簽時的結果:<br>
? <myTag:haveChildTag isOutput="false">
?? <myTag:helloTag/>
? </myTag:haveChildTag><br>
</body>
</html>
該程序的運行結果如圖13-5所示。
《JSP網絡編程從實踐到實踐》原碼下載地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575????
五、 開發迭代的標簽
【實例112】? 開發迭代的標簽:iterateTag
對于集合對象的Iterator類對象,在JSP的Java代碼中需要用while循環或for循環來輸出,難于維護,且可復用性不好,程序員總是在大量地做這樣的工作,這時可以考慮用迭代的標簽來開發,需要輸出數據時只須在JSP頁面中聲明標簽即可。
開發迭代的標簽,需要設計兩個Java類:標簽實現類和表示標簽信息的類。本實例中標簽實現類為iterateTag.java,表示標簽信息的類為IterateTEI.java。開發迭代的標簽可實現IterationTag接口,也可從TagSupport類或BodyTagSupport類繼承,由于BodyTagSupport類繼承自TagSupport類,而TagSupport類又實現了IterationTag接口,為簡化開發,直接從BodyTagSupport類繼承即可。
?。?)第一步:開發標簽實現類和表示標簽信息的類。
iterateTag.java
package body;
import java.util.Collection;
import java.util.Iterator;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class iterateTag extends BodyTagSupport{
??? private String name;//在pageContext中標識的一個屬性名
??? private Iterator it;//要迭代的對象
??? private String type;//it中對象的類型
?? public void setCollection(Collection collection){
?????? if(collection.size()>0)
?????????? it=collection.iterator();
?? }
???
?? //----標簽開始時調用此方法-------
??? public int doStartTag(){
??????? if(it==null) return SKIP_BODY;
??????? else return continueNext(it);
??? }
??? //----標簽體執行完后調用此方法----
??? public int doAfterBody(){
??????? return continueNext(it);
??? }
??? //----標簽結束時調用此方法-------
??? public int doEndTag(){
??????? try{
??????????? if(bodyContent!=null)
??????????????? bodyContent.writeOut(bodyContent.getEnclosingWriter());
??????? }catch(Exception e){
??????????? System.out.println(e);
????? ? }
????? ? return EVAL_PAGE;
?? }?
??? //----迭代----
??? protected int continueNext(Iterator it){
??????? if(it.hasNext()){
??????????? pageContext.setAttribute(name,it.next(),pageContext.PAGE_SCOPE);
?????????? return EVAL_BODY_TAG;
??????? }else return SKIP_BODY;
??? }
?? public String getName() {
?????? return name;
??? }
??? public void setName(String name) {
???? ?? this.name = name;
?? }
?? public String getType() {
??? ??? return type;
??? }
??? public void setType(String type) {
???? ?? this.type = type;
?? }
}
在標簽實現類中,有3個屬性:name、type和it。其中,name代表在pageContext中標識一個屬性的名字;type代表待迭代內容的數據類型;it為要迭代的內容。在doStartTag()方法中,如果it不為null,就開始迭代,迭代時調用continueNext()方法。
IterateTEI.java
package body;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;
//----提供標簽翻譯時的一些相關信息----
public class IterateTEI extends TagExtraInfo {
? ? public IterateTEI() {
?????? super();
?? }
?? public VariableInfo[] getVariableInfo(TagData data){
???? ?? return new VariableInfo[]{
??????? ??????? new VariableInfo(data.getAttributeString("name"),
??????????????????????? data.getAttributeString("type"),
??????????????????????? true,VariableInfo.NESTED)?????????????
??????? };
??? }
}
VariableInfo類中有幾個常量,具體的含義為:
NESTED:標簽中的參數在標簽開始到標簽結束之間是有效的。
AT_BEGIN:標簽中的參數在標簽開始到使用它的JSP頁面結束是有效的。
AT_END:標簽中的參數在標簽的結束到使用它的JSP頁面結束是有效的。
?。?)第二步:編寫標簽描述tld文件。本例在myTag.tld文件中增加內容。在<taglib>與</taglib>之間增加如下內容:
?? <!-- iterateTag-->
?? <tag>
????? <!-- 標簽名稱-->
????? <name>iterateTag</name>
????? <!-- 標簽對應的處理類-->
????? <tag-class>body.iterateTag</tag-class>
????? <tei-class>body.IterateTEI</tei-class>
????? <!-- 標簽體內容,有標簽體則設為jsp-->
????? <body-content>jsp</body-content>
????? <!-- 標簽的屬性聲明-->
????? <attribute>
?????? <name>collection</name>
?????? <required>true</required>
?????? <rtexprvalue>true</rtexprvalue>
????? </attribute>
????? <attribute>
?????? <name>name</name>
?????? <required>true</required>
????? </attribute>
????? <attribute>
?????? <name>type</name>
?????? <required>true</required>
????? </attribute>
? ? </tag>
</taglib>
?。?)第三步:在Web應用的web.xml文件中聲明標簽庫引用。同樣,本例與本章前面的實例使用同一個tld文件,因此不必再修改。
(4)第四步:在JSP頁面中聲明并調用標簽。
<%@ taglib uri="/myTag" prefix="myTag" %>
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.ArrayList"%>
? <head>
? <title>開發迭代的標簽</title>
? </head>
<body>
? 開發一個迭代的標簽,輸出結果:<br>
? <%//----------設置一個ArrayList對象的初始值----------
?? ArrayList testCol=new ArrayList();
?? testCol.add("鄧佳容");
?? testCol.add("黃婧");
?? testCol.add("鄧子云");
?? request.setAttribute("testCol",testCol);
%>
? <myTag:iterateTag name="testColOne" collection="<%=testCol%>" type="String">
?? 輸出一個值:<%=testColOne.toString()%><br>
</myTag:iterateTag>
</body>
</html>
該程序的運行結果如圖13-6所示。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
