<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-67  評(píng)論-522  文章-0  trackbacks-0
        通過(guò)上一篇文章(dom4j實(shí)戰(zhàn)(一)——使用dom4jXML中讀取數(shù)據(jù)源配置),使我們對(duì)dom4j有了一些初步的認(rèn)識(shí)和了解,也掌握了基本的操作方法,本文將承接前篇,借鑒Openfire項(xiàng)目中菜單設(shè)計(jì)的優(yōu)點(diǎn),結(jié)合我們自己的需求,通過(guò)一個(gè)小實(shí)例,來(lái)說(shuō)明一下如何使用dom4j來(lái)實(shí)現(xiàn)這個(gè)功能。
        可以在http://www.igniterealtime.org/downloads/index.jsp 這里下載到Openfire的發(fā)布版和源碼版,Openfire的介紹在這里不作描述,網(wǎng)上相關(guān)的資料有很多,有興趣的朋友可以下載源碼研究一下,其實(shí)不了解Openfire也沒(méi)關(guān)系,因?yàn)槲覀冎皇墙梃b其中的一些思想,等做完了實(shí)例,就會(huì)有一個(gè)比較直觀的認(rèn)識(shí)。
        大象建議先在最后面下載源碼和必要的JAR包,讓程序運(yùn)行起來(lái)看下效果,再看下面的詳細(xì)說(shuō)明。
        開(kāi)發(fā)環(huán)境:Eclipse 3.2.1  MyEclipse 5.10GA  Tomcat 6.10  
                 dom4j-1.6.1.jar  jaxen-1.1-beta-7.jar  sitemesh-2.2.1.jar

        1、創(chuàng)建tag-console.xml
           在src目錄下建一個(gè)tag-console.xml文件,這個(gè)配置文件中寫(xiě)的是菜單信息,內(nèi)容如下:
    <?xml version="1.0" encoding="GBK"?>
    <bookstore>
        
    <global>
            
    <appname>菜單導(dǎo)航demo</appname>
            
    <version>ver 1.0</version>
            
    <creator>菠蘿大象</creator>
        
    </global>
        
    <catalog id="catalog-program" name="編程開(kāi)發(fā)" url="index.jsp" description="編程開(kāi)發(fā)">    
            
    <item id="item-program-java" name="Java開(kāi)發(fā)" url="index.jsp" description="Java開(kāi)發(fā)">
                
    <book id="695043" name="Struts2 深入詳解" url="index.jsp" description="Struts2 深入詳解"/>
                
    <book id="691254" name="Ant整合開(kāi)發(fā)" url="book_ant.jsp" description="Ant整合開(kāi)發(fā)"/>
                
    <book id="693668" name="Java編程思想" url="book_java.jsp" description="Java編程思想"/>
            
    </item>
            
    <item id="item-program-database" name="數(shù)據(jù)庫(kù)開(kāi)發(fā)" url="book_oracle9.jsp" description="數(shù)據(jù)庫(kù)開(kāi)發(fā)">
                
    <book id="691245" name="Oracle 9i數(shù)據(jù)庫(kù)寶典" url="book_oracle9.jsp" description="Oracle 9i數(shù)據(jù)庫(kù)寶典"/>
                
    <book id="693254" name="SQL Server 2005應(yīng)用開(kāi)發(fā)" url="book_sqlserver.jsp" description="SQL Server 2005應(yīng)用開(kāi)發(fā)"/>
                
    <book id="690215" name="Oracle 10g高級(jí)開(kāi)發(fā)" url="book_oracle10.jsp" description="Oracle 10g高級(jí)開(kāi)發(fā)"/>
            
    </item>
        
    </catalog>
        
    <catalog id="catalog-system" name="系統(tǒng)相關(guān)" url="book_vista.jsp" description="系統(tǒng)相關(guān)">
            
    <item id="item-system-windows" name="Windows系統(tǒng)" url="book_vista.jsp" description="Windows系統(tǒng)">
                
    <book id="691258" name="Windows Vista入門(mén)" url="book_vista.jsp" description="Windows Vista入門(mén)"/>
                
    <book id="695489" name="Windows注冊(cè)表實(shí)戰(zhàn)" url="book_windows.jsp" description="Windows注冊(cè)表實(shí)戰(zhàn)"/>
            
    </item>
            
    <item id="item-system-linux" name="Linux系統(tǒng)" url="book_linux9.jsp" description="Linux系統(tǒng)">
                
    <book id="696598" name="Linux 9.0詳解" url="book_linux9.jsp" description="Linux 9.0詳解"/>
                
    <book id="694585" name="Linux寶典" url="book_linux.jsp" description="Linux寶典"/>
            
    </item>
        
    </catalog>
    </bookstore>
           上面XML里面的東西我是隨便寫(xiě)的,大家千萬(wàn)不要較真,我用圖書(shū)來(lái)做菜單一是方便大家理解,另一個(gè)是簡(jiǎn)化程序,其實(shí)Openfire的服務(wù)器端是一個(gè)后臺(tái)管理系統(tǒng),它是基于XMPP(可擴(kuò)展消息處理現(xiàn)場(chǎng)協(xié)議)開(kāi)發(fā)的,XMPP貫穿整個(gè)系統(tǒng)設(shè)計(jì),如果你想用它的控制臺(tái)框架,但又不想用XMPP,請(qǐng)先從網(wǎng)頁(yè)入口開(kāi)始,結(jié)合頁(yè)面仔細(xì)分析代碼,把需要的部分抽取出來(lái)就行了,其它的不用去管。大象沒(méi)有研究過(guò)XMPP,只是抽取了控制臺(tái)框架,對(duì)Openfire的源代碼也沒(méi)能深入的研究,最主要還是E文太爛了。^_^
           Openfire沒(méi)有采用現(xiàn)在很流行的技術(shù)架構(gòu)(SSH),只使用JSP+JavaBean,但是它有自己的系統(tǒng)設(shè)計(jì),就連日志都是自己做的,沒(méi)有使用我們熟悉的log4j,真的是太佩服鳥(niǎo)~~~~
        2、創(chuàng)建ResourceManage.java
           在util包下創(chuàng)建ResourceManage類(lèi),這個(gè)類(lèi)主要是用來(lái)讀取tag-console.xml文件,并取得文件中的基本信息,以及查找元素等操作。
           我們先在Constant接口中,增加一個(gè)字符串常量:String TAG_CONFIG = "tag-console.xml"
           ResourceManage前面加載資源的部分和上一篇,后來(lái)修改過(guò)的DataBaseConnect類(lèi)一樣,只需把Constant.DB_CONFIG換成Constant.TAG_CONFIG就行了。接下來(lái),在類(lèi)中加入幾個(gè)讀取XML中基本信息的方法:
        <global>
            
    <appname>菜單導(dǎo)航demo</appname>
            
    <version>ver 1.0</version>
            
    <creator>菠蘿大象</creator>
        
    </global>
           這里只舉出取得appname元素值的方法,其它的幾個(gè)都很相似,請(qǐng)查看源代碼。
        /**
         * 得到應(yīng)用程序名稱(chēng)
         
    */
        
    public static String getAppName(){
            Element appName 
    = (Element) coreModel.selectSingleNode("//bookstore/global/appname");
            
    if(appName!=null){
                
    return appName.getText();
            }
    else{
                
    return null;
            }
        }
           根據(jù)id屬性值查找對(duì)應(yīng)的元素:
        /**
         * 在整個(gè)文檔節(jié)點(diǎn)中查找id屬性值為傳入id的元素對(duì)象
         * 
    @param id 待查找的id屬性值
         * 
    @return 返回找到的元素對(duì)象
         
    */
        
    public static Element getSingleElementById(String id){
            
    return (Element)coreModel.selectSingleNode("//*[@id='"+id+"']");
        }
           這里用到了XPATH語(yǔ)法,根據(jù)傳入的id值,在整個(gè)文檔中查找id屬性值與此一致的元素對(duì)象。用下面的代碼舉例說(shuō)明:
        <book id="695043" name="Struts2 深入詳解" url="index.jsp" description="Struts2 深入詳解"/>
           當(dāng)傳入的id屬性值為"695043"時(shí),那么我們就會(huì)得到對(duì)應(yīng)這個(gè)id值的book元素對(duì)象,id屬性值在整個(gè)配置文件中就是一個(gè)key關(guān)鍵字,起到定位的作用。
           根據(jù)id屬性值查找上下文中對(duì)應(yīng)的catalog元素
        /**
         * 根據(jù)傳入的id查找上下文中對(duì)應(yīng)的catalog元素
         * 
    @param id 待查找的id屬性值
         * 
    @return 返回id值所在的catalog元素對(duì)象
         
    */
        
    public static Element getElementByID(String id) {
            
    return (Element) coreModel.selectSingleNode("http://*[@id='" + id
                    + "']/ancestor::catalog");

        }
           ancestorXPATH語(yǔ)法中軸的概念,我引用網(wǎng)上官方文檔中的說(shuō)明:“ancestor(axis)包含上下節(jié)點(diǎn)的祖先節(jié)點(diǎn),該祖先節(jié)點(diǎn)由其上下文節(jié)點(diǎn)的父節(jié)點(diǎn)以及父節(jié)點(diǎn)的父節(jié)點(diǎn)等等諸如此類(lèi)的節(jié)點(diǎn)構(gòu)成,所ancestor軸總是包含有根節(jié)點(diǎn),除非上下文節(jié)點(diǎn)就是根節(jié)點(diǎn)本身。這句話的意思其實(shí)就是向上查找節(jié)點(diǎn),直到找到根節(jié)點(diǎn)為止。對(duì)于ancestor::catalog來(lái)說(shuō),就是向上查找直到catalog節(jié)點(diǎn)為止。所以getElementByID這個(gè)方法是根據(jù)傳入的id屬性值在上下文中查找節(jié)點(diǎn),直到找到這個(gè)id值所在的上下文catalog節(jié)點(diǎn)為止。當(dāng)傳入的id屬性值為"695043"時(shí),我們會(huì)得到id="catalog-program"這個(gè)catalog節(jié)點(diǎn)元素,而不會(huì)得到id="catalog-system"這個(gè)catalog節(jié)點(diǎn)元素。這樣說(shuō)大家大概能明白是什么意思了吧?
           可以去這個(gè)網(wǎng)站看下XPATH教程:http://www.zvon.org/xxl/XPathTutorial/General_chi/examples.html
        3、自定義標(biāo)簽  
           采用自定義標(biāo)簽的方式來(lái)生成菜單,借助ResourceManage類(lèi)取出XML文件中的信息,將這些內(nèi)容裝載到標(biāo)簽體中,然后在JSP頁(yè)面中呈現(xiàn)出來(lái)。
           1主菜單標(biāo)簽
              主菜單有兩個(gè),catalog元素這一層表示主菜單。標(biāo)簽的實(shí)現(xiàn)類(lèi)如下:
              MainTag.java
              建com.demo.tag包,在tag包下創(chuàng)建MainTag類(lèi),繼承javax.servlet.jsp.tagext.BodyTagSupport類(lèi),主要的部分代碼如下,完整代碼請(qǐng)下載源碼包查看。
              這些屬性與demo.tld中的屬性對(duì)應(yīng),每個(gè)屬性都有settergetter方法。
        private String css; //菜單的CSS樣式
        private String currentcss; //當(dāng)前選中菜單的CSS樣式

             doStartTag()方法是遇到標(biāo)簽開(kāi)始時(shí)調(diào)用的方法,EVAL_BODY_BUFFERED表示創(chuàng)建一個(gè)緩沖流,將標(biāo)簽體的內(nèi)容保存到BodyContent對(duì)象中,可以對(duì)其內(nèi)容進(jìn)行修改。BodyContent繼承了javax.servlet.jsp.JspWriter類(lèi),BodyContent對(duì)象的內(nèi)容不自動(dòng)寫(xiě)入servlet的輸出流,而是放在一個(gè)字符流緩存中。當(dāng)標(biāo)簽體完成后其對(duì)象仍可在doEndTag()方法中應(yīng)用,由getString()getReader()方法操作。并在必要時(shí)修改及寫(xiě)入恢復(fù)的JspWriter輸出流。EVAL_BODY_INCLUDE表示將顯示標(biāo)簽間的文字。另一個(gè)返回值是SKIP_BODY,它表示不顯示標(biāo)簽間的文字。

        public int doStartTag() throws JspException {
            
    return EVAL_BODY_BUFFERED; //創(chuàng)建保存到BodyContent對(duì)象中的緩沖流
        }
              doEndTag()方法是遇到標(biāo)簽結(jié)束時(shí)調(diào)用的方法,EVAL_PAGE表示處理完標(biāo)簽后繼續(xù)執(zhí)行標(biāo)簽之后的JSP頁(yè)面。另一個(gè)返回值SKIP_PAGE表示不處理標(biāo)簽之后的JSP網(wǎng)頁(yè)。
        public int doEndTag() throws JspException {
            
    //代碼主體省略,請(qǐng)查看源碼
            return EVAL_PAGE; //處理完標(biāo)簽后繼續(xù)執(zhí)行標(biāo)簽之后的JSP頁(yè)面
        }
              doEndTag()方法中部分比較重要的代碼說(shuō)明:
              使用pageContext對(duì)象在JSP頁(yè)面上下文取得請(qǐng)求,不過(guò)請(qǐng)注意pageContext,它定義在javax.servlet.jsp.tagext.TagSupport中,而不是在BodyTagSupport中,因?yàn)?span lang="EN-US">BodyTagSupport繼承了
    TagSupport
        //使用pageContext對(duì)象在JSP頁(yè)面上下文取得請(qǐng)求
        HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
              取得請(qǐng)求中的pageID值,這個(gè)pageID值在每個(gè)jsp頁(yè)面中放在meta標(biāo)簽中,通過(guò)sitemesh裝飾器取出放到request中。
        /*
         * 從請(qǐng)求中得到pageID值,即每個(gè)JSP里meta的content值
         * 與XML文件中book元素的id屬性值一致
         
    */
        String pageID 
    = (String)request.getAttribute("pageID");
              將所有的catalog元素取出放到List集合中,這里是只取得catalog這一層級(jí)的元素,實(shí)質(zhì)就是catalogs中只有兩個(gè)對(duì)象,一個(gè)是id="catalog-program"另一個(gè)是id="catalog-system",使用dom4j我們會(huì)發(fā)現(xiàn)處理元素非常容易,API相當(dāng)?shù)呢S富,想寫(xiě)成什么樣完全憑你自己的想法。
        //將所有的catalog元素取出放到List集合
        List catalogs = ResourceManage.getCoreModel().selectNodes("//catalog");
              看看前面介紹的getElementByID這個(gè)方法,這個(gè)currentCatalog所表示就是pageID所在的catalog元素。上面的代碼是為了和下面的代碼結(jié)合來(lái)判斷當(dāng)前的菜單是否為選中,加入CSS樣式顯示。
        //pageID所在的catalog元素,主要用來(lái)判斷當(dāng)前菜單是否被選中
        Element currentCatalog = (Element)ResourceManage.getElementByID(pageID);
              從BodyContent中將標(biāo)簽體緩存流讀取出來(lái),標(biāo)簽在WebRoot/decorators/main.jsp<a href="[url]" title="[description]" onmouseover="self.status='[description]';return true;" onmouseout="self.status='';return true;">[name]</a>
        String value = getBodyContent().getString(); //得到標(biāo)簽體
              Catalogs里面是兩個(gè)catalog對(duì)象,循環(huán)遍歷取出,將標(biāo)簽體中的[id][url][name][description]替換為XML文件中的屬性值,這樣主菜單標(biāo)簽就生成了。
        for (int i=0; i<catalogs.size(); i++) {
            Element catalog 
    = (Element)catalogs.get(i); //catalog元素對(duì)象
            String value = getBodyContent().getString(); //得到標(biāo)簽體
            /*
             * 將標(biāo)簽體中的[id]、[url]、[name]、[description]
             * 替換為XML文件中的屬性值
             * attributeValue方法是取屬性值
             
    */
            
    if (value != null) {
                value 
    = StringUtils.replace(value, "[url]", request
                           .getContextPath()
                           
    + "/" + catalog.attributeValue("url"));            
                value 
    = StringUtils.replace(value, "[name]",catalog.attributeValue("name"));
                value 
    = StringUtils.replace(value, "[description]",catalog.
                        attributeValue(
    "description"));
            }
            String css 
    = getCss();
            
    //對(duì)當(dāng)前選中菜單添加CSS樣式
            if (catalog.equals(currentCatalog)) {
                css 
    = getCurrentcss();
            }
            buf.append(
    "<li class=\"").append(css).append("\">");
            
    if (i > 0) {
                buf.append(
    " | ");
            }
            buf.append(value).append(
    "</li>");
        }
           2、導(dǎo)航菜單及側(cè)邊欄菜單標(biāo)簽
               導(dǎo)航菜單每個(gè)catalog下都有兩個(gè),而側(cè)邊欄菜單則在item下定義,這兩個(gè)標(biāo)簽類(lèi)與主菜單的標(biāo)簽類(lèi)沒(méi)有太大的區(qū)別,主要就是生成標(biāo)簽體,匹配CSS樣式,因此,代碼中相同的部分我不再細(xì)述,只說(shuō)一下不同的地方。
               在tag包下創(chuàng)建NavTag類(lèi)和SideTag類(lèi),標(biāo)簽屬性與MainTag一樣,只是SideTag多了一個(gè)headercss屬性,這是在頁(yè)面顯示時(shí),加在邊欄上當(dāng)前選中項(xiàng)左側(cè)小箭頭的CSS樣式,不清楚的話,請(qǐng)運(yùn)行程序后觀察。
               NavTag.java
               根據(jù)pageID找到此元素對(duì)象:
        //根據(jù)pageID找到此元素對(duì)象,即book元素對(duì)象
        Element current = ResourceManage.getSingleElementById(pageID);
               如果current不為空,取得父節(jié)點(diǎn),其為item元素。根據(jù)pageID值,如果為695043,則subnavid="item-program-java"item元素,如果為691245,則subnavid="item-program-database"item元素。這個(gè)subnav的作用也是用來(lái)判斷當(dāng)前的菜單是否為選中,加入CSS樣式顯示。
        Element subnav = null;
        
    if (current != null) {
            subnav 
    = current.getParent(); //取得父節(jié)點(diǎn),即item元素
        }
               SideTag.java
               在SideTag中也有上面的代碼,但是subnav不再與CSS有關(guān),而是取得它的所有子元素集合,即book元素集合,然后遍歷所有book節(jié)點(diǎn),取出屬性值放入標(biāo)簽體中再輸出到頁(yè)面。
               我注釋寫(xiě)得很詳細(xì),請(qǐng)查看代碼了解細(xì)節(jié)。
        4、創(chuàng)建StringUtils.java
           在util包下創(chuàng)建StringUtils類(lèi),這個(gè)類(lèi)作為字符串處理類(lèi)。添加public static String replace(String string, String oldString, String newString)方法,它的作用就是將標(biāo)簽體中的[id][url][name][description]替換為XML文件中的屬性值。如果被替換的字符串在標(biāo)簽體中有多個(gè),也能將它全部替換。
        /**
         * 將string中的oldString全部替換為newString
         * 
    @param string 原始字符串
         * 
    @param oldString 被替換的字符串
         * 
    @param newString 要替換的字符串
         * 
    @return 返回替換完后的新string
         
    */
        
    public static String replace(String string, String oldString, String newString) {
            
    if (string == null) {
                
    return null;
            }
            
    int i = 0;
            
    //判斷string中是否有被替換的字符串,i其實(shí)是索引值
            if ((i = string.indexOf(oldString, i)) >= 0) {
                
    char[] string2 = string.toCharArray(); //字符串放入數(shù)組
                char[] newString2 = newString.toCharArray(); //要替換的字符串
                int oLength = oldString.length(); //被替換的字符串的長(zhǎng)度
                StringBuilder buf = new StringBuilder(string2.length);
                
    /*
                 * 從索引0開(kāi)始,按i值的長(zhǎng)度在string2數(shù)組中截取字符
                 * 將截取的字符放到buf中,接著再加入要替換的內(nèi)容
                 
    */
                buf.append(string2, 
    0, i).append(newString2);
                i 
    += oLength; //得到被替換字符結(jié)束位置的索引
                int j = i;
                
    /*
                 * 查找string中,是否仍然含有被替換字符串
                 * 使用循環(huán),將所有oldString換成newString
                 
    */
                
    while ((i = string.indexOf(oldString, i)) > 0) {
                    buf.append(string2, j, i 
    - j).append(newString2);
                    i 
    += oLength; //得到被替換字符結(jié)束位置的索引
                    j = i;
                }
                
    /*
                 * 截取string2數(shù)組中從索引j開(kāi)始
                 * string2.length-j的長(zhǎng)度加到buf中
                 * 其實(shí)就是在buf中補(bǔ)全標(biāo)簽體
                 
    */
                buf.append(string2, j, string2.length 
    - j);
                
    return buf.toString();
            }
            
    return string;
        }
           如果看注釋就能懂那最好不過(guò),如果不明白,在這上面打個(gè)斷點(diǎn)調(diào)試一下,就會(huì)十分清楚了。這個(gè)方法是Openfire中的源代碼,不過(guò)全是E文,大象先也看不明白,后來(lái)調(diào)試了一下,知道是怎么回事了,特加上注釋和大家一起分享這個(gè)好東東。
           寫(xiě)完了自定義標(biāo)簽類(lèi),我們還需要自定義標(biāo)簽文件,在WEB-INF目錄下新建demo.tld,代碼不帖出來(lái)了,使用源碼中的就行。
        5、裝飾器
           后臺(tái)的Java類(lèi),我們?nèi)繉?xiě)完了,現(xiàn)在開(kāi)始完成前臺(tái)部分,在頁(yè)面顯示上,Openfire使用了sitemesh裝飾器框架,它能幫助我們?cè)谟纱罅宽?yè)面構(gòu)成的項(xiàng)目中創(chuàng)建一致的頁(yè)面布局和外觀,如一致的導(dǎo)航條,一致的banner,一致的版權(quán)等等。至于怎樣使用sitemesh這里不作介紹了,請(qǐng)自行去搜索相關(guān)資料,這部分內(nèi)容網(wǎng)上很多的,sitemesh比較簡(jiǎn)單,很容易上手。
           使用裝飾器,需要導(dǎo)入JAR包,在本例中,大象使用的是sitemesh-2.2.1.jar包,將jar包加到WEB-INF/lib目錄中,然后修改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>
           然后在WEB-INF下新建decorators.xml文件,內(nèi)容如下:
        <decorators defaultdir="/decorators">
            
    <decorator name="main" page="main.jsp">
                
    <pattern>/index.jsp</pattern>
                
    <pattern>/book_*.jsp</pattern>
            
    </decorator>
        
    </decorators>
           請(qǐng)注意defaultdir后面的值,這是你放裝飾器頁(yè)面的目錄位置。本例中,在WebRoot目錄下新建decorators文件夾,再在里面新建main.jsp,這個(gè)就是裝飾器頁(yè)面了。<pattern></pattern>之間的內(nèi)容就是需要被裝飾的頁(yè)面,*號(hào)是通配符,可以代替任何字符。/book_*.jsp表示:使用main.jsp裝飾WebRoot目錄下所有以book_開(kāi)頭的頁(yè)面,這里定義的name="main",可以在裝飾器頁(yè)面中使用,因?yàn)椴灰欢ㄖ挥幸粋€(gè)裝飾器頁(yè)面,可能會(huì)有很多個(gè)。因此,在裝飾器頁(yè)面中為了布局效果會(huì)聯(lián)合使用多個(gè)裝飾器來(lái)修飾頁(yè)面,以達(dá)到簡(jiǎn)化布局、降低維護(hù)難度、提高工作效率的作用。另外在使用時(shí),請(qǐng)注意被裝飾頁(yè)面與裝飾器頁(yè)面之間的相對(duì)位置。
        6、main.jsp
            在頁(yè)面中引用被裝飾頁(yè)面的page對(duì)象:<decorator:usePage id="decoratedPage" />
            使用decoratedPage取得被裝飾頁(yè)面中meta標(biāo)簽的content值,再將它放到request請(qǐng)求中,這樣在自定義標(biāo)簽類(lèi)中我們使用pageContext對(duì)象得到的請(qǐng)求就是這個(gè)
        <%
            request.setAttribute(
    "pageID", decoratedPage.getProperty("meta.pageID"));
        %>
            顯示被裝飾頁(yè)面<title></title>之間的標(biāo)題:<decorator:title />
            顯示被裝飾頁(yè)面body中的內(nèi)容,被裝飾頁(yè)面的主體都將在這里顯示:<decorator:body/>
            除此之外,在main.jsp中,我們還發(fā)現(xiàn)大量的使用div來(lái)放置元素,并且每個(gè)標(biāo)簽中都有id屬性,沒(méi)有看到任何的CSS樣式,其實(shí)是通過(guò)id屬性在demo.css文件進(jìn)行了定義,所有的布局和顯示效果都在這個(gè)文件中進(jìn)行了定義,這樣就達(dá)到了內(nèi)容呈現(xiàn)與樣式布局相分離的結(jié)果,方便以后的修改和維護(hù),這種做法用的人現(xiàn)在已經(jīng)越來(lái)越多,大家趕快行動(dòng)吧!
           sitemesh中還有一個(gè)sitemesh.xml文件,如果程序中沒(méi)有特別需求,可以不用加入它,我們也能在sitemesh-2.2.1.jar中找到,com.opensymphony.module.sitemesh.factory目錄下有一個(gè)sitemesh-default.xml文件,這就是sitemesh默認(rèn)的配置文件。
        7、顯示頁(yè)面
           在tag-console.xmlurl屬性里定義了顯示頁(yè)面,接下來(lái)我們把這些頁(yè)面都做好,內(nèi)容很簡(jiǎn)單,本文只是演示Openfire的菜單設(shè)計(jì)思想,用容易懂的例子來(lái)說(shuō)明,以便大家能夠快速了解。
          index.jsp頁(yè)面的代碼:
    <%@ page contentType="text/html; charset=utf-8" %>
    <html>
    <head>
        
    <title>Struts2 深入詳解</title>
        
    <meta name="pageID" content="695043"/>
    </head>
    <body>
        
    <center><h1>Struts2 深入詳解</h1></center>
    </body>
    </html>
           其余的幾個(gè)頁(yè)面內(nèi)容大致一樣,把content值、<title></title>標(biāo)題、以及<center><h1></h1></center>之間的內(nèi)容換成book元素中定義的屬性值即可。
           demo.css
           在WebRoot目錄下新建css文件夾,再在里面創(chuàng)建demo.css文件。我直接把Openfire的樣式表COPY過(guò)來(lái)。然后把里面沒(méi)用的部分刪除了,體積小了不少。
           圖片
           我從Openfire中只取了本例用到的圖片,如果是專(zhuān)業(yè)美工,完全可以設(shè)計(jì)出自己的菜單風(fēng)格。
        8、發(fā)布項(xiàng)目
           我們?cè)?span lang="EN-US">web.xml中可以加入下面一段代碼,index.jsp作為我們的默認(rèn)顯示頁(yè)面:

        <welcome-file-list>
            
    <welcome-file>index.jsp</welcome-file>
        
    </welcome-file-list>
           把demo部署到%TOMCAT_HOME%\webapps目錄下,啟動(dòng)tomcat,在地址欄中輸入:http://localhost:8080/demo 看看效果是不是和下面的一樣:

           大家覺(jué)得這個(gè)菜單的顯示方式怎么樣呢?偶覺(jué)得這用來(lái)做后臺(tái)管理到還是不錯(cuò)滴,如果是其它的信息管理系統(tǒng),那這個(gè)配置文件的內(nèi)容就會(huì)很恐怖了,其實(shí)還可以把XML中的中文信息保存到國(guó)際化資源文件中,這樣可以實(shí)現(xiàn)多語(yǔ)種版本以及簡(jiǎn)化維護(hù)。各位有什么好的意見(jiàn)或建議,可以和我留言或E-mail給我。大象也想把自己的一點(diǎn)心得拿出來(lái)和大家分享。
           點(diǎn)擊下載:demo源碼
           點(diǎn)擊下載:dom4j-1.6.1.jar  jaxen-1.1-beta-7.jar  sitemesh-2.2.1.jar
           本文為菠蘿大象原創(chuàng),如要轉(zhuǎn)載請(qǐng)注明出處
    posted on 2008-08-17 23:35 菠蘿大象 閱讀(3977) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): dom4j&jdom
    主站蜘蛛池模板: 99久久国产亚洲综合精品| 9久热精品免费观看视频| 97免费人妻在线视频| 亚洲成a人片在线观看国产| 亚洲Av高清一区二区三区| 光棍天堂免费手机观看在线观看| 狠狠久久永久免费观看| 久久亚洲中文字幕精品有坂深雪| 国产99久久久久久免费看| 国产高清视频在线免费观看| 亚洲国产高清美女在线观看| 免费观看91视频| 国产亚洲精品影视在线产品 | 亚洲欧美在线x视频| h片在线免费观看| 亚洲国产精品久久久久婷婷软件| 九九全国免费视频| 四虎免费久久影院| 亚洲国产精华液2020| 无码人妻一区二区三区免费手机| 91亚洲精品第一综合不卡播放| 国内精品免费久久影院| 亚洲免费无码在线| 猫咪免费人成在线网站| 国产又黄又爽又刺激的免费网址 | 亚洲国产综合AV在线观看| 国产精品1024永久免费视频| 亚洲人成网www| 免费人成网站在线观看不卡| 亚洲欧洲成人精品香蕉网| av电影在线免费看| 亚洲精品偷拍视频免费观看 | 久久国产精品免费一区| 亚洲日韩人妻第一页| 日韩精品无码永久免费网站| 国产免费av一区二区三区| 大桥未久亚洲无av码在线| 暖暖日本免费在线视频| 亚洲精华液一二三产区| 大地资源在线观看免费高清| 91在线亚洲综合在线|