今天在公司用到了sitemesh這個框架。
網上的資料已經有很多了。 在此就不做具體介紹了, 僅僅做個筆記。
sitemesh是一種模板框架,是為了解決頁面重復代碼而設計的。
設計思想
sitemesh的設計思想是裝飾者設計模式。
由於本文討論的是sitemesh,並不是設計模式。故在此簡單地說明一下裝飾者這個設計模式。
java io就是常見的裝飾者設計模式應用的地方。 用各種FilterInputStream裝飾InputStream。
一個常見的例子就是讀取文本文件中的文本。
用FileInputStream這種文件流讀取的時候,速度較慢,而用BufferedInputStream裝飾FileInputStream的時候效率提高了很多。
因為BufferedInputStream對FileInputStream讀取的數據做了二次處理,內部有個緩沖區對讀取的數據進行暫存。
sitemesh也是同樣的道理,通過裝飾器將返回的頁面需要裝飾的部分用其他頁面先裝飾好,然后再處理不需要裝飾的頁面。
實例
實例使用idea作用ide,用maven構建項目。 前端框架使用bootstrap和jQuery。
項目結構如下:
maven加入sitemesh依賴即可。
<dependency> <groupId>opensymphony</groupId> <artifactId>sitemesh</artifactId> <version>2.4.2</version> </dependency>
效果圖:
從實例可以看出,頭部logo和底部,還有導航條這3個東西是固定不變的。
點擊導航條這些內容是不變的,變的只是導航條下面的內容。 因此sitemesh在這種場景就用上了。
使用sitemesh還是非常簡單的。 只需要3步。
1. 配置filter
<filter> <filter-name>SiteMeshFilter</filter-name> <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>SiteMeshFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這里注意一下,sitemesh老版本的filter是PageFilter。 目前這個Filter已經過時,使用新的SiteMeshFilter。
2.在WEB-INF文件夾下創建decorators.xml文件,內容如下:
<?xml version="1.0" encoding="utf-8"?> <decorators defaultdir="/layouts/"> <excludes> <pattern>/static/*</pattern> </excludes> <decorator name="default" page="default.jsp"> <pattern>/*</pattern> </decorator> </decorators>
根標簽decorators有個defaultdir屬性,也就是前綴目錄。下面的decorator標簽的屬性中的page屬性default.jsp這個模板頁面具體位置就需要加上之前那個前綴目錄。也就是/layouts/default.jsp。項目結構中已說明的很清楚。同時這個模板頁面作用於所有的頁面,因為它的pattern是/*,這個跟filter類似。excludes這個標簽顧名思義,也就是排除某些url,使之不使用模板。 比如一些靜態的html頁面和不需要使用模板的頁面。
3.建立模板文件
模板文件也就是/layouts/default.jsp。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title><decorator:title/></title> <link rel="stylesheet" href="static/bootstrap.min.css"/> <link rel="stylesheet" href="static/bootstrap-theme.min.css"/> <script type="text/javascript" src="static/jquery1.11.0.js"></script> <style> .body,.foot { margin-top: 50px; } </style> </head> <body> <div class="head">logo</div> <div class="body"> <div> <ul class="nav nav-pills" id="nav"> <li id="home"><a href="index.jsp">Home</a></li> <li id="page1"><a href="page1.jsp">Page1</a></li> <li id="page2"><a href="page2.jsp">Page2</a></li> </ul> </div> <div> <decorator:body/> </div> </div> <div class="foot">address...</div> </body> </html>
引用了1個標簽庫。 decorator, 也就是sitemesh提供的標簽庫。 模板文件中<decorator:body/>和<decorator:title/>這兩部分是需要引用具體頁面的。其他的內容均引用自這個頁面。
原理
當瀏覽器進入頁面首頁的時候,會進入index.jsp.
index.jsp內容如下
<head> <title>主頁</title> </head> <body> <h1 style="background-color: red;">除body之外其他的內容已經全部在/layout/default.jsp中定義了。</h1> <input type="button" value="click"/> <script type="text/javascript"> $("#nav li").removeClass('active'); $("#home").addClass('active'); </script> </body>
由於配置了filter。因此進入這個頁面之前,請求已經被filter截取。
filter會先得到模板頁面,也就是/layout/default.jsp這個頁面。
由於default.jsp這個頁面有兩處內容需要具體頁面渲染,因此這兩處內容就由新進入的這個頁面進行渲染。即<decorator:title/>對應"主頁",<decorator:body/>對應body標簽內的內容。
同理,page1和page2頁面也這樣處理。
page1.jsp
<head> <title>頁面1</title> </head> <body> <h1 style="background-color: green;">頁面1.....</h1> <script type="text/javascript"> $("#nav li").removeClass('active'); $("#page1").addClass('active'); </script> </body>
page2.jsp
<head> <title>頁面2</title> </head> <body> <h1 style="background-color: blue;">頁面2.....</h1> <script type="text/javascript"> $("#nav li").removeClass('active'); $("#page2").addClass('active'); </script> </body>
總結
sitemesh配置簡單,因為只對response回去的code進行二次渲染,這樣基本不會影響業務邏輯,非常推薦使用。