使用SiteMesh 简化网页布局
1. 基本原理
SiteMesh 是以 Servlet 2.3API 为基础。它包含一个引擎,用来解析输出的网页或者网页片段,决定是否需要应用装饰器以及合并合适的装饰器。
SiteMesh 与应用内容无关,适用的内容格式包括 Html 、 JSP 、 Servlet 、 XSL ,甚至 CGI 。
2. 实现流程
1)当为 Servlet 容器指定一个Http请求时,SiteMesh 截取请求,使用一个 Servlet Filter,然后捕捉 Html 结果。
2)然后这个 Html 被解析,并且任何相关的内容都被提取到一个 Page 对象中。
3)询问 DecoratorMapper 来确定那一个装饰器需要被应用。
4)Servlet 向包含装饰器的 JSP 发送请求。
5)装饰器生成带有从 page 对象中获得的内容的 Html 布局。
大致流程如下图:
http://www.blogjava.net/images/blogjava_net/faith/13332/o_Sitemesh%e6%b5%81%e7%a8%8b.jpg
Sitemesh 这样的好处是,所有具体业务页面的开发者无需考虑该页面将处在最终输出页面的那个位置。无需 include 一大堆页面,以后如果系统整体改版,那么只需要改写装饰器页面及重新配置装饰规则即可完成,方便快捷,可维护性极好。
3. 在项目中使用 Sitemesh
1) 将 sitemesh_[version].jar 包加到 WEB-INF/lib 下
2) 在 web.xml 中增加
< filter >
< filter-name > sitemesh </ filter-name >
< filter-class > com.opensymphony.module.sitemesh.filter.PageFilter </ filter-class >
</ filter >
< filter-mapping >
< filter-name > sitemesh </ filter-name >
< url-pattern > /* </ url-pattern >
</ filter-mapping >
表示对系统中所有 url 请求均使用 sitemesh Filter 进行拦截。
3) 在 WEB-INF 下配置 sitemesh.xml 和 decorator.xml 配置文件。
Sitemesh.xml
< sitemesh >
< property name ="decorators-file" value ="/WEB-INF/decorators.xml" />
< excludes file ="${decorators-file}" />
< page-parsers >
< parser default ="true" class ="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
< parser content-type ="text/html"
class ="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
< parser content-type ="text/html;charset=ISO-8859-1"
class ="com.opensymphony.module.sitemesh.parser.HTMLPageParser" />
</ page-parsers >
< decorator-mappers >
<!-- for print -->
< mapper class ="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper" >
< param name ="decorator" value ="printable" />
< param name ="parameter.name" value ="printable" />
< param name ="parameter.value" value ="true" />
</ mapper >
< mapper class ="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper" >
< param name ="config" value ="${decorators-file}" />
</ mapper >
</ decorator-mappers >
</ sitemesh >
Decorator.xml
< decorators defaultdir ="/decorators" >
< excludes >
< pattern > /demos/* </ pattern >
< pattern > /resources/* </ pattern >
< pattern > /test* </ pattern >
< pattern > /FCKeditor/* </ pattern >
</ excludes >
<!-- decorator for print(has parameter: printable=true) -->
< decorator name ="printable" page ="decPrintable.jsp" />
< decorator name ="login" page ="decLogin.jsp" >
< pattern > *login* </ pattern > <! —url 映射模式 -- >
</ decorator >
< decorator name ="default" page ="decDefault.jsp" >
< pattern > /* </ pattern > <! — 缺省的装饰器 -- >
</ decorator >
</ decorators >
在 sitemesh.xml 中配置了两个 DecoratorMapper : PrintableDecoratorMapper 和 ConfigDecoratorMapper 。
PrintableDecoratorMapper 是供打印专用,在 url 后加上 printable=true 即会使用 decorator.xml 中指定的 printable 装饰器来对页面进行装饰,一般来说打印页面是只需要打印本页面的内容,其余的如头、脚、导航栏、左右菜单等是不需要打印的,通过装饰器可以轻松实现打印页面的过滤。
4) 创建一个装饰器 JSP 页面,建议所有装饰器页面放到 decorators 目录,并且以 dec[ 功能 ].jsp 作为命名方式,如 decPrintable.jsp 、 decDefault.jsp 。
下面是一个装饰器的代码:
<! DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN "
" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " >
<%-- Include common set of tag library declarations for each layout --%>
<% @ include file = " /common/taglibs.jsp " %>
< html xmlns = " http://www.w3.org/1999/xhtml " xml:lang = " en " >
< head >
< decorator:head />
</ head >
< body
< decorator:getProperty property = " body.id " writeEntireProperty = " true " />
< decorator:getProperty property = " body.onload " writeEntireProperty = " true " />
< decorator:getProperty property = " body.onunload " writeEntireProperty = " true " />
>
<% @ include file = " /common/header.jsp " %>
< h1 >< decorator:getProperty property = " page.heading " /></ h1 >
<% @ include file = " /common/messages.jsp " %>
< decorator:body />
< jsp:include page = " /common/footer.jsp " />
</ body >
</ html >
注意其 <decorator:…> 标签,这些标签将被装饰的 page 页面的相应内容作为属性传入。 Page 页面的相关内容将放在 decorator 标签所指定的位置。
Title :标题
Head :头部,一般是公共的 js 、 css 及 meta 。
Body :被装饰的 page 的主体内容。
5) Sitemesh 通过在 sitemesh.xml 中配置 DecoratorMapper 配置映射器,通过在 decorator.xml 中配置装饰器文件及其匹配方式。当有页面需要输出到客户端时,将根据这些配置选择相应的装饰器来进行装饰,将装饰结果返回给客户界面。