gdufo

           

          sitemesh應(yīng)用Decorator模式

          sitemesh應(yīng)用Decorator模式,用filter截取request和response,把頁(yè)面組件head,content,banner結(jié)合為一個(gè)完整的視圖。通常我們都是用include標(biāo)簽在每個(gè)jsp頁(yè)面中來(lái)不斷的包含各種header, stylesheet, scripts and footer,現(xiàn)在,在sitemesh的幫助下,我們可以開(kāi)心的刪掉他們了。如下圖,你想輕松的達(dá)到復(fù)合視圖模式,那末看完本文吧。

          一、在WEB-INF/web.xml中copy以下filter的定義:

          <?xml version="1.0" encoding="GBK"?>
          <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
          version="2.4">

          <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>

          </web-app>

          二、copy所需sitemesh-2.3.jar到WEB-INF\lib下。(這里可以下載http://www.opensymphony.com/sitemesh/)

          三、
          建立WEB-INF/decorators.xml描述各裝飾器頁(yè)面。

          <decorators defaultdir="/decorators">
                                         <decorator name="main" page="main.jsp">
                                             <pattern>*</pattern>
                                         </decorator>
                                  </decorators>

            上面配置文件指定了裝飾器頁(yè)面所在的路徑,并指定了一個(gè)名為main的裝飾器,該裝飾器默認(rèn)裝飾web應(yīng)用根路徑下的所有頁(yè)面。

          四、
          建立裝飾器頁(yè)面 /decorators/main.jsp

        1. <%@ page contentType="text/html; charset=GBK"%>
          <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> <html>
                <head>
                    <title><decorator:title default="裝飾器頁(yè)面..." /></title>
                    <decorator:head />
                </head>
               <body>
                  sitemesh的例子<hr>
                  <decorator:body />
                  <hr>chen56@msn.com
              </body>
          </html>
           

          五、建立一個(gè)的被裝飾頁(yè)面 /index.jsp(內(nèi)容頁(yè)面)

        2. <%@ page contentType="text/html; charset=GBK"%>
                                  <html>
                                       <head>
                                         <title>Agent Test</title>
                                       </head>
                                       <body>
                                         <p>本頁(yè)只有一句,就是本句.</p>
                                       </body>
                                  </html>

            最后訪問(wèn)index.jsp,將生成如下頁(yè)面:

                而且,所有的頁(yè)面也會(huì)如同index.jsp一樣,被sitemesh的filter使用裝飾模式修改成如上圖般模樣,卻不用再使用include標(biāo)簽。



          1. 裝飾器     decorator概念
                為了建立可復(fù)用的web應(yīng)用程序,一個(gè)通用的方法是建立一個(gè)分層系統(tǒng),如同下面一個(gè)普通的web應(yīng)用:
            • 前端:JSP和Servlets,或jakarta的velocity 。。。
            • 控制層框架 Controller : (Struts/Webwork)
            • 業(yè)務(wù)邏輯 Business :主要業(yè)務(wù)邏輯
            • 持久化框架 :hibernate/jdo

                可糟糕的是前端的頁(yè)面邏輯很難被復(fù)用,當(dāng)你在每一個(gè)頁(yè)面中用數(shù)之不盡的include來(lái)復(fù)用公共的header, stylesheet, scripts,footer時(shí),一個(gè)問(wèn)題出現(xiàn)了-重復(fù)的代碼,每個(gè)頁(yè)面必須用copy來(lái)復(fù)用頁(yè)面結(jié)構(gòu),而當(dāng)你需要?jiǎng)?chuàng)意性的改變頁(yè)面結(jié)構(gòu)時(shí),災(zāi)難就愛(ài)上了你。

                 sitemesh通過(guò)filter截取request和response,并給原始的頁(yè)面加入一定的裝飾(可能為header,footer...),然后把結(jié)果返回給客戶端,并且被裝飾的原始頁(yè)面并不知道sitemesh的裝飾,這也就達(dá)到了脫耦的目的。

                 據(jù)說(shuō)即將新出臺(tái)的Portlet規(guī)范會(huì)幫助我們標(biāo)準(zhǔn)的實(shí)現(xiàn)比這些更多更c(diǎn)ool的想法,但可憐的我還不懂它到底是一個(gè)什末東東,有興趣的人可以研究
            jetspeed,或JSR (Java Specification Request) 168,但我想sitemesh如此簡(jiǎn)單,我們不妨先用著。

             

            讓我們看看怎樣配置環(huán)境
                除了要copy到WEB-INF/lib中的sitemesh.jar外,還有2個(gè)文件要建立到WEB-INF/:
            • sitemesh.xml (可選)  
            • decorators.xml

            sitemesh.xml 可以設(shè)置2種信息:

            Page Parsers :負(fù)責(zé)讀取stream的數(shù)據(jù)到一個(gè)Page對(duì)象中以被SiteMesh解析和操作。(不太常用,默認(rèn)即可)

            Decorator Mappers : 不同的裝飾器種類,我發(fā)現(xiàn)2種比較有用都列在下面。一種通用的mapper,可以指定裝飾器的配置文件名,另一種可打印的裝飾器,可以允許你當(dāng)用http://localhost/aaa/a.html?printable=true方式訪問(wèn)時(shí)給出原始頁(yè)面以供打印(免得把header,footer等的花哨的圖片也搭上)

            (但一般不用建立它,默認(rèn)設(shè)置足夠了:com/opensymphony/module/sitemesh/factory/sitemesh-default.xml):

            范例:

            <sitemesh>
                 <page-parsers>
                   <parser default="true" class="com.opensymphony.module.sitemesh.parser.DefaultPageParser" />
                   <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
                   <parser content-type="text/html;charset=ISO-8859-1" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
                 </page-parsers>

                 <decorator-mappers>
                   <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
                     <param name="config" value="/WEB-INF/decorators.xml" />
                   </mapper>
                     <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>
              
            </decorator-mappers>
            </sitemesh>

            decorators.xml :定義構(gòu)成復(fù)合視圖的所有頁(yè)面構(gòu)件的描述(主要結(jié)構(gòu)頁(yè)面,header,footer...),如下例:

            <decorators defaultdir="/decorators">
                 <decorator name="main" page="main.jsp">
                   <pattern>*</pattern>
                 </decorator>
                 <decorator name="printable" page="printable.jsp" role="customer" webapp="aaa" />
            </decorators>
            • defaultdir: 包含裝飾器頁(yè)面的目錄
            • page : 頁(yè)面文件名
            • name : 別名
            • role : 角色,用于安全
            • webapp : 可以另外指定此文件存放目錄
            • Patterns : 匹配的路徑,可以用*,那些被訪問(wèn)的頁(yè)面需要被裝飾。

             

            最重要的是寫出裝飾器本身(也就是那些要復(fù)用頁(yè)面,和結(jié)構(gòu)頁(yè)面)。
                其實(shí),重要的工作就是制作裝飾器頁(yè)面本身(也就是包含結(jié)構(gòu)和規(guī)則的頁(yè)面),然后把他們描述到decorators.xml中。

                讓我們來(lái)先看一看最簡(jiǎn)單的用法:其實(shí)最常用也最簡(jiǎn)單的用法就是我們的hello例子,面對(duì)如此眾多的技術(shù),我想只要達(dá)到功能點(diǎn)到為止即可,沒(méi)必要去研究太深(除非您有更深的需求)。

            <%@ page contentType="text/html; charset=GBK"%>
                                        <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
                                        <html>
                                             <head>
                                               <title><decorator:title default="裝飾器頁(yè)面..." /></title>
                                               <decorator:head />
                                             </head>
                                             <body>
                                               sitemesh的例子<hr>
                                               <decorator:body />
                                               <hr>chen56@msn.com
                                             </body>
                                        </html>
                                        

            我們?cè)谘b飾器頁(yè)面只用了2個(gè)標(biāo)簽:

            <decorator:title default="裝飾器頁(yè)面..." />       : 把請(qǐng)求的原始頁(yè)面的title內(nèi)容插入到<title></title>中間。

            <decorator:body /> : 把請(qǐng)求的原始頁(yè)面的body內(nèi)的全部?jī)?nèi)容插入到相應(yīng)位置。

            然后我們?cè)赿ecorator.xml中加入以下描述即可:

            <decorator name="main" page="main.jsp">
                   <pattern>*</pattern>
            </decorator>

            這樣,請(qǐng)求的所有頁(yè)面都會(huì)被重新處理,并按照main.jsp的格式重新展現(xiàn)在你面前。

             

            讓我們看看更多的用法。(抄襲sitemesh文檔)
            以下列著全部標(biāo)簽:
            Decorator Tags Page Tags
            被用于建立裝飾器頁(yè)面. 被用于從原始內(nèi)容頁(yè)面訪問(wèn)裝飾器.
            <decorator:head />
            <decorator:body />
            <decorator:title />
            <decorator:getProperty />
            <decorator:usePage />
            <page:applyDecorator />
            <page:param
             

            <decorator:head />

            插入原始頁(yè)面(被包裝頁(yè)面)的head標(biāo)簽中的內(nèi)容(不包括head標(biāo)簽本身)。

            <decorator:body />

            插入原始頁(yè)面(被包裝頁(yè)面)的body標(biāo)簽中的內(nèi)容。

            <decorator:title [ default="..." ] />

            插入原始頁(yè)面(被包裝頁(yè)面)的title標(biāo)簽中的內(nèi)容,還可以添加一個(gè)缺省值。

            例:

            /decorator/main.jsp中 (裝飾器頁(yè)面): <title><decorator:title default="卻省title-hello"     /> - 附加標(biāo)題</title>

            /aaa.jsp中 (原始頁(yè)面):<title>aaa頁(yè)面</title>

            訪問(wèn)/aaa.jsp的結(jié)果:<title>aaa頁(yè)面 - 附加標(biāo)題</title>

            <decorator:getProperty property="..." [ default="..." ] [ writeEntireProperty="..." ]/>

            在標(biāo)簽處插入原始頁(yè)面(被包裝頁(yè)面)的原有的標(biāo)簽的屬性中的內(nèi)容,還可以添加一個(gè)缺省值。

            sitemesh文檔中的例子很好理解:
            The decorator: <body bgcolor="white"<decorator:getProperty property="body.onload" writeEntireProperty="true" />>
            The undecorated page: <body onload="document.someform.somefield.focus();">
            The decorated page: <body bgcolor="white" onload="document.someform.somefield.focus();">

            注意,writeEntireProperty="true"會(huì)在插入內(nèi)容前加入一個(gè)空格。

            <decorator:usePage id="..." />
            象jsp頁(yè)面中的<jsp:useBean>標(biāo)簽一樣,可以使用被包裝為一個(gè)Page對(duì)象的頁(yè)面。 (懶的用)

            例:可用<decorator:usePage id="page" /><%=page.getTitle()%>達(dá)到<decorator:title/>的訪問(wèn)結(jié)果。

            <page:applyDecorator name="..." [ page="..." title="..." ] >
            <page:param name="..."> ... </page:param>
            <page:param name="..."> ... </page:param>
            </page:applyDecorator>

            應(yīng)用包裝器到指定的頁(yè)面上,一般用于被包裝頁(yè)面中主動(dòng)應(yīng)用包裝器。這個(gè)標(biāo)簽有點(diǎn)不好理解,我們來(lái)看一個(gè)例子:

            包裝器頁(yè)面 /decorators/panel.jsp:<p><decorator:title /></p>     ... <p><decorator:body /></p>
                 并且在decorators.xml中有<decorator name="panel" page="panel.jsp"/>

            一個(gè)公共頁(yè)面,即將被panel包裝:/public/date.jsp:  
                 ... <%=new java.util.Date()%>     ...<decorator:getProperty property="myEmail" />

            被包裝頁(yè)面 /page.jsp :
                 <title>page的應(yīng)用</title>
                 .....  

                 <page:applyDecorator name="panel" page="/_public/date.jsp" >
                   <page:param name="myEmail"> chen_p@neusoft.com </page:param>
                 </page:applyDecorator>

            最后會(huì)是什末結(jié)果呢?除了/page.jsp會(huì)被默認(rèn)的包裝頁(yè)面包裝上header,footer外,page.jsp頁(yè)面中還內(nèi)嵌了date.jsp頁(yè)面,并且此date.jsp頁(yè)面還會(huì)被panel.jsp包裝為一個(gè)title加body的有2段的頁(yè)面,第1段是date.jsp的title,第2段是date.jsp的body內(nèi)容。

            另外,page:applyDecorator中包含的page:param標(biāo)簽所聲明的屬性值還可以在包裝頁(yè)面中用decorator:getProperty標(biāo)簽訪問(wèn)到。


            可打印的界面裝飾
                 前面說(shuō)過(guò)有1種可打印的裝飾器,可以允許你當(dāng)用http://localhost/aaa/a.html?printable=true方式訪問(wèn)時(shí),應(yīng)用其他的裝飾器(自己指定),給出原始頁(yè)面以供打印(免得把header,footer等的花哨的圖片也搭上)。

            讓我們來(lái)看一看怎樣實(shí)現(xiàn)他:

            1.首先在WEB-INFO/sitemesh.xml中設(shè)置:
                 <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>
            這樣就可以通過(guò)?printable=true來(lái)使用名為printable的裝飾器,而不是用原來(lái)的裝飾器。

            2.在WEB-INFO/decorators.xml中定義相應(yīng)的printable裝飾器
                 <decorator name="printable" page="printable.jsp"/>

            3.最后編寫printable裝飾器/decorators/printable.jsp

            <%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
            <html>
            <head>
                 <title><decorator:title /></title>
                 <decorator:head />
            </head>
            <body>

                 <h1><decorator:title /></h1>
                 <p align="right"><i>(printable version)</i></p>

                 <decorator:body />

            </body>
            </html>

            這樣就可以讓一個(gè)原始頁(yè)面通過(guò)?printable=true開(kāi)關(guān)來(lái)切換不同的裝飾器頁(yè)面。

             

            中文問(wèn)題
            由于sitemesh內(nèi)部所使用的缺省字符集為iso-8859-1,直接使用會(huì)產(chǎn)生亂碼,我們可以通過(guò)以下方法糾正之:
            • 方法1:可以在您所用的application server的配置文件中找一找,有沒(méi)有設(shè)置encoding或charset的項(xiàng)目,然后設(shè)成gbk或gb2312即可
            • 方法2:這也是我們一直使用的方法。
              1.在每一個(gè)jsp頁(yè)里設(shè)置: <%@ page contentType="text/html; charset=gbk"%> 來(lái)告訴server你所要求的字符集。
              2.在每個(gè)jsp頁(yè)的head中定義:<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=gbk"> 來(lái)告訴瀏覽器你所用的字符集。
            總結(jié):使用sitemesh最通常的途徑:

            1.配置好環(huán)境,

            2.在WEB-INFO/decroators.xml中描述你將建立的包裝器。

            3.開(kāi)發(fā)在decroators.xml中描述的包裝器,最好存放在/_decorators目錄下

            4.ok ,可以看看辛勤的成果了 :)

            posted on 2008-08-04 17:21 gdufo 閱讀(3829) 評(píng)論(0)  編輯  收藏 所屬分類: Appfuse

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(6)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            收藏夾

            Hibernate

            友情鏈接

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            主站蜘蛛池模板: 湘潭市| 庄河市| 红原县| 宜阳县| 始兴县| 九江市| 朔州市| 松江区| 定西市| 洛宁县| 安龙县| 巢湖市| 东城区| 田东县| 西藏| 濉溪县| 仁化县| 兴宁市| 陆河县| 湖北省| 屯昌县| 武冈市| 壤塘县| 义马市| 靖宇县| 丰镇市| 平山县| 香河县| 修文县| 团风县| 额济纳旗| 留坝县| 北碚区| 本溪市| 新宾| 蕉岭县| 册亨县| 河曲县| 来宾市| 长顺县| 墨玉县|