SiteMesh 是一個網頁佈局和修飾的框架,利用它能夠將網頁的內容和頁面結構分離,以達到頁面結構共享的目的。php
Sitemesh 是由一個基於Web 頁面佈局、裝飾以及與現存 Web 應用整合的框架。它能幫助咱們在由大量頁面構成的項目中建立一致的頁面佈局和外觀,如一致的導航條,一致的 banner,一致的版權,等等。它不單單能處理動態的內容,如 jsp,php,asp 等產生的內容,它也能處理靜態的內容,如 htm 的內容,使得它的內容也符合你的頁面結構的要求。甚至於它能將 HTML 文件象 include 那樣將該文件做爲一個面板的形式嵌入到別的文件中去。全部的這些,都是 GOF 的 Decorator 模式的最生動的實現。儘管它是由 java 語言來實現的,但它能與其餘 Web 應用很好地集成。css
下圖是SiteMesh的結構圖:html
SiteMesh 是基於 Servlet 的 filter 的,即過濾流。它是經過截取 response,並進行裝飾後再交付給客戶。java
其中涉及到兩個名詞: 裝飾頁面(decorator page)和 被裝飾頁面(Content page), 即 SiteMesh 經過對 Content Page 的裝飾,最終獲得頁面佈局和外觀一致的頁面,並返回給客戶。git
運行SiteMesh3至少須要:github
wiki上的下載連接爲:http://wiki.sitemesh.org/wiki/display/sitemesh3/Homeweb
GitHub上3.0.1版本下載地址爲(含demo):https://github.com/sitemesh/sitemesh3/releases/tag/3.0.1app
pom.xml文件添加如下依賴:框架
<!--sitemesh--> <dependency> <groupId>org.sitemesh</groupId> <artifactId>sitemesh</artifactId> <version>3.0.1</version> </dependency>
<web-app> ... <filter> <filter-name>sitemesh</filter-name> <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
該裝飾頁面包含Web應用程序中常見得佈局和樣式,它是一個包含<title>,<head>
和<body>
元素的模板。它至少要包含:jsp
<HTML> <HEAD> <title> <sitemesh:write property ='title'/> </ title> <sitemesh:write property ='head'/> </HEAD> <BODY> <sitemesh:write property ='body'/> </BODY> </HTML> 標籤`<sitemesh:write property='...'/>`將會被 SiteMesh 重寫,用來包含從『被裝飾頁面』(content page)中提取到的值。能夠從被裝飾頁面(content page)中提取更多的屬性,而且能夠自定義規則 。 在WEB應用程序中建立`/decorator.html`,其中包含: ```html <html> <head> <title>SiteMesh example: <sitemesh:write property='title'>Title goes here</sitemesh:write></title> <style type='text/css'> body { font-family: arial, sans-serif; background-color: #ffffcc; } h1, h2, h3, h4 { text-align: center; background-color: #ccffcc; border-top: 1px solid #66ff66; } .disclaimer { text-align: center; border-top: 1px solid #cccccc; margin-top: 40px; color: #666666; font-size: smaller; } </style> <sitemesh:write property='head'/> </head> <body> <h1 class='title'>SiteMesh example site: <sitemesh:write property='title'>Title goes here</sitemesh:write></h1> <sitemesh:write property='body'>Body goes here. Blah blah blah.</sitemesh:write> <div class='disclaimer'>Site disclaimer. This is an example.</div> <div class='navigation'> <b>Examples:</b> [<a href="./">Static example</a>] [<a href="demo.jsp">Dynamic example</a>] </div> </body> </html>
在這個例子中,裝飾頁面是一個靜態的.html
文件,可是若是你但願用動態頁面,那麼可使用諸如JSP,FreeMarker等技術。
<html> <head> <title>Hello World</title> </head> <body> <p>Well hello there, fine world.</p> <p>And so concludes this <b>SiteMesh</b> example.</p> <h2>How it works</h2> <ul> <li>This page (<code>/index.html</code>) contains vanilla HTML content.</li> <li>SiteMesh is configured (in <code>/WEB-INF/web.xml</code>) to apply a decorator to all paths (<code>/*</code>).</li> <li>The decorator (<code>/decorator.html</code>) contains the common look and feel that is applied to the site.</li> </ul> </body> </html>
像裝飾頁面同樣,被裝飾頁面能夠是靜態文件,也能夠是由 Servlet 引擎動態生成(例如JSP)。
SiteMesh 配置支持兩種方法 : XML 或 Java。
在工程的 /WEB-INF/sitemesh3.xml
中添加如下設置:
<sitemesh> <mapping path="/*" decorator="/decorator.html"/> </sitemesh>
要使用 Java 的配置方式,自定義的 SitMesh 過濾器須要繼承org.sitemesh.config.ConfigurableSiteMeshFilter
並重寫applyCustomConfiguration(SiteMeshFilterBuilder builder)
方法。 具體以下:
package com.wangxiaoan1234; import org.sitemesh.builder.SiteMeshFilterBuilder; import org.sitemesh.config.ConfigurableSiteMeshFilter; public class MySiteMeshFilter extends ConfigurableSiteMeshFilter { [@Override](https://my.oschina.net/u/1162528) protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) { builder.addDecoratorPath("/*", "/decorator.html"); } }
既然使用 Java 配置方式,就再也不須要sitemesh3.xml
文件,可是在web.xml
中要使用本身重寫的 SiteMesh 過濾器。 即web.xml的設置改爲以下所示:
<filter> <filter-name>sitemesh</filter-name> <filter-class>com.wangxiaoan1234.MySiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
本地查看內容頁面.html
效果以下:
經過SiteMesh3裝飾後訪問效果以下:
查看該效果頁面源代碼以下:
<html> <head> <title>SiteMesh example: Hello World (Dynamic)</title> <style type='text/css'> body { font-family: arial, sans-serif; background-color: #ffffcc; } h1, h2, h3, h4 { text-align: center; background-color: #ccffcc; border-top: 1px solid #66ff66; } .disclaimer { text-align: center; border-top: 1px solid #cccccc; margin-top: 40px; color: #666666; font-size: smaller; } </style> <style type='text/css'> .date { font-weight: bold; padding: 10px; font-size: larger; } </style> </head> <body> <h1 class='title'>SiteMesh example site: Hello World (Dynamic)</h1> <p>This page demonstrates that dynamic content can be decorated in the same way as static content.</p> <p>This is a simple JSP that shows the date and time on the server is now:</p> <div class='date'>Tue Aug 15 14:25:41 CST 2017</div> <p>Of course, with SiteMesh you are not limited to JSP. Because it's a Servlet Filter, both content and decorators can be generated by any technology in your ServletEngine, including: static files, JSP, Velocity, FreeMarker, JSF, MVC frameworks, JRuby.... you get the point.</p> <div class='disclaimer'>Site disclaimer. This is an example.</div> <div class='navigation'> <b>Examples:</b> [<a href="./">Static example</a>] [<a href="demo.jsp">Dynamic example</a>] </div> </body> </html>
sitemesh3.xml
文件以下:
<?xml version="1.0" encoding="UTF-8"?> <sitemesh> <!--默認狀況下,sitemesh 只對 HTTP 響應頭中 Content-Type 爲 text/html 的類型進行攔截和裝飾,咱們能夠添加更多的 mime 類型--> <mime-type>text/html</mime-type> <mime-type>application/vnd.wap.xhtml+xml</mime-type> <mime-type>application/xhtml+xml</mime-type> <!-- 默認裝飾器,當下面的路徑都不匹配時,啓用該裝飾器進行裝飾 --> <mapping decorator="/default-decorator.html"/> <!--不一樣的匹配路徑採用不一樣的裝飾頁面--> <mapping path="/admin/*" decorator="/another-decorator.html"/> <mapping path="/*.special.jsp" decorator="/special-decorator.html"/> <!--一個匹配路徑同時採用不一樣的裝飾頁面--> <mapping> <path>/articles/*</path> <decorator>/decorators/article.html</decorator> <decorator>/decorators/two-page-layout.html</decorator> <decorator>/decorators/common.html</decorator> </mapping> <!-- 知足該匹配路徑將不被裝飾 --> <mapping path="/login.htm" exclue="true" /> <!-- 自定義標籤 --> <content-processor> <tag-rule-bundle class="com.something.CssCompressingBundle" /> <tag-rule-bundle class="com.something.LinkRewritingBundle"/> </content-processor> </sitemesh>
對應 Java 配置以下(同理仍是在web.xml
中引用本身的 SiteMesh 過濾器):
package com.wangxiaoan1234; import org.sitemesh.builder.SiteMeshFilterBuilder; import org.sitemesh.config.ConfigurableSiteMeshFilter; public class MySiteMeshFilter extends ConfigurableSiteMeshFilter { [@Override](https://my.oschina.net/u/1162528) protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) { //默認裝飾器,當下面的路徑都不匹配時,啓用該裝飾器進行裝飾 builder.addDecoratorPath("/*", "/decorator.html") //添加更多的 mime 類型 .setMimeTypes("text / html","application / xhtml + xml","application / vnd.wap.xhtml + xml") //不一樣匹配路徑採用不一樣的裝飾頁面 .addDecoratorPath("/admin/*", "/another-decorator.html") .addDecoratorPath("/*.special.jsp", "/special-decorator.html") //一個匹配路徑同時採用不一樣的裝飾頁面 .addDecoratorPaths("/articles/*", "/decorators/article.html", "/decoratos/two-page-layout.html", "/decorators/common.html") //知足該匹配路徑將不被裝飾 .addExcludedPath("/javadoc/*") //添加自定義標籤 .addTagRuleBundle(new CssTagRuleBundle()); } }
其中自定義標籤類格式以下:
package com.wangxiaoan1234; import org.sitemesh.SiteMeshContext; import org.sitemesh.content.ContentProperty; import org.sitemesh.content.tagrules.TagRuleBundle; import org.sitemesh.content.tagrules.html.ExportTagToContentRule; import org.sitemesh.tagprocessor.State; /** * 自定義標籤 */ public class CssTagRuleBundle implements TagRuleBundle { [@Override](https://my.oschina.net/u/1162528) public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { defaultState.addRule("my-css", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("my-css"), false)); defaultState.addRule("my-footer", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("my-footer"), false)); } [@Override](https://my.oschina.net/u/1162528) public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { } }
在web.xml
中還能夠指定請求來源:
<filter> <filter-name>sitemesh</filter-name> <filter-class>com.wangxiaoan1234.MySiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> <dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher> </filter-mapping>
<dispatcher>
這個元素有四個可能的值:即 REQUEST、FORWARD、INCLUDE 和 ERROR,這個元素使得 filter 將會做用於直接從客戶端過來的request,經過 forward 過來的 request,經過 include 過來的 request 和經過<error-page>
過來的 request。若是沒有指定任何K元素,默認值是REQUEST。
<html> <head> <title>SiteMesh example: <sitemesh:write property='title'>Title goes here</sitemesh:write></title> <style> <sitemesh:write property='my-css'/> </style> <sitemesh:write property='head'/> </head> <body> <div> <p>pppppppppppppppppppppp</p> </div> <siteMesh:write property='my-footer'/> </body> </html>
<html> <head> <title>Hello World</title> <my-css> div p { color : red; } </my-css> </head> <body> <p>Well hello there, fine world.</p> <p>And so concludes this <b>SiteMesh</b> example.</p> <my-footer> <div style="text-align: center"> ©wangxiaoan1234.com </div> </my-footer> </body> </html>
效果頁面源碼:
<html> <head> <title>SiteMesh example: Hello World</title> <style> div p { color : red; } </style> </head> <body> <div> <p>pppppppppppppppppppppp</p> </div> <div style="text-align: center"> ©wangxiaoan1234.com </div> </body> </html>