From Gossip@caterpillar

JSP/Servlet: SimpleTagSupport 類別(<jsp:attribute>)

 

 


SimpleTagSupport類別顧名思義,就是可以處理一些簡單的自訂標籤需求,它是在JSP 2.0之後新增的類別,對於一些簡單的自訂標籤頁求,您可以繼承它來實作標籤處理類別,而不用為了處理一些TagSupport、 BodyTagSuppourt類別中回傳值的問題。

為了使用上的簡單而降低了複雜性,另一方面就是SimpleTagSupport類別所處理的功能受了些限制,它只處理標籤與本體,要不要顯示本體文字取 決於您,對於標籤之後的頁面則不在SimpleTagSupport處理的範圍之內,另外SimpleTagSupport類別的本體文字不能設定為JSP,這也是使用 SimpleTagSupport上的一些限制。

儘管有了一些限制,對於簡單的自訂標籤需求,使用SimpleTagSupport還是比較容易的,它實作了SimpleTag介面,您只要重新定義 doTag()方法就可以實作自訂標籤的處理,先來看一個簡單的範例:

  • SimpleHelloTag.java
package onlyfun.caterpillar;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class SimpleHelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
JspWriter out = getJspContext().getOut();
out.println("Hello!World!");
}
}

假設在tld檔中設定是這樣的:
  • hello.tld
...
<tag>
<description>Simple Tag</description>
<name>hello</name>

<tag-class>onlyfun.caterpillar.SimpleHelloTag</tag-class>
<body-content>empty</body-content>
</tag>
...

則我們就可以在JSP網頁中這麼使用以顯示一段Hello!World!文字:
<caterpillar:hello/>
 
當然要真正顯示字串,別忘了web.xml中的設定與taglib的設定,前面已經說過好多次,不再重複了。

SimpleTagSupport預設不顯示本體文字,如果您想要自訂可以顯示本體文字的標籤,則可以這麼撰寫:

  • SimpleTextTag.java
package onlyfun.caterpillar;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class SimpleHelloTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
JspFragment frag = getJspBody();
frag.invoke(null);
}
}

getJspBody()方法傳回JspFragment物件,它包括了標籤本體的相關訊息,使用invoke()方法可以將這些訊息寫入指定的 Writer中,如果設定為null,則預設寫入getJspContext().getOut()取得的Writer,假設 tld檔是這樣設定:
  • text.tld
...
<tag>
<description>Simple Tag</description>
<name>showbody</name>
<tag-class>demo.tags.SimpleTagText</tag-class>
<body-content>tagdependent</body-content>
</tag>
...

則可以在JSP網頁中這麼使用它,作用只是將本體文字再顯示出來:
<caterpillar:showbody>
    顯示這段文字。。。。
</caterpillar:showbody>
 
除了使用上面的方式來包裝本體文字至JspFragment中之外,您還可以< jsp:attribute>動作元素,將指定的文字包裝為JspFragment,例如先撰寫以下的標籤處理類別:

  • SimpleFragTag.java
package onlyfun.caterpillar; 

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class SimpleFragTag extends SimpleTagSupport {
private JspFragment fragment1;
private JspFragment fragment2;

public void setFragment1(JspFragment fragment1) {
this.fragment1 = fragment1;
}

public void setFragment2(JspFragment fragment2) {
this.fragment2 = fragment2;
}

public void doTag() throws JspException, IOException {
fragment2.invoke(null);
fragment1.invoke(null);
}
}

這個處理類別將接受兩個JspFragment,為了要能包裝JspFragment,必須在tld檔中指定:
  • frag.tld
 ...
<tag>
<description>Simple Tag</description>
<name>fragtest</name>
<tag-class>onlyfun.caterpillar.SimpleFragTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>fragment1</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
<attribute>
<name>fragment2</name>
<required>true</required>
<fragment>true</fragment>
</attribute>
</tag>
...

這次在設定屬性時,指定<fragment>為true,表示屬性將接受JspFragment物件,接下來這樣測試:
  • test.jsp
<%@taglib prefix="caterpillar" 
uri="http://caterpillar.onlyfun.net/"%>
<html>
<body>

<caterpillar:fragtest>
<jsp:attribute name="fragment1">
Frag1 Test ..... <br>
</jsp:attribute>
<jsp:attribute name="fragment2">
Frag2 Test .... <br>
</jsp:attribute>
</caterpillar:fragtest>

</body>
</html>

這個JSP網頁的傳回結果如下:
<html>
<body>
 Frag2 Test .... <br>Frag1 Test ..... <br>
</body>
</html>
 
如果您想要處理標籤的本體文字內容的話該怎麼辦呢?invoke()方法可以將文字寫入指定的Writer中,可以使用StringWriter,將文字寫入當中,然後再取得String物件就可以進行處理了,例如:

  • SimpleDemoTag.java
package onlyfun.caterpillar;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class SimpleDemoTag extends SimpleTagSupport {
public void doTag() throws JspException, IOException {
JspFragment frag = getJspBody();
JspWriter out = getJspContext().getOut();
StringWriter writer = new StringWriter();

frag.invoke(writer);
String str = writer.toString();
out.println(str.replaceAll("<%","&lt;%"));
}
}

上面的程式示範了如何處理本體文字,這個標籤處理類別將所有的 <% 置換 &lt;。