Tiles提供的模板機制可以最大限度地避免重復編寫代碼。實際上,Tiles模板就是的JSP頁面,只是在這種JSP頁面中使用Tiles標簽代替確定不了的內容(相當於占位符),也就是需要在開發人員使用模板時來確定的內容。除了這一點,Tiles模板頁面和普通的JSP頁面完全相同。
一般的模板頁面可以有如下兩種占位符:
1.字符串:使用<tiles:getAsString>標簽進行占位。如<tiles:getAsString name = "title" />。
2.Web資源(包括JSP、Servlet、HTML等):使用<tiles:insert>標簽來占位,如<tiles:insert attribute="header" />。
下面我們來看一下如何編寫一個Tiles模板。在Web根目錄中建立一個layout.jsp文件,代碼如下:
<%@ page pageEncoding="GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>
<html>
<head>
<title><tiles:getAsString name="title" /></title>
</head>
<body>
<table border=<tiles:getAsString name="border" />>
<tr>
<td>
<tiles:insert attribute="header" />
</td>
</tr>
<tr>
<td>
<tiles:insert attribute="body" />
</td>
</tr>
<tr>
<td>
<tiles:insert attribute="footer" />
</td>
</tr>
</table>
</body>
</html>
從上例可以看出有五處占位符,這些內容將由開發人員在使用layout.jsp模板時指定。在編寫完上述模板後,在Web根目錄中建立三個在模板中使用的JSP文件,代碼如下:
header.jsp
<%@ page pageEncoding="GBK"%>
這是一個頁頭
body.jsp
<%@ page pageEncoding="GBK"%>
這是一個頁體
footer.jsp
<%@ page pageEncoding="GBK"%>
這是一個頁尾
下面我們來使用這個模板。在Web根目錄中建立一個mypage.jsp文件,代碼如下:
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>
<tiles:insert page="layout.jsp">
<tiles:put name="title" value="我的頁面" />
<tiles:put name="border" value="${param.border}"/>
<tiles:put name="header" value="header.jsp"/>
<tiles:put name="body" value="body.jsp"/>
<tiles:put name="footer" value="footer.jsp"/>
</tiles:insert>
從mypage.jsp頁面中可以看出,在<tiles:insert>標簽中通過page屬性插入了layout.jsp頁面(也就是Tiles模板),並且在<tiles:insert>標簽中使用了< tiles:put>子標簽為layout.jsp頁面中的占位標簽指定參數值。如果是<tiles:getAsString>標簽,就會將<tiles:put>標簽中的value屬性值解釋為字符串;如果是<tiles:insert>標簽,就會將< tiles:put>標簽中的value屬性值解釋為Web資源。大家可以看到,如果有多個使用layout.jsp模板的JSP頁面,都可以按著 mypage.jsp頁面的方式使用這個layout.jsp模板,而無須再重復編寫象table這樣的HTML元素。
在啟動Tomcat後,我們可以使用如下兩個URL來測試程序:
http://localhost:8080/samples/mypage.jsp?border=1
http://localhost:8080/samples/mypage.jsp?border=0
注意:由於<tiles:insert>和<jsp:include>標簽類似,被插入或包含的Web資源都無法改面當前頁面的字符集編碼,因此,在使用Tiles模板時,即使在當前頁沒有使用中文,也應該使用page指令設置相應的字符集編碼。如果沒有設置,當模板頁面中有中文字符時,即使模板頁面使用了正確的字符集編碼,在當前頁面仍然無法正常顯示中文字符。
上面曾講過,Tiles框架的目的就是最大限度地避免重復編寫代碼。而上面的例子雖然已經基本上避免了重復編碼的工作,但仍然可能會存在一些重復的代碼。如在mypage.jsp頁面中的<tiles:put>標簽。如果有很多頁面都需要插件頁頭、頁尾,那麼就會有很多插入相同頁面的<tiles:put>標簽被分布在不同的JSP頁面中。因此,Tiles框架又提供了一個定義文件,來定義些重復使用的Tiles標簽。在使用定義文件之前,需要首先安裝Tiles插件(如果不使用定義文件,是不需要安裝Tiles插件的)。
下面我們來將上面的部分代碼放到定義文件中。在WEB-INF目錄中建立一個tiles-defs.xml文件,代碼如下:
<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://struts.apache.org/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<definition name="myLayout" path="/layout.jsp">
<put name="title" value="我的頁面" />
<put name="header" value="header.jsp" />
<put name="body" value="body.jsp" />
<put name="footer" value="footer.jsp" />
</definition>
</tiles-definitions>
在上面的代碼中定義了一個<definition>元素。並且使用< put>元素對四個屬性:title、header、body和footer賦值。因此,如果使用這個定義文件,就可以無需使用< tiles:put>標簽再賦一遍值了。在Web根目錄中建立一個newpage.jsp文件,代碼如下:
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%>
<tiles:insert definition="myLayout">
<tiles:put name="border" value="${param.border}"/>
</tiles:insert>
newpage.jsp頁面的功能和mypage.jsp頁面完全一樣,只是代碼要簡單得多。由於只有border屬性需要設置,因此,在newpage.jsp頁面中只要設置這一個屬性即可。而在<tiles:insert> 標簽中使用了definition屬性指定了“myLayout”。這個值就是在tiles-defs.xml中<definition>元素的name屬性值。
在啟動Tomcat後,我們可以使用如下的URL來測試newpage.jsp:
http://localhost:8080/samples/newpage.jsp?border=1
為了更好的復用,在定義文件中的<definition>元素也可以繼承其他的<definition>,如我們可以在tiles-defs.xml文件中加一個<definition>元素,來繼承myLayout,代碼如下:
<definition name="myLayout.newLayout" extends="myLayout">
<put name="title" value="新的頁面" />
</definition>
上面的代碼覆蓋了myLayout中的title屬性,其他的屬性值都繼承了myLayout中相應的屬性值。其中name屬性的值中的“.”是為了表明這個新的<definition>元素是從myLayout繼承的,沒有特殊的含義。