如何建立一個簡單的標記處理器?
需要做三件事:
一、編寫標籤處理器(java檔案)
二、在標籤庫描述符檔案中描述該標籤 (TLD檔案)
三、在jsp檔案中引用該標籤
具體步驟:
step1:編寫一個擴充SimpleTagSupport的類
package foo;import javax.servlet.jsp.tagext.SimpleTagSupport;//mort import...public class SimpleTagTest1 extands SimpleTagSupport{ //這裡放標記處理代碼 }
step2: 實現doTag()方法
public void doTag() throws JspException, IOException { //在response中列印 "This is xxxxxx" getJspContext().getOut().print("This is xxxxxx");}
step3: 為標記建立一個TLD (taglib description, 標籤庫描述符)
<?xml version="1.0" encoding="ISO-8859-1" ?><taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/jsee/web-jsptagLibrary_2_0.xsd" version="2.0"> <tlib-version>1.2</tlib-version> <uri>simpleTags</uri> <tag> <name>simple1</name> <description>xxxxxxxx</description> <tag-class>foo.SimpleTagTest1</tag-class> <body-content>empty</body-content> </tag></taglib>
step4: 部署標記處理器和TLD
把TLD檔案放在WEB-INF下,並把標記處理器放在WEB-INF/classes下,這裡當然還要遵循包目錄結構。換句話說,標記處理器類要與所有其他web應用Java類放在同一個位置上。
step5: 編寫一個使用標記的JSP
<%@ taglib prefix="myTags" uri="simpleTags" %><html> <body> <myTags:simple1 %> </body></html>
uri中的名稱要與TLD檔案中的uri的名稱一致。
至此,就建立了一個簡單的自訂標籤。
自訂標籤還有幾種常見的情況,分別為:
一、有體的標記 (如,<x:label>...</x:label>,"..."為標籤的body)
二、標記體中使用了運算式 (如,<x:label> ${movie} </x:label>, "${movie}"為標籤的體中出現的EL運算式)
三、迴圈執列標籤體
四、含有屬性的簡單標籤 (如,<x:label movie="${movie}" />)
以下,將分別介紹這幾種情況:
情況一:編寫的是有體(body)的標記,如:
<myTags:simple2> This is the body //這個就是標記的body</myTags:simple2>
那麼在這種情況下,為了執行body內的語句就需要加入這樣一句話到doTag()方法中:
getJspBody().invoke(null);
invoke的意思是“處理標記的body,並把它列印到響應(response)中”。
null的意思是把內容輸出到響應(response),而不是輸出到什麼別的書寫器(Writer)上。
除此以外,TLD中的 “<body-content>empty</body-content>” 一欄也需要改動,要改為:
<body-content>scriptless</body-content>
之後會介紹四種不同的body-content的參數。
情況二、如果標記體使用了運算式,如:
<myTags:simple3> Message is : ${message}</myTags:simple3>
那麼這個運算式的賦值需要在標籤處理器的doTag()中完成,如:
getJspContext().setAttribute("message","wear sunscreen");getJspBody().invoke(null);//一定要記得寫這句,否則標籤體不會執行
情況三、若想要迴圈輸出一個集合的資料,應該如何??如:
<table><myTags:simple3> <tr><td>${movie}</td></tr></myTags:simple3></table>
顯然,希望通過迴圈輸出不同的movie來形成 一個表格。那麼標記處理器的doTag()方法應該改為:
String[] movies = {"Monsoon Wedding", "Saved!", ".. ..."};public void doTag() throws JspException, IOException { for(int i = 0; i < movies.length; i++){ getJspContext().setAttribute("movie",movies[i]); getJspBody().invoke(null);//每次invoke,都會執行一次標籤body }}
情況四、如果這個簡單標記是有屬性的,怎麼辦?如:
<table><myTags:simple5 movieList="${movieCollection}"> <tr> <td>${movie.name}</td> <td>${movie.genre}</td> </tr></myTags:simple5></table>
由於標記中出現了屬性,所以TLD中的描述必須反映這一情況,因此TLD應調整為:
<?xml version="1.0" encoding="ISO-8859-1" ?><taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/jsee/web-jsptagLibrary_2_0.xsd" version="2.0"> <tlib-version>1.2</tlib-version> <uri>simpleTags</uri> <tag> <name>simple1</name> <description>xxxxxxxx</description> <tag-class>foo.SimpleTagTest1</tag-class> <body-content>empty</body-content> <attribute> <name>movieList</name> <required>true</required><!-- 說明movieList屬性是必需的 --> <rtexprvalue>true</rtexprvalue><!-- 說明movieList屬性可以是一個運行時運算式(不用非得是一個常量String) --> </attribute> </tag></taglib>
另外,在標記處理器類中,也要對這一屬性有相應的體現:
public class SimpleTagTest5 extends SimpleTagSupport{ private List movieList; public void setMovieList(List movieList){ this.movieList = movieList; } public void doTag() ....}
補充:
<body-content></body-content>中可以寫入的參數有四種:
① empty
即標記不可為空
② scriptless
這個標記不能有指令碼元素,但可以有模板文本和EL, 還可以是定製和標準動作
③ tagdependent
標記體要看做是純文字,所以不會計算EL,也不會出發標記/動作
④ JSP
能放在JSP中的東西都能放在這個標記體中