在J2EE項目中,JSP頁面常常通過在靜態(tài)頁面模板中嵌入scriptlets來插入動態(tài)的內(nèi)容。然而,隨著復雜程序的增加,JSP頁面也變得難于管理。 雖然用這種方法開發(fā)小形項目唾手可得,但是scriptlets仍然要面對下面的不利情況:
與其創(chuàng)建充滿了scriptlets的巨大的JSP頁面,不如考慮使用用戶自定義標簽。用戶自定義標簽允許你創(chuàng)建、在JSP中使用你自己定義的類HTML標簽。每當JSP引擎遇到用戶自定義標簽時,就會自動查找標簽處理類,并自動調(diào)用他。頁面中的自定義標簽將會被票簽處理類的輸出所代替。這就使得JSP頁面不用直接在頁面寫Java代碼,就可以指定生成動態(tài)的內(nèi)容的。 用戶自定義標簽為你的網(wǎng)頁設(shè)計提供了N種好處:他提高了頁面代碼的可讀性。頁面設(shè)計人員而不是程序員,能夠使用很比使用Scriptlets更容易的使用標簽。維護代碼的程序員也只需個性標簽庫面不是JSP頁面,這樣他就不要再冒著破壞頁面美觀的風險。 在使用標簽的每一處,增強或者固定的標簽改變了標簽了的表現(xiàn)。標簽比Scriptlets更容易確定參數(shù),因為他會被 作為一種屬性或者在標簽體內(nèi)被傳達。最后,標簽比Scriptlets高度的可重用性,因為你可以創(chuàng)建共享的、可重用的自定義標簽庫。 JSTL提供的就是這種標準的自定義標簽集。 讓我們通過看一個簡單的JSP頁面例子,來看看如何使用自定義標簽。 下面這個頁面使用scriptlet來得到數(shù)據(jù): <%@ page import="java.text.SimpleDateFormat" %> <%@ page import="java.util.Date" %> <HTML> <HEAD><TITLE>Sample JSP</TITLE></HEAD> <BODY> <H3> The date and time at the server are: <% String sformat = "EEEE, d MMMM yyyy ‘a(chǎn)t‘ kk:mm:ss z"; SimpleDateFormat format = new SimpleDateFormat(sformat); Date date = new Date(); String sdate = format.format(date); out.print(sdate); %> </H3> </BODY> </HTML>
這個頁面非常的簡單直接,盡管這個簡單的函數(shù)看上去好像有許多東東。如果你想要在每一個頁面上顯示日期,那么你只能拷貝粘貼這段代碼到項目中的每一個頁面。如果你這么做,那么你要維護的不僅僅是這段代碼的原始拷貝,而是你粘貼的每一個拷貝。 如果這段代碼出現(xiàn)在多個頁面,那么改變一下時間格式將會占用你的很多時間。 下面這段是一個非常清潔的JSP頁面。在這里,Java代碼被從scriptlet中移出放到了自定義標簽中: <%@ taglib uri="/WEB-INF/taglib.tld" prefix="mytags" %>
<HTML> <HEAD><TITLE>Sample JSP using a custom tag</TITLE></HEAD> <BODY> <H3> The date and time at the server are: <mytags:date/> </H3> </BODY> </HTML> 在這個例子中,<@% taglib %>用來指出自定義標簽描述符文件路徑(標簽庫中的描述符或者TLD文件),并且為這個標簽名定義一個名字空間(“mytags”,可是你喜歡的任何字符)。JSP引擎認可<mytags:date/>作為一個用戶定義標簽的符號,他會調(diào)用這個標簽的標簽處理器,并用處理結(jié)果替換標簽和內(nèi)容。 創(chuàng)建一個用戶定義標簽處理器 創(chuàng)建一個用戶定義標簽處理器需要比定scriptlet多一定量的工作,因為這一個Java類,并且你不得不為他寫一個TLD格式(在下一節(jié)介紹)的描述符文件。下面這個類DataTag實現(xiàn)了一個標簽處理器: public class DateTag extends TagSupport {
protected PageContext _pageContext; protected String _sFormat; static final String _sFormatDefault = "EEEE, d MMMM yyyy ‘a(chǎn)t‘ kk:mm:ss z";
public void setPageContext(PageContext pageContext) { _pageContext = pageContext; _sFormat = _sFormatDefault; }
// Handle the tag public int doStartTag() throws JspException { SimpleDateFormat format = new SimpleDateFormat(getFormat()); JspWriter out = _pageContext.getOut(); Date date = new Date(); String sdate = format.format(date); try { out.print(sdate); } catch (IOException ex) { throw new JspException("DateTag: can‘t write: " + ex.getMessage()); } return SKIP_BODY; }
// Handlers for "format" attribute public void setFormat(String sFormat) { _sFormat = sFormat; }
public String getFormat() { return _sFormat; } } TagSupport實現(xiàn)了標簽處理器要求的所有接口。這些方法本來沒有做什么任何事,標簽處理器開發(fā)人員重構(gòu)了需要方法,允許基類處理調(diào)用所有的其他的方法。標簽處理器每一次被調(diào)用都會調(diào)setPageContext方法。 這個類為稍后便用簡單的保存了PageContext參照。 當JSP引擎遇到這個標簽時會調(diào)用doStartTag方法。這個方法和第1個版本JSP頁面的scriptlet處理了相同的事。他將結(jié)果寫回給JspWriter,結(jié)果包括了先存儲的PageContext.所有寫給JspWriter的內(nèi)容,會被直接嵌入到響應頁面。 注意doStartTag只能拋出JspException異常。如果發(fā)生寫失敗,那么原始IOException會被轉(zhuǎn)化成一個JspException重新拋出。這個方法會返回SKIP_BODY,他告訴JSP容器拋棄標簽內(nèi)容。 標簽處理器最后的兩個方法是setFormat和getFormat。機敏的讀者應該已經(jīng)知道了他作用。 他被網(wǎng)頁容器用來設(shè)置標簽屬性值(后面進行更詳細的討論)。在這兒他們被用來設(shè)定日期格式屬性和輸出日期格式屬性。 標簽定義:TLD文件 一個標簽庫描述符文件, 或者TLD文件, 是一個XML文件。他用來描述標簽庫中的標簽。以下是DateTag標簽的描述文件。 <?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java./dtd/web-jsptaglibrary_1_2.dtd">
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>first</short-name> <uri>http://www./j2eetips/sept2002/taglib</uri> <description>Sample tag library</description>
<tag> <name>date</name> <tag-class>com.elucify.tips.sep2002.DateTag</tag-class> <body-content>empty</body-content> <description>Print the date with a compiled-in format</description>
<attribute> <name>format</name> <required>false</required> <rtexprvalue>false</rtexprvalue> </attribute>
</tag> </taglib> 這些描述符提供了這個標簽庫的信息。他還提供了每一個標簽的如標簽名、處理器的類和標簽描述的信息。這個文件被用來替換WEB-INF目錄下的WAR文件,為JSP頁面使用這些標簽提供參照。 增加屬性 Notice that the TLD file shown above defines an attribute called format. This is the string passed to SimpleDateFormat to control how the date is printed. If a format attribute is present on a date tag, the JSP engine calls setFormat on the handler class. Otherwise, the handler class uses a default format. Attributes provide a great deal of customizability to custom tags. For example, the following JSP page uses the format attribute to format the date in several different ways on the same page: 注意上面這個TLD文件顯示的屬性調(diào)用格式 。這是一個字符串被傳遞給SimpleDateFormat,來控制如何顯示日期。如果一個日期格式被提供給日期標簽,那么JSP引擎將調(diào)用控制器類中的setFormat方法 ,否則,標簽處理器將使用默認格式。屬性為用戶定義標簽提供了大量可定制屬性。例如以下這個例子,在同一個頁面的, 用幾種不同的格式屬性來格式化時間。 <%@ taglib uri="/WEB-INF/taglib.tld" prefix="mytags" %>
<HTML%> <HEAD><TITLE%>Sample JSP using a custom tag and format</TITLE%></HEAD%> <BODY%> <H3%> The time zone at the server is <mytags:date format="zzzz"/%>.<br%> The server date is <mytags:date format="M/d/yyyy"/%>.<br%> The server time is <mytags:date format="hh:mm:ss a"/%>.<br%> </H3%> </BODY%> </HTML%> 想像一下,如果使用scriptlets,做同樣的事情,將會要多少行多余的代碼。 布署使用自定義標簽的JSP頁面 標簽處理器可以放在WEB-INF/classes目錄下,和TLD分離。 或者也可以將一組想關(guān)的標簽和TLD文件綁定成JAR文件,提供一個單一的布署。這個例子使用的是第一個方法。這不需要在web.xml中增加任何布署描述。 用戶自定義標簽大大提高了JSP頁面動態(tài)內(nèi)容代碼的可讀性、可伸縮性、可重用性和可維護性。 自定義標簽資源 You can learn how to implement several kinds of custom tags in the J2EE Tutorial section Custom Tags in JSP Pages. Also see the JavaServer Pages Standard Tag Library page. The Enterprise Java BluePrints has several best practices for Web components, including JSP pages and custom tags. Among other features, JavaServerTM Faces technology provides a large library of general-purpose custom tags. |
|