?一.?簡(jiǎn)單標(biāo)簽處理器JSP 2.0的設(shè)計(jì)者意識(shí)到了在JSP 1.1及 JSP1.2中實(shí)現(xiàn) 標(biāo)簽及標(biāo)簽處理器的復(fù)雜性。因此,JSP 2.0中,在 javax.servlet.jsp.tagext包下增加了接口——SimpleTag。 實(shí)現(xiàn)SimpleTag的標(biāo)簽處理器都叫作簡(jiǎn)單標(biāo)簽處理器; 實(shí)現(xiàn)Tag、IterationTag及BodyTag的標(biāo)簽處理器都叫作 經(jīng)典標(biāo)簽處理器。 簡(jiǎn)單標(biāo)簽處理器有著簡(jiǎn)單的生命周期,而且比經(jīng)典 標(biāo)簽處理器更加易于實(shí)現(xiàn)。SimpleTag接口中用于標(biāo)簽 觸發(fā)的方法只有一個(gè)——doTag,并且該方法只會(huì)執(zhí)行 一次。業(yè)務(wù)邏輯、遍歷及頁(yè)面內(nèi)容操作都在這里實(shí)現(xiàn)。 簡(jiǎn)單標(biāo)簽處理器中的頁(yè)面內(nèi)容都在JspFragment類的實(shí) 例中體現(xiàn)。 簡(jiǎn)單標(biāo)簽的生命周期如下:
通常情況下,都需要把使用傳入的JspContext指定 為類的成員變量以便后繼使用:
javax.servlet.jsp.tagext包中也包含一個(gè)SimpleTag的 基礎(chǔ)類:SimpleTagSupport。SimpleTagSupport提供了 SimpleTag所有方法的默認(rèn)實(shí)現(xiàn),并便于擴(kuò)展實(shí)現(xiàn)簡(jiǎn)單 標(biāo)簽處理器。在SimpleTagSupport類中用getJspContext 方法返回JspContext實(shí)例,這個(gè)實(shí)例在JSP容器調(diào)用 SimpleTag的setJspContext方法時(shí)傳入。 二.SimpleTag示例自定義標(biāo)簽需要有兩個(gè)步驟:編寫標(biāo)簽處 理器及注冊(cè)標(biāo)簽。 1. 編寫標(biāo)簽處理器清單6.1中列出了MyFirstTag類,它是一個(gè) SimpleTag的實(shí)現(xiàn)。 MySimpleTag類中有一個(gè)名為jspContext的 JspContext類型變量。在setJspContext方法中,將由JSP 容器中傳入的JspContext對(duì)象賦給該變量。在doTag方法 中,通過JspContext對(duì)象獲取JspWriter對(duì)象實(shí)例。然后 用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)簽被嵌套才會(huì)調(diào)用
System.out.println("setParent");
}
public JspTag getParent() {
System.out.println("getparent");
return null;
}
public void setJspContext(JspContext jspContext) { //jsp容器 首先會(huì)調(diào)用setJSpContext方法
System.out.println("setJspcontext");
this.jspContext = jspContext;
}
public void setJspBody(JspFragment body) {//如果標(biāo)簽里面有內(nèi)容則會(huì)調(diào)用setJspBody方法,否則不會(huì)調(diào)用
System.out.println("setJspBody");
}
}
? 2.注冊(cè)標(biāo)簽在標(biāo)簽處理器能夠被JSP頁(yè)面使用之前,它需要在 標(biāo)簽庫(kù)描述器中注冊(cè)一下,這個(gè)描述器是以.tld結(jié)尾的 XML文件。本例標(biāo)簽庫(kù)描述是一個(gè)名為mytags.tld的文 件。這個(gè)文件必須放在WEB-INF目 錄下。 在標(biāo)簽描述文件中最主要的節(jié)點(diǎn)是tag,它用于定 義一個(gè)標(biāo)簽。它可以包含一個(gè)name節(jié)點(diǎn)及一個(gè)tag-class 的節(jié)點(diǎn)。name節(jié)點(diǎn)用于說明這個(gè)標(biāo)簽的名稱;tag-class 則用于指出標(biāo)簽處理器的完整類名。一個(gè)標(biāo)簽庫(kù)描述器 中可以定義多個(gè)標(biāo)簽。 此外,在標(biāo)簽描述器中還有其他節(jié)點(diǎn)。description 節(jié)點(diǎn)用于說明這個(gè)描述器中的所有標(biāo)簽。tlib-version節(jié) 點(diǎn)用于指定自定義標(biāo)簽的版本。short-name節(jié)點(diǎn)則是這 些標(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)簽描述器的絕對(duì)路徑或者相對(duì)路 徑。本例中使用相對(duì)路徑。但是,如果使用的是jar包 中的標(biāo)簽庫(kù),就必須要使用絕對(duì)路徑了。 <%@ 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頁(yè)面,JSP容器就會(huì)調(diào)用標(biāo) 簽處理器中的setJspContext方法。由于firstTagTest.jsp中 的標(biāo)簽沒有內(nèi)容,因此JSP容器也就不會(huì)在調(diào)用doTag 方法前調(diào)用setJspBody的方法。 ? 三. 處理屬性? 實(shí)現(xiàn)SimpleTag接口或者擴(kuò)展SimpleTagSupporta的 標(biāo)簽處理器都可以有屬性, 下面列出的名為 DataFormaterTag的標(biāo)簽處理器可以將逗號(hào)分隔內(nèi)容轉(zhuǎn) 換成HTML表格。這個(gè)標(biāo)簽有兩個(gè)屬性:header、 items。header屬性值將會(huì)轉(zhuǎn)成表頭。 例如, 將“Cities”作為header屬性值, “London,Montreal”作為 items屬性值,那么會(huì)得到如下輸出: <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類有兩個(gè)Set方法用于接收屬性: setHeader、setItems。doTag方法中則實(shí)現(xiàn)了其余的內(nèi) 容。 doTag方法中,首先通過getJspContext方法獲取通 過JSP容器傳入的JSPContext對(duì)象: 接著,通過JspContext實(shí)例中的getOut方法獲取 JspWriter對(duì)象,它能將響應(yīng)寫回客戶端: 然后,doTag方法使用StringTokenizer解析items屬 性值,然后將每個(gè)item都轉(zhuǎn)換成表格中的一行: 為了能夠使用DataFormatterTag的標(biāo)簽處理器,還 需要在tag節(jié)點(diǎn)中注冊(cè)一下,如清單所示。簡(jiǎn)單地 說,就是把它加入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 頁(yè)面 <%@ 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頁(yè)面使用了 dataFormatter標(biāo)簽兩次,每次都使用不同的兩種方式: 一種是標(biāo)簽屬性,另一種是標(biāo)準(zhǔn)屬性。 三.訪問標(biāo)簽內(nèi)容在SimpleTag中,可以通過JSP容器傳入的 JspFragment來訪問標(biāo)簽內(nèi)容。 JspFragment類提供了多 次訪問JSP中這部分代碼的能力。JSP片段的定義不能 包含腳本或者腳本表達(dá)式,它只能是文件模板或者JSP 標(biāo)準(zhǔn)節(jié)點(diǎn)。 JspFragment類中有兩個(gè)方法:getJspContext、 invoke。我們的定義如下: public abstract JspContext getJspContext() public abstract void invoke(java.io.Writer writer) throws JspException, java.io.IOException getJspContext方法返回這個(gè)JspFragment關(guān)聯(lián)的 JspContext對(duì)象。可以通過invoke方法來執(zhí)行這個(gè)片段 (標(biāo)簽的內(nèi)容),然后通過指定的Writer對(duì)象把它直接 輸出。如果把null傳入invoke方法中,那么這個(gè)Writer將 會(huì)被JspFragment所關(guān)聯(lián)的JspContext對(duì)家中的getOut方 法返回的JspWriter方法所接管。 看清單中所列出來的SelectElementTag類。使用 標(biāo)簽處理器可以輸出如下格式的HTML select節(jié)點(diǎn): <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的 國(guó)家名。 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é)點(diǎn)用于注冊(cè)SelectElementTag, 并把它轉(zhuǎn)成select的標(biāo)簽。接著,像上面的例子一樣, 我們繼續(xù)把這個(gè)節(jié)點(diǎn)加入到mytags.tld文件中。 <tag> <name>select</name> <tag-class>customtag.SelectElementTag</tag-class> <body-content>scriptless</body-content> //scriptless代表無腳本 </tag> JSP頁(yè)面 <%@ 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時(shí),都要獲取一次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 |
|
|