今天來看到classic tag
這部分較複雜一點點
最早JSP所提供的自訂標標籤處理器
在JSP 2.0之後雖然simple tag結合JSTL和tag file已經可以處理大部分的事了
但這塊還是可以稍微了解一下
且若要考認證考試還是會出個幾題
有別於simple tag的doTag
classic主要分成兩個部分
doStartTag()和doEndTag()
在JSP和TLD和simplet tag是相同的(也就是說TLD也可以切換到呼叫simple tag)
主要差在java程式,上述的兩個方法已以及回傳的參數意義
還有IOException要另外處理的部分
ClassiclTag.java
package com.web.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
public class ClassiclTag extends TagSupport{
JspWriter output;
// Classic並沒有宣告IOException,所以要在程式裡面自己try catch
public int doStartTag() throws JspException{
//從TagSupport繼承到pageContext(類似simple tag的getJspContext())
output = pageContext.getOut();
try{
output.print("doStartTag...");
}catch(IOException ex)
{
throw new JspException("IOException is "+ex.toString());
}
//這個參數表示就算有body,也直接跳到doEndTag方法
//若要執行body(具有主體時),則回傳EVAL_BODY_INCLUDE
return SKIP_BODY;
}
public int doEndTag()throws JspException{
try{
output.print("doEndTag...");
}catch(IOException ex)
{
throw new JspException("IOException is "+ex.toString());
}
//繼續執行剩下的部分
//和它相反的為SKIP_PAGE,類似simple的SkipPageException
return EVAL_PAGE;
}
}
因為Classic有doStartTag和doEndTag
不像simple tag有dotag()一次做完
所以classic提供了doAfterBody()來處理body的部分
順序如下:
整個流程及回傳的return值直接用下圖表示
其中所有的回傳值只有EVAL_BODY_AGAIN是由IterationTag所提供
剛剛有提到的doAfterBody()就是由IterationTag提供
IterationTag API
若在doAfterBody()裡面set屬性
因為doAfterBody()是在主體被執行一次才會執行
所以在doStartTag()時也需要set一次相同的屬性,否則在doStartTag()時會找不到此屬性
畫面上會多一個空值
另外Classic Tag是可以重複被Container使用
這點和Simple tag不相同,因此在參數的設定上也需要注意是否要重新設定其值
Simple tag可以利用writer的方法,處理body的內容
但classic tag
則需要BodyTag來幫忙
BodyTag繼承了BodyTagSupport
可以使用setBodyContext()和doInitBody()
來呼叫處理器的實際主內容去做控制
因此整個流程就變成,多了兩個方法和一個回傳值
這裡分成兩個部分討論(此部分simple 和classic都相同)
1.父tag要取得子tag的資訊
因為沒有提供往下找的方法
所以需要在子tag裡面去新增屬性,將子tag的屬性傳給父tag
ParentTag.java
package com.web.tag;
import java.util.ArrayList;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
public class ParentTag extends TagSupport{
private ArrayList arrayName;
//新增一個方法供子tag呼叫
public void addItem(String s)
{
arrayName.add(s);
}
public int doStartTag() throws JspException{
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspException{
return EVAL_PAGE;
}
}
SubTag.java
package com.web.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
public class SubTag extends TagSupport{
private String str;
public void setStr(String str) {
this.str = str;
}
public int doStartTag() throws JspException{
return EVAL_BODY_INCLUDE;
}
public int doEndTag()throws JspException{
//呼叫父tag,使用addItem將子tag的值傳入
ParentTag parTag = (ParentTag) getParent();
parTag.addItem(str);
return EVAL_PAGE;
}
}
2.子tag要取得父tag的資訊
不管是simple和tag都具有getParent()的方法
只是回傳的型別不相同
因此可以在子tag裡面使用getParent()得到父tag的物件
但要記得做轉型
此外由於simple回傳是JspTag
包含了tag的interface
所以getParent()
classic tag只能存取classic tag的父標籤
但simple tag除了存取自己類型的父tag之外,也可存取classic tag
其實今天還有漏掉一個主題
DynamicAttributes
不是因為偷懶,是因為還需要花一些時間研究一下
不是很了解書中講解的範例
明天會先繼續後面的進度
再找時間練習這個部分,之後再補充上來