struts系列學習(tiles標籤庫二)

Tiles的使用(二)- -

                                      

Tiles定義
          
我們需要一種方法,在一個單獨的可複用文件中定義所有的attributes和properties,當參數改變時能夠重載這個文件,這就是Tiles Definitions要做的事情。好,下面就來吧!
1.)聲明Definitions
          所需信息:模板路徑,零個或多個屬性(屬性名和值對),唯一標示符。
          如你所見,Definitions和<tiles:insert> 標記間真正的不同在於Definition 可以命名。儘管只加入了一個標識符,卻擁有了新的特性:
  1. 可以通過傳遞附加或替換屬性而重載
  2. 可以通過父類Definitions擴展爲其他Definitions
  3. 可以通過存儲在一個JSP 中的Definitions或者從一個XML 文檔中裝載而重用
  4. 可以是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.。作爲一個Bean中保存在JSP中,用id 作爲屬性標識。<tiles:definition>標籤支持scope屬性,默認爲page。這個Definitions只對該JSP餘下的部分有效。

部署聲明的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/> 
要使用聲明的Definition,可以用<tiles:insert>標記,通過id名稱來調用上面聲明的Definition。
啓動時,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>
這段代碼可以看到,body使用了一個新的屬性值。還新增加了extra屬性,這就意味着佈局(layout)沒有管理到這個tile,但如果提供也可以顯示。佈局時可以使用ignore標籤,當ingore設置爲true時,如果屬性不存在將不會報告錯誤。父類Definition繼承來的myLayout.jsp怎樣要添加一個extra tile::

 <tiles:insert attribute="extra" ignore="true" />

 
複用Definition:在上面的例子中看到,我們在重載某些屬性前不得不重複的Definitions,這當然是非常不實際的方法。有一種更加簡單的好方法,看下面的例子:
 <%@ 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>
使用標準的JSP include標籤把Definition引入,你能夠想平常一樣使用Definition。在例子中,也重載了title和body屬性。這種複用的方法對於擁有少量Definition來說是好的。但有個缺點,每次文件被include的時候,會把Definitions重新創建執行,這就影響了性能。在開發過程中這仍是個好方法,因爲對Definition的修改在下次頁面裝載時就會體現出來。通常可以這樣使用,在一個工作區中創建一個帶有scope屬性的Definition,再用Structs的<logic:notPresent>塊來包含:
 <%@ 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>
這樣做就不會重新創建Definitions了。每個頁面仍然需要包含Definition並檢查是否存在,但至少它們不需要再被不斷創建了。
       Tiles提供一個更好的方法來一次性裝載和複用Definition:使用XML文檔。Definition直接用來ActionFrowards。這是個管理Tiles Definitions的好方法,請看下面的內容。
 
3.)使用配置文件聲明
        
在一個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>
 
擴展Definitions:一個Definition能夠被聲明爲另一個Definition的子類。新的Definition繼承了父類Definitions的所以東西。
 <definition name="portal.page" extends="portal.masterPage">
<put name="title" value="Tiles 1.1 Portal" />
<put name="body" value="portal.body" />
</definition>
這種繼承能力允許我們聲明一個父Definition(設置缺省的屬性),然後以特定的屬性來擴展Definition(如title 和body)。如果你的所有定義都是從一個父Definition中擴展而來,那麼在父Definition中的修改就會影響到所有從它擴展的Definition。這和重載很相似但增加了持久性。重載描述了我們在哪裏標識了Definition,並且傳遞給他新的參數(或者屬性), 就象調用一個方法,並傳遞給它參數。但重載不能在一個<tiles:insert>標籤中調用另一個<tiles:insert>,所以重載Definitions是不能被引用和複用的。通過使用extend 屬性就可以創建一個新的Definition。這個新的Definition可以被插入和重載,甚至被其他Definition擴展,它通過繼承關係仍然指向它們的祖先Definition。重載或擴展一個Definitions能顯著的減少頁面多餘的信息。每個標籤,導航欄和內容組件在你的web站點中只要聲明一次。這些組件就能被複用到任何你想要的地方了。
       這非常的酷!但我們需要一個額外的頁面來放置Definition,意思是說要添加一個新內容的頁面(content page),就要新增一個頁面,然後再用一個頁面來插入這個標識新內容的Definition。如果一個普通的應用程序有60個內容頁面,就會有60個頁面,那一個模板應用程序就至少會有120個頁面來包含所有內容。模板頁面比其常規頁面要小巧而簡單,但文件的管理還是個問題。一個好的解決放方案是用Structs ActionFrowards來放置Definition。
 
將Definitions作爲ActionForwards:
       在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> 
然而,用斜槓的方式可能和與Action 和頁面URI 相關的標識符相沖突。推薦在Tile 定義中使用點號,而在ActionForward 中使用斜槓語法,確保名稱是會衝突。Action類常會忽略ActionFrom路徑,而是通過它的名稱來處理。所以用Tiles Definition來代替URL,大部分Action類不需要重新構建。你可以混合使用常規的ActionForwards和Tiles-Definition-ActionForwards,這樣模板頁面的數量會明顯的下降。對需擁有60個頁面的應用程序,我們只需要60個內容頁面加上少量提供標準的導航和佈局的工具tile 。但是創建第61 個頁面時,只需要再創建一個提供內容的JSP 和一個XML Definition,而後者只不過是簡單的一行文字。
 
Tiles屬性
1.)useAttribute
        
<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" />
<useAttribute> 標記與<useBean> 動作和Struts <bean:define> 標記相對應,允許訪問Tiles中的屬性。
每個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
3.)put
        
<tiles:put>標籤,被用來聯繫屬性和屬性值,name屬性用字符串來指定,屬性值分三種:tag property,tag body,JavaBean。
4.)putList and add
            
 
 
 
<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" />
或:<tiles:put name="title" value="<%=myObject%>" />   // 是運行時的表達式
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title">My first page</tiles:put>
或:<tiles:put name="title"><bean:write message="first.pageTitle"/></tiles:put>  // 是標記體
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanScope="session" />  /* 獲取beanName標識的對象,然後其值被用作爲屬性值。beanScope用來搜索bean的作用域,如果沒指定會調用pageContext.findAttribute()方法,這邊添加了Tiles中專有的"tiles"的作用域(支持page,request,application),用來在tiles中搜索bean。*/
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanProperty="myProperty"/>  // 相當於調用myBean.getMyProperty()來
                                                                                                            // 指定tile的屬性值
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="footer" value="/tiles/footer.jsp" type="page"/> //type有三種:string -- value值做爲字符串輸出; 
                                                                                          //                    page-- value值做爲一個URL;
                                                                                          //                    definition-- value值做爲Definition名稱 
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" value="myValue" role="myManager"/> 
 /* 當使用基於容器的安全認證時,你也可以爲一個tile指定role,如果用戶不是指定的role,value值就不會被設置,這允許你爲每個安全角色指定一個tile,而讓框架爲當前的用戶選擇相應的Tile。 如果<put>用在<tiles:insert>標籤中,role立即被驗證,用在<tiles:definition>中,role在Tiles內容初始化時被驗證。      */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章