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

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

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

    海鷗航際

    JAVA站
    posts - 11, comments - 53, trackbacks - 1, articles - 102

    struts-menu+ibatis+少量的代碼=通用的自定義菜單和動(dòng)態(tài)加載的樹(shù)

    前言:
    知識(shí)準(zhǔn)備:首先你需要懂一些struts的基本知識(shí),會(huì)用struts-menu,并理解站長(zhǎng)對(duì)struts-menu的分析那篇文章,還要知道ibatis的基本知識(shí),如果不懂,請(qǐng)去google或者站長(zhǎng)的論壇里找相關(guān)的文章。

    樹(shù)形結(jié)構(gòu)在實(shí)際開(kāi)發(fā)中很常用,但是樹(shù)形結(jié)構(gòu)的開(kāi)發(fā)往往也是難題,尤其是在顯示這一條上,很難做到通用。通常有兩種典型的樹(shù)型結(jié)構(gòu)。一種是論壇的帖子,其結(jié)構(gòu)往往通過(guò)父子ID號(hào)相連,數(shù)據(jù)在一張表里。一種是級(jí)別,比如論壇中的Category->Forum->Thread這種結(jié)構(gòu),數(shù)據(jù)放在不同的表里。因?yàn)檎搲『冒诉@兩種結(jié)構(gòu)。因此。我們就能Jive的表結(jié)構(gòu)來(lái)做這個(gè)例子。首先我們通過(guò)RsMetaDataTest來(lái)掃描數(shù)據(jù)庫(kù),得到需要的XML配置文件。拿一個(gè)xml為例,解釋一下

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sql-map
    PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN"
    "<sql-map name="jivecategory">
    <!-- =============================================
        mapped-statement find
    ============================================= -->
    <dynamic-mapped-statement name="findjivecategoryDao"  result-class="java.util.HashMap">
       select $listfield$  from JIVECATEGORY
       <dynamic prepend="where">
          <isPropertyAvailable prepend="and" property="CATEGORYID" >
             <isNotNull prepend="" property="CATEGORYID" >
                 CATEGORYID=#CATEGORYID#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="NAME" >
             <isNotNull prepend="" property="NAME" >
                 NAME=#NAME#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="DESCRIPTION" >
             <isNotNull prepend="" property="DESCRIPTION" >
                 DESCRIPTION=#DESCRIPTION#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="CREATIONDATE" >
             <isNotNull prepend="" property="CREATIONDATE" >
                 CREATIONDATE=#CREATIONDATE#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="MODIFIEDDATE" >
             <isNotNull prepend="" property="MODIFIEDDATE" >
                 MODIFIEDDATE=#MODIFIEDDATE#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="LFT" >
             <isNotNull prepend="" property="LFT" >
                 LFT=#LFT#
             </isNotNull>
          </isPropertyAvailable>
          <isPropertyAvailable prepend="and" property="RGT" >
             <isNotNull prepend="" property="RGT" >
                 RGT=#RGT#
             </isNotNull>
          </isPropertyAvailable>
       </dynamic>  
    </dynamic-mapped-statement>

    </sql-map>

     

    可見(jiàn)有一個(gè)名叫findjivecategoryDao,這是一個(gè)典型的動(dòng)態(tài)查詢。返回對(duì)象是HashMap。其中$listfield$表示動(dòng)態(tài)讀取的字段。可以這么說(shuō),通過(guò)這個(gè)查詢。有關(guān)這樣表的任何方式的查詢都已經(jīng)解決了。由于這個(gè)演示只用到四張表,因些我們?cè)趕ql-map-config-storedb.xml也只加載了四張表的定義。

    <sql-map resource="sqlmap/jivecategory.xml" />
    <sql-map resource="sqlmap/jiveforum.xml" />
    <sql-map resource="sqlmap/jivethread.xml" />
    <sql-map resource="sqlmap/jivemessage.xml" />

    然后定義MenuDefine類(lèi),這個(gè)類(lèi)是一個(gè)通用的定義,其主要屬性如下。可以通過(guò)它建立一個(gè)四張表的樹(shù)形關(guān)系。

    //sql Map的名稱
    private String sqlMapName;
    //調(diào)用的查詢名稱
    private String SqlName;
    //子菜單的名稱
    private String submenuName; //對(duì)應(yīng)字段,其中key為主表的字段,value是從表的字段。
    private HashMap keymap;
    //菜單的名稱
    private String MenuName;
    //標(biāo)題
    private String Title;
    //標(biāo)題字段
    private String TitleField;
    //需要讀取的字段
    private String listField;
    //是否需要顯示
    private boolean needShow=true;

     


    然后建立一個(gè)XML的文件(此處簡(jiǎn)化了它的功能,就是把上面這個(gè)類(lèi)序列化了一下)。把它放在classes目錄下。

     

    <?xml version="1.0" encoding="UTF-8"?>
    <java version="1.4.2_03" class="java.beans.XMLDecoder">
     <object class="java.util.HashMap">
      <void method="put">
       <string>message</string>
       <object class="com.ewuxi.champion.MenuDefine">
        <void property="keymap">
         <object class="java.util.HashMap">
          <void method="put">
           <string>MESSAGEID</string>
           <string>PARENTMESSAGEID</string>
          </void>
         </object>
        </void>
        <void property="listField">
         <string>MESSAGEID,SUBJECT</string>
        </void>
        <void property="menuName">
         <string>message</string>
        </void>
        <void property="sqlMapName">
         <string>jivemessage</string>
        </void>
        <void property="sqlName">
         <string>findjivemessageDao</string>
        </void>
        <void property="submenuName">
         <string>message</string>
        </void>
        <void property="title">
         <string>文章</string>
        </void>
        <void property="titleField">
         <string>SUBJECT</string>
        </void>
       </object>
      </void>
      <void method="put">
       <string>category</string>
       <object class="com.ewuxi.champion.MenuDefine">
        <void property="keymap">
         <object class="java.util.HashMap">
          <void method="put">
           <string>CATEGORYID</string>
           <string>CATEGORYID</string>
          </void>
         </object>
        </void>
        <void property="listField">
         <string>CATEGORYID,NAME</string>
        </void>
        <void property="menuName">
         <string>category</string>
        </void>
        <void property="sqlMapName">
         <string>jivecategory</string>
        </void>
        <void property="sqlName">
         <string>findjivecategoryDao</string>
        </void>
        <void property="submenuName">
         <string>forum</string>
        </void>
        <void property="title">
         <string>大分類(lèi)</string>
        </void>
        <void property="titleField">
         <string>NAME</string>
        </void>
       </object>
      </void>
      <void method="put">
       <string>forum</string>
       <object class="com.ewuxi.champion.MenuDefine">
        <void property="keymap">
         <object class="java.util.HashMap">
          <void method="put">
           <string>FORUMID</string>
           <string>FORUMID</string>
          </void>
         </object>
        </void>
        <void property="listField">
         <string>FORUMID,NAME</string>
        </void>
        <void property="menuName">
         <string>forum</string>
        </void>
        <void property="sqlMapName">
         <string>jiveforum</string>
        </void>
        <void property="sqlName">
         <string>findjiveforumDao</string>
        </void>
        <void property="submenuName">
         <string>thread</string>
        </void>
        <void property="title">
         <string>子分類(lèi)</string>
        </void>
        <void property="titleField">
         <string>NAME</string>
        </void>
       </object>
      </void>
      <void method="put">
       <string>thread</string>
       <object class="com.ewuxi.champion.MenuDefine">
        <void property="keymap">
         <object class="java.util.HashMap">
          <void method="put">
           <string>THREADID</string>
           <string>THREADID</string>
          </void>
          <void method="put">
           <string>FORUMID</string>
           <string>FORUMID</string>
          </void>
          <void method="put">
           <string>ROOTMESSAGEID</string>
           <string>MESSAGEID</string>
          </void>
         </object>
        </void>
        <void property="listField">
         <string>THREADID,ROOTMESSAGEID</string>
        </void>
        <void property="menuName">
         <string>thread</string>
        </void>
        <void property="needShow">
         <boolean>false</boolean>
        </void>
        <void property="sqlMapName">
         <string>jivethread</string>
        </void>
        <void property="sqlName">
         <string>findjivethreadDao</string>
        </void>
        <void property="submenuName">
         <string>message</string>
        </void>
        <void property="title">
         <string>欄目</string>
        </void>
        <void property="titleField">
         <string>ROOTMESSAGEID</string>
        </void>
       </object>
      </void>
     </object>
    </java>

       

     

    關(guān)聯(lián)關(guān)系是category表通過(guò)CATEGORYID與forum關(guān)聯(lián),forum通過(guò)FORUMID與thread關(guān)聯(lián),thread是一張?zhí)厥獾谋怼K鼘⒉伙@示在樹(shù)中,只是一個(gè)過(guò)渡關(guān)聯(lián),用于讀出新建的文章。

    thread通過(guò)FORUMID、FORUMID、ROOTMESSAGEID與message表關(guān)聯(lián)(FORUMID、FORUMID、MESSAGEID)。而message表是一個(gè)自關(guān)聯(lián)的表。MESSAGEID與PARENTMESSAGEID關(guān)聯(lián)建立父子關(guān)系。

    然后我們建立一個(gè)session類(lèi)作為主要類(lèi)

    public class TreeDemoSession {
     //通過(guò)名稱和參數(shù)來(lái)得到樹(shù)
     public MenuComponent getMenu(String name, Map keys) throws Exception {
      Map menuMap =
       (Map) (new XmlUtils().read(Service.getPath() + "/menu.xml"));
      MenuComponent menu = new MenuComponent();

      if (menuMap.get(name) != null) {
       MenuDefine rootMenudefine = (MenuDefine) menuMap.get(name);
       menu.setTitle(rootMenudefine.getTitle());
       menu.setName(rootMenudefine.getMenuName());

       menu = submenuAdd(menu, keys, menuMap, name);
      }
      return menu;
     }

     /**一個(gè)典型的遞歸函數(shù)。用以組織樹(shù)。
      * @param menu
      * @param map
      * @param menuMap
      * @param menuName
      * @return
      * @throws DaoException
      * @throws Exception
      */
     private MenuComponent submenuAdd(
      MenuComponent menu,
      Map map,
      final Map menuMap,
      String menuName)
      throws DaoException, Exception {
      try {
       //得到菜單定義
       MenuDefine menudefine = (MenuDefine) menuMap.get(menuName);
       //listfield,表示需要讀取哪幾個(gè)字段
       map.put("listfield", menudefine.getListField());
       //查詢,返回列表。
       List list = DaoCommon.findbyName(map, menudefine.getSqlName());

       int namei = 0;
       for (Iterator iter = list.iterator(); iter.hasNext();) {
        Map element = (Map) iter.next();
                    //建立當(dāng)前節(jié)點(diǎn)
        MenuComponent submenu = new MenuComponent();
        submenu.setName(menu.getName() + String.valueOf(namei++));
        submenu.setTitle(
         String.valueOf(element.get(menudefine.getTitleField())));
         //如果不需要顯示,則使用父節(jié)點(diǎn)作為當(dāng)前節(jié)點(diǎn)
        if (!menudefine.isNeedShow())
         submenu = menu;
        //如果有子菜單,則遞歸調(diào)用。 
        if (menudefine.getSubmenuName() != null) {

         submenu =
          submenuAdd(
           submenu,
           getSubMenuInfo(menudefine, element),
           menuMap,
           menudefine.getSubmenuName());
        }
        //將當(dāng)前節(jié)點(diǎn)放到樹(shù)中。(如果不需要顯示就不用放)
        if (menudefine.isNeedShow())
         menu.addMenuComponent(submenu);
       }
       return menu;
      } catch (DaoException e) {

       throw e;
      } catch (Exception e) {

       throw e;
      }
     }

     /**將父菜單的關(guān)鍵字段的值作為參數(shù)給子菜單
      * @param menudefine
      * @param element
      * @return
      */
     private HashMap getSubMenuInfo(MenuDefine menudefine, Map element) {
      HashMap map = new HashMap();
      for (Iterator iter = menudefine.getKeymap().keySet().iterator();
       iter.hasNext();
       ) {
       String key = (String) iter.next();
       map.put(menudefine.getKeymap().get(key), element.get(key));
      }
      return map;
     }
    }

     

    三個(gè)函數(shù),非常簡(jiǎn)單,主函數(shù)讀取配置文件的內(nèi)容。一個(gè)遞歸函數(shù)用來(lái)建立樹(shù)形結(jié)構(gòu)。這棵樹(shù)只有兩個(gè)屬性被設(shè)置。一個(gè)是名字和標(biāo)題。其中標(biāo)題采用從數(shù)據(jù)庫(kù)里讀出的字段。名字則采用流水號(hào)。讀取數(shù)據(jù)庫(kù)只有一句,其中map是參數(shù)的一個(gè)列表。后面是sql的名字。

    List list = DaoCommon.findbyName(map, menudefine.getSqlName());

    而真正的實(shí)現(xiàn)代碼也非常簡(jiǎn)單

    public static List findbyName(Object vo,String name) throws DaoException {
    try {
    SqlMap sqlMap = DaoCommon.getSqlMap(DaoCommon.getDefautDao());
    return (List) sqlMap.executeQueryForList(name, vo);
    } catch (Exception e) {
    throw new DaoException(e);
    }
    }

    下面我們來(lái)做Action的工作

    public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws Exception { Service.initSet();
    DaoCommon.startTransaction();

    HashMap parMap = new HashMap();
    Enumeration enumeration = request.getParameterNames();
    while (enumeration.hasMoreElements()) {
    String element = (String) enumeration.nextElement();
    parMap.put(element, request.getParameter(element));
    }
    TreeDemoSession session=new TreeDemoSession();
    request.setAttribute("com.ewuxi.champion.menu",session.getMenu(request.getParameter("menuName"),parMap));

    DaoCommon.rollBack();

    return mapping.findForward(request.getParameter("type"));
    }

     


    這個(gè)函數(shù)也非常簡(jiǎn)單,就是把從request傳來(lái)的內(nèi)容生成一個(gè)Map對(duì)象。然后調(diào)用session,將返回結(jié)果以com.ewuxi.champion.menu為名字保存到request中去。

    最后我們需要生成一個(gè)自定義的taglib。實(shí)際上很簡(jiǎn)單。只是因?yàn)閟truts-menu自身的taglib是寫(xiě)死了,我們不能利用,不過(guò)只要改一個(gè)地方就可以了,copy UseMenuDisplayerTag到我們的目錄下。

    MenuRepository repository =
    (MenuRepository) pageContext.getServletContext().getAttribute(MenuRepository.MENU_REPOSITORY_KEY); if (repository == null) {
    throw new JspException("Could not obtain the menu repository");
    }

    MenuComponent menu = repository.getMenu(this.name);

     

    找到上面這一段,改成


    MenuComponent menu =
    (MenuComponent) pageContext.findAttribute(this.name);


    就OK了。然后需要建立一個(gè)JSP文件。我們把xtree.jsp借用過(guò)來(lái)。唯一需要改的就是<cp:displayMenu name="com.ewuxi.champion.menu"/>,當(dāng)然還有幾個(gè)link的路徑。因?yàn)榇颂幱胻reeDemo來(lái)所以就是href="/treeDemo/styles/xtree.css"

    <head>
    <title>XTree (with Velocity) Example</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <link rel="stylesheet" type="text/css" media="screen"
    href="/treeDemo/styles/global.css" />
    <link rel="stylesheet" type="text/css" media="screen"
    href="/treeDemo/styles/xtree.css" />

    <script type="text/javascript" src="/treeDemo/scripts/xtree.js"></script>

    </head>
    <body>

    <div class="container">
    Simple menu with Velocity:<br />
    <script type="text/javascript">
    <menu:useMenuDisplayer name="Velocity" config="/templates/xtree.html"
    bundle="org.apache.struts.action.MESSAGE">
    if (document.getElementById) {
    <cp:displayMenu name="com.ewuxi.champion.menu"/>
    } else {
    var msg = "Your browser does not support document.getElementById().\n";
    msg += "You must use a modern browser for this menu.";
    alert(msg);
    }


    </menu:useMenuDisplayer>
    </script>
    </div>

     

     

    下面就可以自由的看效果了。

    <p><a href="demo.do?type=demo&menuName=category" target="_blank">大分類(lèi)列表</a>
    </p>
    <p><a href="demo.do?type=demo&menuName=forum" target="_blank">子分類(lèi)列表</a> </p>
    <p><a href="demo.do?type=demo&menuName=forum&FORUMID=1" target="_blank">只看java分類(lèi)</a> </p>
    <p><a href="demo.do?type=demo&menuName=thread" target="_blank">所有文章</a> </p>

    上面是幾種不同的參數(shù)。主要的差別是menuName不同。然后也可以加數(shù)據(jù)庫(kù)需要的參數(shù),比如java分類(lèi)的forumId=1。就在參數(shù)中加FORUMID=1,注意大小寫(xiě)要跟XML中的動(dòng)態(tài)參數(shù)相同,此處全是大寫(xiě)。

    在線演示看這樣http://demo.ewuxi.com:8000/treejivedemo/,源碼下載

     

    主站蜘蛛池模板: 亚洲中文字幕无码mv| 久久WWW免费人成—看片| 国产乱子影视频上线免费观看| 猫咪免费人成网站在线观看入口| 中文字幕亚洲乱码熟女一区二区| 国产成人AV片无码免费| 亚洲人成电影网站色www| 亚洲精品无码成人AAA片| 日本亚洲免费无线码| 一级全免费视频播放| 亚洲人色大成年网站在线观看| 免费在线观看理论片| 蜜臀98精品国产免费观看| 亚洲a无码综合a国产av中文| 日本亚洲成高清一区二区三区| 在线播放免费人成视频在线观看| 精品国产免费人成网站| 亚洲成人激情小说| 亚洲成色www久久网站夜月| 女人被男人桶得好爽免费视频 | 亚洲一区二区三区高清不卡| 亚洲日本一区二区一本一道| 亚洲精品免费在线视频| 一级毛片免费毛片毛片| 亚洲国产区男人本色在线观看| 亚洲色欲一区二区三区在线观看| 午夜成年女人毛片免费观看| 永久免费av无码入口国语片| 亚洲av无码有乱码在线观看| 亚洲国语精品自产拍在线观看| 免费国产人做人视频在线观看| aⅴ在线免费观看| 中国内地毛片免费高清| 福利片免费一区二区三区| 亚洲av乱码一区二区三区香蕉 | 中文字幕免费在线观看| 黄 色一级 成 人网站免费| 亚洲精品色播一区二区| 亚洲女人影院想要爱| 国产精品亚洲片在线| 亚洲精品无码久久毛片 |