?一.?簡單標(biāo)簽處理器JSP 2.0的設(shè)計者意識到了在JSP 1.1及 JSP1.2中實現(xiàn) 標(biāo)簽及標(biāo)簽處理器的復(fù)雜性。因此,JSP 2.0中,在 javax.servlet.jsp.tagext包下增加了接口——SimpleTag。 實現(xiàn)SimpleTag的標(biāo)簽處理器都叫作簡單標(biāo)簽處理器; 實現(xiàn)Tag、IterationTag及BodyTag的標(biāo)簽處理器都叫作 經(jīng)典標(biāo)簽處理器。 簡單標(biāo)簽處理器有著簡單的生命周期,而且比經(jīng)典 標(biāo)簽處理器更加易于實現(xiàn)。SimpleTag接口中用于標(biāo)簽 觸發(fā)的方法只有一個——doTag,并且該方法只會執(zhí)行 一次。業(yè)務(wù)邏輯、遍歷及頁面內(nèi)容操作都在這里實現(xiàn)。 簡單標(biāo)簽處理器中的頁面內(nèi)容都在JspFragment類的實 例中體現(xiàn)。 簡單標(biāo)簽的生命周期如下:
通常情況下,都需要把使用傳入的JspContext指定 為類的成員變量以便后繼使用:
javax.servlet.jsp.tagext包中也包含一個SimpleTag的 基礎(chǔ)類:SimpleTagSupport。SimpleTagSupport提供了 SimpleTag所有方法的默認(rèn)實現(xiàn),并便于擴展實現(xiàn)簡單 標(biāo)簽處理器。在SimpleTagSupport類中用getJspContext 方法返回JspContext實例,這個實例在JSP容器調(diào)用 SimpleTag的setJspContext方法時傳入。 二.SimpleTag示例自定義標(biāo)簽需要有兩個步驟:編寫標(biāo)簽處 理器及注冊標(biāo)簽。 1. 編寫標(biāo)簽處理器清單6.1中列出了MyFirstTag類,它是一個 SimpleTag的實現(xiàn)。 MySimpleTag類中有一個名為jspContext的 JspContext類型變量。在setJspContext方法中,將由JSP 容器中傳入的JspContext對象賦給該變量。在doTag方法 中,通過JspContext對象獲取JspWriter對象實例。然后 用JspWriter方法中的print方法輸出“This is my first tag”的字符串。 package customtag; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.tagext.JspTag; import javax.servlet.jsp.tagext.SimpleTag; public class MyFirstTag implements SimpleTag{ JspContext jspContext; public void doTag() throws IOException, JspException{//輸出 System.out.println("dotag"); jspContext.getOut().print("This is my first tag."); } public void setParent(JspTag jspTag) {//只有標(biāo)簽被嵌套才會調(diào)用 System.out.println("setParent"); } public JspTag getParent() { System.out.println("getparent"); return null; } public void setJspContext(JspContext jspContext) { //jsp容器 首先會調(diào)用setJSpContext方法 System.out.println("setJspcontext"); this.jspContext = jspContext; } public void setJspBody(JspFragment body) {//如果標(biāo)簽里面有內(nèi)容則會調(diào)用setJspBody方法,否則不會調(diào)用 System.out.println("setJspBody"); } } ? 2.注冊標(biāo)簽在標(biāo)簽處理器能夠被JSP頁面使用之前,它需要在 標(biāo)簽庫描述器中注冊一下,這個描述器是以.tld結(jié)尾的 XML文件。本例標(biāo)簽庫描述是一個名為mytags.tld的文 件。這個文件必須放在WEB-INF目 錄下。 在標(biāo)簽描述文件中最主要的節(jié)點是tag,它用于定 義一個標(biāo)簽。它可以包含一個name節(jié)點及一個tag-class 的節(jié)點。name節(jié)點用于說明這個標(biāo)簽的名稱;tag-class 則用于指出標(biāo)簽處理器的完整類名。一個標(biāo)簽庫描述器 中可以定義多個標(biāo)簽。 此外,在標(biāo)簽描述器中還有其他節(jié)點。description 節(jié)點用于說明這個描述器中的所有標(biāo)簽。tlib-version節(jié) 點用于指定自定義標(biāo)簽的版本。short-name節(jié)點則是這 些標(biāo)簽的名稱。 <?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java./xml/ns/j2ee" xmlns:xsi="http://www./2001/XMLSchema-instance" xsi:schemaLocation="http://java./xml/ns/j2ee web-jsptaglibrary_2_1.xsd" version="2.1"> <description> Simple tag examples </description> <tlib-version>1.0</tlib-version> <short-name>My First Taglib Example</short-name> //2.o版本的不能有空格 <tag> <name>firstTag</name> <tag-class>customtag.MyFirstTag</tag-class> <body-content>empty</body-content> //empty表示標(biāo)簽里面不能有內(nèi)容 </tag> </taglib> 2.1 配置部署描述符必需在web.xml文件加上以下配置,要不能找不到tld文件的路徑 <jsp-config> <taglib> <taglib-uri>customtag.MyFirstTag</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib> </jsp-config> ? 3.使用標(biāo)簽要使用自定義標(biāo)簽,就要用到taglib指令。taglib指 令中的uri屬性是標(biāo)簽描述器的絕對路徑或者相對路 徑。本例中使用相對路徑。但是,如果使用的是jar包 中的標(biāo)簽庫,就必須要使用絕對路徑了。 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/WEB-INF/c.tld" prefix="easy" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <easy:firstTag></easy:firstTag> </body> </html> 一旦訪問firtTagTest.jsp頁面,JSP容器就會調(diào)用標(biāo) 簽處理器中的setJspContext方法。由于firstTagTest.jsp中 的標(biāo)簽沒有內(nèi)容,因此JSP容器也就不會在調(diào)用doTag 方法前調(diào)用setJspBody的方法。 ? 三. 處理屬性? 實現(xiàn)SimpleTag接口或者擴展SimpleTagSupporta的 標(biāo)簽處理器都可以有屬性, 下面列出的名為 DataFormaterTag的標(biāo)簽處理器可以將逗號分隔內(nèi)容轉(zhuǎn) 換成HTML表格。這個標(biāo)簽有兩個屬性:header、 items。header屬性值將會轉(zhuǎn)成表頭。 例如, 將“Cities”作為header屬性值, “London,Montreal”作為 items屬性值,那么會得到如下輸出: <table style="border:1px solid green"> <tr><td><b>Cities</b></td></tr> <tr><td>London</td></tr> <tr><td>Montreal</td></tr> </table> DataFormatterTag類 package customtag; import java.io.IOException; import java.util.StringTokenizer; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class DataFormatterTag extends SimpleTagSupport { private String header; private String items; public void setHeader(String header) { this.header = header; } public void setItems(String items) { this.items = items; } public void doTag() throws IOException, JspException { JspContext jspContext = getJspContext(); JspWriter out = jspContext.getOut(); out.print("<table style='border:1px solid green'>\n" "<tr><td><span style='font-weight:bold'>" header "</span></td></tr>\n"); StringTokenizer tokenizer = new StringTokenizer(items, ",");//分解字符串 while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); out.print("<tr><td>" token "</td></tr>\n"); } out.print("</table>"); } } DataFormatterTag類有兩個Set方法用于接收屬性: setHeader、setItems。doTag方法中則實現(xiàn)了其余的內(nèi) 容。 doTag方法中,首先通過getJspContext方法獲取通 過JSP容器傳入的JSPContext對象: 接著,通過JspContext實例中的getOut方法獲取 JspWriter對象,它能將響應(yīng)寫回客戶端: 然后,doTag方法使用StringTokenizer解析items屬 性值,然后將每個item都轉(zhuǎn)換成表格中的一行: 為了能夠使用DataFormatterTag的標(biāo)簽處理器,還 需要在tag節(jié)點中注冊一下,如清單所示。簡單地 說,就是把它加入mytags.tld中,用法如下所示。 <tag> <name>dataFormatter</name> <tag-class>customtag.DataFormatterTag</tag-class> <body-content>empty</body-content> <attribute> <name>header</name> <required>true</required> </attribute> <attribute> <name>items</name> <required>true</required> </attribute> </tag> jsp 頁面 <%@ taglib uri="/WEB-INF/c.tld" prefix="easy"%> <html> <head> <title>Testing DataFormatterTag</title> </head> <body> <easy:dataFormatter header="States" items="Alabama,Alaska,Georgia,Florida"/> <br/> <easy:dataFormatter header="Countries"> <%-- 設(shè)置屬性items的值 --%> <jsp:attribute name="items"> US,UK,Canada,Korea </jsp:attribute> </easy:dataFormatter> </body> </html> 注意,清單6.6所列出來的JSP頁面使用了 dataFormatter標(biāo)簽兩次,每次都使用不同的兩種方式: 一種是標(biāo)簽屬性,另一種是標(biāo)準(zhǔn)屬性。 三.訪問標(biāo)簽內(nèi)容在SimpleTag中,可以通過JSP容器傳入的 JspFragment來訪問標(biāo)簽內(nèi)容。 JspFragment類提供了多 次訪問JSP中這部分代碼的能力。JSP片段的定義不能 包含腳本或者腳本表達式,它只能是文件模板或者JSP 標(biāo)準(zhǔn)節(jié)點。 JspFragment類中有兩個方法:getJspContext、 invoke。我們的定義如下: public abstract JspContext getJspContext() public abstract void invoke(java.io.Writer writer) throws JspException, java.io.IOException getJspContext方法返回這個JspFragment關(guān)聯(lián)的 JspContext對象??梢酝ㄟ^invoke方法來執(zhí)行這個片段 (標(biāo)簽的內(nèi)容),然后通過指定的Writer對象把它直接 輸出。如果把null傳入invoke方法中,那么這個Writer將 會被JspFragment所關(guān)聯(lián)的JspContext對家中的getOut方 法返回的JspWriter方法所接管。 看清單中所列出來的SelectElementTag類。使用 標(biāo)簽處理器可以輸出如下格式的HTML select節(jié)點: <select> <option value="value-1">text-1</option> <option value="value-2">text-2</option> ... <option value="value-n">text-n</option> </select> 在本例中,這些值都是String數(shù)組類型countries的 國家名。 SelectElementTag package customtag; import java.io.IOException; import javax.servlet.jsp.JspContext; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SelectElementTag extends SimpleTagSupport { private String[] countries = {"Australia", "Brazil", "China" }; public void doTag() throws IOException, JspException { JspContext jspContext = getJspContext(); JspWriter out = jspContext.getOut(); out.print("<select>\n"); for (int i = 0; i < 3; i ) { // 每次循環(huán)設(shè)置一次Attribute 然后利用invoke輸出 getJspContext().setAttribute("value", countries[i]); getJspContext().setAttribute("text", countries[i]); getJspBody().invoke(null); //getJSpBody得到的是標(biāo)簽中間的內(nèi)容,在這里是 <option value="${value}">${text}</option> } out.print("</select>\n"); } } Tag節(jié)點用于注冊SelectElementTag, 并把它轉(zhuǎn)成select的標(biāo)簽。接著,像上面的例子一樣, 我們繼續(xù)把這個節(jié)點加入到mytags.tld文件中。 <tag> <name>select</name> <tag-class>customtag.SelectElementTag</tag-class> <body-content>scriptless</body-content> //scriptless代表無腳本 </tag> JSP頁面 <%@ taglib uri="/WEB-INF/mytags.tld" prefix="easy"%> <html> <head> <title>Testing SelectElementFormatterTag</title> </head> <body> <easy:select> <option value="${value}">${text}</option> </easy:select> </body> </html> 注意,select標(biāo)簽傳入如下內(nèi)容: <option value="${value}">${text}</option> //該內(nèi)容可以用getJspBody()獲取 在SelectElementTag標(biāo)簽處理器中的doTag里,每次 觸發(fā)JspFragment時,都要獲取一次value及text屬性值: for (int i=0; i<3; i ) { getJspContext().setAttribute("value", countries[i]); getJspContext().setAttribute("text", countries[i]); getJspBody().invoke(null); //invoke用于輸出 } 四. 編寫EL函數(shù)? 來源:http://www./content-4-163801.html |
|