[Tag] Jsp 2.x Tag - interface SimpleTag

之前我們介紹的Tag都是以實作interface Tag來達到效果。而Interface Tag有多個method,並且在不同的時候返回不同的值來控制流程。

但是當我們在實際使用的時候,通常來說我們不會需要控制這些流程,我們只會override doEndTag()而已,就為了這個要實作並且返回奇怪的數字看起來是在很麻煩。

因此在jsp 2.x之後,除了支援舊的格式以外,有多增加了一個interface叫做SimpleTag讓我們開發自定義tag的時候更加容易。

這一篇我們來看一下和interface Tag有什麼不一樣。

前言

之前我們介紹的Tag都是以實作interface Tag來達到效果。而Interface Tag有多個method,並且在不同的時候返回不同的值來控制流程。

但是當我們在實際使用的時候,通常來說我們不會需要控制這些流程,我們只會override doEndTag()而已,就為了這個要實作並且返回奇怪的數字看起來是在很麻煩。

因此在jsp 2.x之後,除了支援舊的格式以外,有多增加了一個interface叫做SimpleTag讓我們開發自定義tag的時候更加容易。

這一篇我們來看一下和interface Tag有什麼不一樣。

SimpleTag的架構

SimpleTag很簡單,只需要實作一個void doTag()的方法。和Tag一樣,有一個模板的class叫做SimpleTagSupport我們可以直接繼承這個class來開發自定義Tag。

SimpleTag和Tag一樣都支援Attribute和取得tag body內容。

SimpleTag的tld定義基本上和Tag一樣。

SimpleTag取得Attribute

和Tag一樣,都是設定tld然後有一個對應一樣名稱的variable,例如:


public class TestSimpleTag extends SimpleTagSupport  {

	int a;
	int b;
	public void setA(int a) {
		this.a = a;
	}
	public void setB(int b) {
		this.b = b;
	}
	@Override
	public void doTag() throws JspException, IOException {

		this.getJspContext().getOut().println(a + " * " + b + " = " + a*b);
	}

}

然後tld一樣:


  <tag>
    <name>multiple</name>
    <tag-class>tag.TestSimpleTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
    	 <name>a</name>
    	 <required>true</required>
    	 <rtexprvalue>true</rtexprvalue>
    </attribute>
        <attribute>
    	 <name>b</name>
    	 <required>true</required>
    	 <rtexprvalue>true</rtexprvalue>
    </attribute>
    
  </tag>

這樣就完成了使用Attribute的範例。

SimpleTag取得body 內容

相較於取得Attribute,要取得body內容就不太一樣了。

SimpleTag裡面有一個JspFragment的object我們可以呼叫,而那個object就代表著body的內容。

簡單的範例,把body文字全部轉成小寫:


@Override
public void doTag() throws JspException, IOException {

	JspFragment body = this.getJspBody();

	//write the content of JspFragment into writer
	StringWriter writer = new StringWriter();
	body.invoke(writer);
	
	String content = writer.toString();
	
	JspWriter out = this.getJspContext().getOut();
	out.println(content.toLowerCase());	

}

這一次要記得在tld裡面content的部份要修改:


  <tag>
    <name>multiple</name>
    <tag-class>tag.TestSimpleTag</tag-class>
    <body-content>tagdependent</body-content> 
  </tag>

呼叫我就不顯示了。

可以看得出來,我們取得JspFragment有點像是一個body內容的buffer,需要把它寫出(invoke())來才能用。因此我們能夠對body內容做修改。

多個body標籤

在SimpleTag裡面我們可以擁有多個標籤body,並且我們也可以像在Tag裡面一樣,多次呼叫body去執行,做法如下:


public class TestSimpleTag extends SimpleTagSupport  {

	private JspFragment body1;
	private JspFragment body2;

	public void setBody1(JspFragment body1) {
		this.body1 = body1;
	}

	public void setBody2(JspFragment body2) {
		this.body2 = body2;
	}

	@Override
	public void doTag() throws JspException, IOException {

		//write the content of JspFragment into writer
		StringWriter writer = new StringWriter();
		
		for (int i = 0; i < 2; i++) {
			body1.invoke(writer);
		}
		
		
		StringWriter writer2 = new StringWriter();
		for (int i = 0; i < 3; i++) {
			body2.invoke(writer2);
		}
		
		String content = writer.toString();
		
		String content2 = writer2.toString();
		
		JspWriter out = this.getJspContext().getOut();
		out.println("content 1: " + content);
		out.println("content 2: " + content2);

	}

}

和定義attribute很像,我們先定義兩個body JspFragment。可以看到在執行的時候我們多次執行了個自裡面的body內容,這個和TagBodySupport裡面在doAfterBody() 重複return一樣道理。

接下來在tld裡面我們要註明這個是fragment:


<tag>
    <name>multiple</name>
    <tag-class>tag.TestSimpleTag</tag-class>
    <body-content>tagdependent</body-content> 
    <attribute>
    	<name>body1</name>
    	<required>false</required>
    	<fragment>true</fragment>
    </attribute>
    <attribute>
    	<name>body2</name>
    	<required>false</required>
    	<fragment>true</fragment>
    </attribute>
</tag>

最後在呼叫的時候,利用jsp action tag的attribute來使用:


<hello2:multiple>
	<jsp:attribute name='body1'>body1,</jsp:attribute>
	<jsp:attribute name='body2'>body2,</jsp:attribute>
</hello2:multiple>

就可以了。

結語

自定義Tag其實因為版本不同因此有兩種做法。使用Jsp 1.x(實作Tag interface)的方法讓我們對於執行流程有更多的控制,不過大部份情況我們都不需要控制到這麼細,因此在jsp 2.x才有了SimpleTag的interface出現。

希望透過這篇能夠瞭解如何使用SimpleTag。在下一篇我們會提到如何自定義tag function,就像jstl裡面的fmt那樣。

Dotblogs 的標籤: ,

Google+

創用 CC 授權條款
Alan Tsai 的隨手筆記Alan Tsai製作,以創用CC 姓名標示 4.0 國際 授權條款釋出。