sitemmesh是一個頁面裝飾框架,利用它可以很簡單的對整個系統進行統一架構裝飾,比如一個應用系統的web層可能就是top+left+content+footer四個部分組成(下圖)
使用sitemesh定義好一個統一的框架后,程序員只需要關注動態的內容部分就可以了,而不需要在每個頁面去單獨的include一堆的footer,left,header之類的公共部分--框架只是一個工具,存在的目的在於提高生產率,減少重復勞動。
以下是這個sitemsh的裝飾頁面源碼
<%@ page contentType="text/html; charset=GBK"%> <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title><decorator:title default="裝飾器頁面..." /></title> <decorator:head /> </head> <body> <jsp:include page="/header.jsp"></jsp:include> <jsp:include page="/left.jsp"></jsp:include> <decorator:body /> <jsp:include page="/footer.jsp"></jsp:include> </body> </html>非常簡潔明了,把頁面拆成可復用的組件單元,通過jsp include來引入
實際生產中的問題
做一個系統,可能有多個模塊組成,通常會給每個模塊分配一個namespace或package,如一個用戶管理系統可能有user和system兩個模塊組成,那么其訪問鏈接很可能是http://localhost:8080/user/userList.action和http://localhost:8080/system/sysConfig.action,這個時候對於不同模塊其對應的左側菜單或header部分很可能是不同的,如user模塊左側菜單是創建用戶,修改密碼,而system模塊則是配置系統參數,發送email等,怎樣用sitemesh來實現對於不同模塊加載不同的左側菜單的目的呢?通常有兩種方式
1.創建多個decorator,為每個模塊都創建一個單獨的decorator,在decorator里加載不同的left菜單
優勢:配置簡單,理解成本比較小
劣勢:對於絕大數系統來說,多個系統模塊的模塊一般都是統一的,配置多個decorator意味着創建個裝飾頁面,這些裝飾頁面里可能95%以上的代碼都是一樣的,不同點在於include不同的left.jsp文件
2.一個decorator,使用動態參數來動態加載哪個left.jps文件
實現原理:當前請求所在模塊作為參數傳遞給sitemesh,sitemesh讀取該參數,並去對應模塊加載各自的left.jsp文件,這樣就存在以下的問題
a)所在模塊信息存放在哪里?
通常的做法是在動態頁面的<head>元素中添加一個<meta>元素,meta元素其實可以簡單的理解成一個key-value的數據節點,如在user模塊的創建用戶頁面/user/createUser.jsp里添加
<meta name="moduleName" content="user"/>,而在system模塊的系統配置頁面/system/sysConfig.jsp頁面添加如下 <meta name="moduleName" content="system"/>
b)sitemsh怎么讀?
對於所有的jsp頁面,根據jsp頁面所在的模塊不同,也存放為不同的頁面下,這里做一個統一的命名約束,對於各個模塊的左側菜單,都統一命名為left.jsp,其目錄結構如下
/user/ left.jsp
/user/createUser.jsp
/system/ left.jsp
/system/sysConfig.jsp
有了這樣的命名約束后,我們就可以在sitemesh的裝飾頁面做文章了
<%@ page contentType="text/html; charset=GBK"%> <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <html> <head> <title><decorator:title default="裝飾器頁面..." /></title> <decorator:head /> </head> <body> <jsp:include page="/header.jsp"></jsp:include> <decorator:usePage id="thePage" /> <!-- 把當前頁面賦值給thePage這個變量--> <jsp:include page="/<%=thePage.getProperty("meta.moduleName")%>/left.jsp"></jsp:include> <decorator:body /> <jsp:include page="/footer.jsp"></jsp:include> </body> </html>