Tiles的使用(二)- -
我們需要一種方法,在一個單獨的可複用文件中定義所有的attributes和properties,當參數改變時能夠重載這個文件,這就是Tiles Definitions要做的事情。好,下面就來吧!
1.)聲明Definitions
如你所見,Definitions和<tiles:insert> 標記間真正的不同在於Definition 可以命名。儘管只加入了一個標識符,卻擁有了新的特性:
- 可以通過傳遞附加或替換屬性而重載
- 可以通過父類Definitions擴展爲其他Definitions
- 可以通過存儲在一個JSP 中的Definitions或者從一個XML 文檔中裝載而重用
- 可以是Struts ActionForward 的目標
有兩種方法來聲明Definitions:JSP和XML文檔。
2.)JSP聲明
這是個簡單快速的方法。它不能減少你模板文件的數量,但可以通過重載來複用。在運行時需要用一個存根(stub)文件來部署Definitions。在下一節,我們將看到將這些相同的Definitions將放入到一個XML 文檔,然後直接從Struts ActionForward 中進行部署,基本的流程都是一樣的。過程是:聲明-部署-重載-複用。
用一個JSP聲明一個Definitions:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> |
部署聲明的Definition:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <tiles:insert beanName="definitionName" flush="true/> |
啓動時,Tiles 使用XML 元素的id definitionName 創建一個Definition對象(或bean)。
運行時,<tiles:insert> 標記通過beanName 屬性引用定義id。
重載:可以重載某些或全部屬性。重載時,只需要一個新的屬性值。要創建一個新的屬性,包含一個新的屬性名稱和值就可以了。
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <tiles:insert beanName="definitionName" flush="true" > <tiles:put name="title" value="New PageTitle" /> <tiles:put name="body" value="/tiles/anotherBody.jsp" /> <tiles:put name="extra" value="/extra.jsp" /> </tiles:insert> |
<tiles:insert attribute="extra" ignore="true" /> |
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <%@ include file="definitionsConfig.jsp" %> <tiles:insert beanName="definitionName" beanScope="request" /> <tiles:put name="title" value="Another Page" /> <tiles:put name="body" value="/tiles/anotherBody.jsp" /> </tiles:insert> |
<%@ taglib uri="/tags/struts-logic" prefix="logic" %> <%@ taglib uri="/tags/tiles" prefix="tiles" %> <logic:notPresent name="definitionName" scope="application"> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <%-- … other definitions … --%> </logic:notPresent> |
Tiles提供一個更好的方法來一次性裝載和複用Definition:使用XML文檔。Definition直接用來ActionFrowards。這是個管理Tiles Definitions的好方法,請看下面的內容。
在一個XML 配置文件中聲明你的Definition,應用程序在啓動時裝載這個文件,並創建一個包含Definition的"Definition factory"。每個Definition用其屬性名稱來標識,並且要是唯一的。其他組件如ActionForward,就可以通過這個名稱來引用Definition。在一個XML 配置文件中聲明Tiles Definition需要一些額外的設置,以允許在應用程序初始化時可以讀取並裝載配置文件。《Structs in action》第4 章中,可以得到關於如何在Struts 1.1 中安裝Tiles。應用程序初始化時,XML 配置文件被讀取,然後解析到一個"Definition factory"中,該工廠包含了每個聲明過的Definition的實例。每個Definition應該有其唯一的名稱,以便它可以被JSP 標記或者StrutsActionForward 引用。定義的名稱及用作內部引用。它不是一個URI,不能直接被客戶端引用。使用XML 文檔的定義宣稱的流程和使用JSP 的處理並沒有什麼太大的不同。主要的不同點是他們如何被創建,如何被擴展,以及Definition如何可以被Struts ActionForward 使用。
創建配置文件:
XML 配置文件的總體格式有點類似於Struts 配置文件。令人驚訝的是,XML 配置文件文件之中使用的語法和Tiles <definition>標記相似:
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"> <tiles-definitions> <definition name="definitionName" page="/layouts/myLayout.jsp"> <put name="title" value="Hello World" /> <put name="header" value="/tiles/header.jsp" /> <put name="footer" value="/tiles/footer.jsp" /> <put name="menu" value="/tiles/menu.jsp" /> <put name="body" value="/tiles/helloBody.jsp" /> </definition> <!-- ... more definitions ... --> </tiles-definitions> |
<definition name="portal.page" extends="portal.masterPage"> <put name="title" value="Tiles 1.1 Portal" /> <put name="body" value="portal.body" /> </definition> |
這非常的酷!但我們需要一個額外的頁面來放置Definition,意思是說要添加一個新內容的頁面(content page),就要新增一個頁面,然後再用一個頁面來插入這個標識新內容的Definition。如果一個普通的應用程序有60個內容頁面,就會有60個頁面,那一個模板應用程序就至少會有120個頁面來包含所有內容。模板頁面比其常規頁面要小巧而簡單,但文件的管理還是個問題。一個好的解決放方案是用Structs ActionFrowards來放置Definition。
在Structs應用程序中,大多數的頁面不會被直接引用,而是封裝到ActionForward對象中。ActionForward給出一個唯一的邏輯名稱對應實際的URL,Action選擇和返回一個ActionForward給servlet控制器,ActionServlet通過ActionForward的路徑值控制轉發到指定的URL上。Tiles包包含一個ActionServlet的子類來檢查和Definitions有關的路徑值。如果Definitions的id和ActionForward的path匹配,Definitions bean被放置在request中,控制器會轉發到佈局,你組裝好的模板就會顯示。
<action path="/tutorial/testAction2" type="org.apache.struts.example.tiles.tutorial.ForwardExampleAction"> <forward name="failure" path=".forward.example.failure.page"/> //這邊可以使用斜槓代替圓點:path="/forward/example/failure.page" <forward name="success" path=".forward.example.success.page"/> </action> |
<tiles:useAttribute>標籤,使某個Tiles 的屬性在整個頁面中有效。其它標籤(像Struts <bean:write>)能引用的名稱用來傳遞參數。
<tiles:useAttribute name="myAttribute" /> <tiles:useAttribute attributeName="anAttribute" name="myAttribute" /> //標識另外一個屬性名稱 <bean:write name="myAttribute" /> //Struts bean 標記既可以引用這個信息 ------------------------------------------------------------------------------------------------------------------------------------------ 也可以用來聲明一個腳本變量供JSP scriptlet使用: <tiles:useAttribute id="list" name="myAttribute" classname="java.util.List" /> |
每個tile 都是一個不同的"頁面",每一個都有自己的頁面範圍。如果你想避免tile間的屬性衝突,可以使用page scope。如果你想一個屬性被另一個tile 共享,你可以使用request scope:
<tiles:useAttribute name="myAttribute" scope="request"/>
<useAttribute>的操作是按順序。頁面中後面tile也許可以使用某個屬性,而先前的tile也許不能使用它,因爲它還不存在。
2.)inportAttribute
<tiles:importAttribute>標籤,和<useAttribute>不一樣,它不支持重命名和作爲腳本變量使用。
<tiles:importAttribute/> //把所有的tile屬性導入到頁面作用域中 <tiles:importAttribute name="myAttribute" scope="request"/> //指定某個屬性的scope,scope默認值是page |
<tiles:put>標籤,被用來聯繫屬性和屬性值,name屬性用字符串來指定,屬性值分三種:tag property,tag body,JavaBean。
<tiles:insert page="menu.jsp" > <tiles:putList name="items"> <tiles:add value="home" /> <tiles:add value="documentation"/> </tiles:putList> </tiles:insert> // 兩個標籤聯合使用,指定一個列對象作爲單一屬性進行傳遞。 ------------------------------------------------------------------------------------------------------------------------------------------ <tiles:importAttribute/> <TABLE> <logic:iterate id="item" name="items" > <TR> <TD> <bean:write name="item"> </TD> </TR> </logic:iterate> </TABLE> //<putList>標籤常和<useAttribute>或<importAttribute>一起使用,以便能在一個頁面訪問別的標籤。 |
<tiles:put name="title" value="My first page" /> |