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

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