Tiles的使用(一)
綜述
可用性是當今應用程序設的主要關注點,一致性(consistency)是可用性的主要因素。用戶想要專注於手上的任務,卻會被應用程序界面或屏幕的佈局的小問題而擔擱。保持動態web應用程序一致性是個很大挑戰,因爲一般都是手動對每個頁面進行編碼的。如今已經有許多針對靜態頁面的佈局設計工具可以提供給設計人員,但基於JSP的很少。更糟的是,應用程序的外觀往往是到最後纔會被確定下來,然後會在不同的版本間改變,甚至是對一個大型的web站點隨意的重新佈局(relaunch)。在最後的期限編碼或測試,即使是改變背景色或添加一個新的鏈接到工具欄上,也像是一場惡夢!
在書的一開始,我們着重講了應用程序分層的重要性,這樣能減少改動帶來的影響。通過對應用程序的分層,我們可以修改某個部分而不會影響其它部分。表現層使用相同的設計,實現了內容和外觀的分離。將內容從佈局(layout)中分離出來,可以使用動態的JSP include。JSP規範提供了靜態的和動態的include。標準的動態JSP include的動作是:<jsp:include>。
我們可以使用動態include把頁面分成幾個片斷,每個都有自己特有的用途。把一個後臺模板設成缺省的佈局頁面,運行時用這些片斷來提供內容。
Tiles框架是一種更加高級的JSP include行爲的表現形式。在Tiels應用程序中,模板常被用來定義header,menu body,content和footer的位置。其它的頁面用來向這些頁面填充內容。如果header需要改變,只要修改模板文件就可以了。這種改變會自動的應用到每個使用模板的頁面中。改動帶來的影響會降到最低。
標準的HTML組件,象CSS也能很好的工作在動態模板下,這樣能進一步降低改動的影響。
Dynamic element (動態元素) |
JSP 的一部分,會被JSP翻譯器識別,包括action,directive,expression, JSP標籤, 或scriptlet |
Template data (模版數據) |
JSP的一部分,通常不被JSP 翻譯器轉換,而被逐字傳遞到響應之中。 通常是標記或者可視文本 |
Template page (模版頁面) |
一個包含其他頁面或者被其他頁面包含的JSP |
Template file (模版文件) |
一個包含模版頁面的靜態文件或者JSP文件 |
Tile | 模版頁面的同義詞 |
Layout (佈局) |
描述模版文件或tiles應該如何在頁面中定位 |
Tiles | 一個強大易用的模版和佈局框架 |
Definition (定義) |
一個Tiles 特徵,允許一個佈局被標識爲一個模版頁面,或者一個JavaBean。也可以用一個XML 文檔來描述 |
當HTML 表格第一次引入時,頁面設計者馬上將它作爲是一種佈局方式。無邊框的表格可以用來包含其他表格和內容,這是一種與衆不同的佈局方式。同樣的想法經常用在動態模板中,一個主模板用來提供頁面的佈局和組件位置,頁面片段被包含進來填充這些組件。頁面片段可以被包含進各種類型的佈局:無邊框表格,<div>標記,甚至最簡單的將一個組件堆在另一個組件之上。
Tiles 是一個用簡單但有效的標記庫來實現模板和佈局的框架。它可以用來替換Struts1.0 中的模板標記庫但功能更強大。Tiles包也用在任何的JSP應用程序中。
通常,JSP 模板系統都是使用一個模板作爲佈局,而其他作爲填充組件。Tiles 稱之爲佈局文件Definitions。大多數模版系統都要求有一個額外的文件作爲佈局文件。爲避免這種麻煩,Tiles允許佈局Definitions像一個JavaBean一樣被存儲。而且,在Struts 中還有個擴展,允許Definitions是一個ActionForward 的目標。這是一個激動人心的特徵,現在讓我們從頭開始,創建一個新的佈局。 你可以在下面代碼中見到,我們創建用來包含佈局組件的地方,都放置了一個JSP 標記,像
<tiles:insert attribute="aName"/>。意思是說在這裏插入屬性值指代的tile(或者模板文件) 。當要在應用程序中使用這個模板的時候,只要傳遞給它這個文件的路徑。這允許我們在多處使用同一個模板,只需要簡單的傳遞一個或多個不同tile的路徑。
在大多數情況下,每個頁面的body tile可能不同,但是同一模塊中所有頁面可以共享相同的header和menu tile。同時,可能同一站點的所有頁面都要共享同一個footer tile。當新的一年過去,需要在每個頁面中更新版權聲明,這時只要修改footer tile就行。接着只需要加入剩下的HTML 標記,一個完整的獨立的模板頁面就完成了。
爲了能快速完成一個例子,我們將構建一個典型的有一個header,menu,body和footer的web頁面。佈局如下:
herder |
|
menu |
body |
footer |
創建一個像上圖一個的模板頁面是很容易的:
- 打開一個新的JSP頁面
- 導入Tiles標記庫
- 創建一個匹配上圖的HTML表格
- 使用Tiles JSP tag -<tiles:insert>去命名佈局中的每個部分
<%@ taglib uri="/tags/tiles" prefix="tiles" %> |
但什麼是tile呢?
Tiles 框架提供的模板特性要遠遠超過標準Servlet 和JSP include 所提供的。框架稱其模板爲tiles。這有助於說明tiles比簡單的JSP 模板功能更加強大。對於你的表現層,Tiles就象是積木。
學術上,tile是JSP中的一個矩形區域,有時也稱爲區域(region)。一個tile 也可以由其他tile 組合而成。Tiles能被遞歸構建,像是一顆樹,樹上的每個節點是一個區域,根節點是頁面,最終節點或葉節點包含內容,中間的節點通常被用來佈局。佈局節點很有用,可以確定位置一個tile或爲內容tile提供後臺標籤。
- Parameters--參數
在運行期間一個tile能夠以參數或屬性的形式接受不同的信息,據這些信息表現出不同的效果。tiles 參數通常稱爲屬性(attribute)以避免和請求參數相沖突。Tile的屬性插入tile時被定義,此屬性只有在這個tile中可見。對於子tiles或包含該tile的頁面也是不可見的。當相同的tile多次用在相同的頁面中時,可以避免名稱衝突。開發人員就可以着力於構建Tiles而不用擔心名字衝突的問題了。tile屬性可以是String或其它類型。 - Definitions--定義
各種屬性通過一個tile組合在一起用來描述屏幕的顯示。在實際中,這些描述是有關聯的,往往是構建在其它tile之上的。Definitions存儲一組屬性,有自己標識的獨立對象。聲名一個base Screen Definitions,然後在這個基礎上建立其它的Definitions。如果這個base Screen改變了,在這個base Screen上擴展的所有Definitions也會改變。這就將面向對象的繼承和封裝原理帶到了你的動態頁面中。Definitions是可選的,也可以隨時用一個簡單的JSP標記來部署Tile。
部署Tiles模板
上面說了在什麼地方使用Tiles,接着要介紹怎麼使用Tiles ,下面是hello.jsp的源代碼,使用的是myLayout.jsp的佈局方式:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:insert page="/layouts/myLayout.jsp" flush="true"> <tiles:put name="title" value="Hello World" /> <tiles:put name="header" value="/tiles/header.jsp" /> <tiles:put name="footer" value="/tiles/footer.jsp" /> <tiles:put name="menu" value="/tiles/menu.jsp" /> <tiles:put name="body" value="/tiles/helloBody.jsp" /> </tiles:insert> |
將下面的代碼:
<tiles:put name="title" value="Hello World" /> <tiles:put name="body" value="/tiles/helloBody.jsp" /> |
替換爲:
<tiles:put name="title" value="Hello Again" /> <tiles:put name="body" value="/tiles/pageTwo.jsp" /> |
這就很容易產生一個只有title和body與hello.jsp不同的新頁面了。
但是,要注意的是,執行上面的步驟,要創建兩個新的頁面:一個是hello.jsp,第二個是要插入hello.jsp的包含內容的頁面,像helloBody.jsp。下面的方法就不需要產生兩個頁面。
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:insert page="/layouts/myLayout.jsp" flush="true"> <tiles:put name="title" value="Hello World" /> <tiles:put name="header" value="/tiles/header.jsp" /> <tiles:put name="body" type="string"> //直接打印下面的內容 <%-- Place the content from /tiles/pageTwo.jsp here --%> </tiles:put> <tiles:put name="footer" value="/tiles/footer.jsp" /> <tiles:put name="menu" value="/tiles/menu.jsp" /> </tiles:insert> |
使用put的type標籤,像上面的例子中使用的type="String",直接把helloBody.jsp的內容放進這個標籤中,這樣就避免了創建多餘的tile了。唯一不好的是screen Definitions分散在站點的各處,這使得全局的修改很困難。但對於一個小型的應用程序,還是很有用的。
添加一個CSS
<%@ taglib uri="/tags/struts-html" prefix="html" %> <HTML> <HEAD> <TITLE><tiles:getAsString name="title"/></TITLE> <html:base/> <LINK rel="stylesheet" type="text/css" ref="<html:rewrite page='/assets/styles/global.css'/>"> </HEAD> <BODY> |
還可以使用<html:base> 標記來引入CSS或其它資源。