<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+少量的代碼=通用的自定義菜單和動態加載的樹

    前言:
    知識準備:首先你需要懂一些struts的基本知識,會用struts-menu,并理解站長對struts-menu的分析那篇文章,還要知道ibatis的基本知識,如果不懂,請去google或者站長的論壇里找相關的文章。

    樹形結構在實際開發中很常用,但是樹形結構的開發往往也是難題,尤其是在顯示這一條上,很難做到通用。通常有兩種典型的樹型結構。一種是論壇的帖子,其結構往往通過父子ID號相連,數據在一張表里。一種是級別,比如論壇中的Category->Forum->Thread這種結構,數據放在不同的表里。因為論壇恰好包含了這兩種結構。因此。我們就能Jive的表結構來做這個例子。首先我們通過RsMetaDataTest來掃描數據庫,得到需要的XML配置文件。拿一個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>

     

    可見有一個名叫findjivecategoryDao,這是一個典型的動態查詢。返回對象是HashMap。其中$listfield$表示動態讀取的字段??梢赃@么說,通過這個查詢。有關這樣表的任何方式的查詢都已經解決了。由于這個演示只用到四張表,因些我們在sql-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類,這個類是一個通用的定義,其主要屬性如下。可以通過它建立一個四張表的樹形關系。

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

     


    然后建立一個XML的文件(此處簡化了它的功能,就是把上面這個類序列化了一下)。把它放在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>大分類</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>子分類</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>

       

     

    關聯關系是category表通過CATEGORYID與forum關聯,forum通過FORUMID與thread關聯,thread是一張特殊的表。它將不顯示在樹中,只是一個過渡關聯,用于讀出新建的文章。

    thread通過FORUMID、FORUMID、ROOTMESSAGEID與message表關聯(FORUMID、FORUMID、MESSAGEID)。而message表是一個自關聯的表。MESSAGEID與PARENTMESSAGEID關聯建立父子關系。

    然后我們建立一個session類作為主要類

    public class TreeDemoSession {
     //通過名稱和參數來得到樹
     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;
     }

     /**一個典型的遞歸函數。用以組織樹。
      * @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,表示需要讀取哪幾個字段
       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();
                    //建立當前節點
        MenuComponent submenu = new MenuComponent();
        submenu.setName(menu.getName() + String.valueOf(namei++));
        submenu.setTitle(
         String.valueOf(element.get(menudefine.getTitleField())));
         //如果不需要顯示,則使用父節點作為當前節點
        if (!menudefine.isNeedShow())
         submenu = menu;
        //如果有子菜單,則遞歸調用。 
        if (menudefine.getSubmenuName() != null) {

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

       throw e;
      } catch (Exception e) {

       throw e;
      }
     }

     /**將父菜單的關鍵字段的值作為參數給子菜單
      * @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;
     }
    }

     

    三個函數,非常簡單,主函數讀取配置文件的內容。一個遞歸函數用來建立樹形結構。這棵樹只有兩個屬性被設置。一個是名字和標題。其中標題采用從數據庫里讀出的字段。名字則采用流水號。讀取數據庫只有一句,其中map是參數的一個列表。后面是sql的名字。

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

    而真正的實現代碼也非常簡單

    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);
    }
    }

    下面我們來做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"));
    }

     


    這個函數也非常簡單,就是把從request傳來的內容生成一個Map對象。然后調用session,將返回結果以com.ewuxi.champion.menu為名字保存到request中去。

    最后我們需要生成一個自定義的taglib。實際上很簡單。只是因為struts-menu自身的taglib是寫死了,我們不能利用,不過只要改一個地方就可以了,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了。然后需要建立一個JSP文件。我們把xtree.jsp借用過來。唯一需要改的就是<cp:displayMenu name="com.ewuxi.champion.menu"/>,當然還有幾個link的路徑。因為此處用treeDemo來所以就是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">大分類列表</a>
    </p>
    <p><a href="demo.do?type=demo&menuName=forum" target="_blank">子分類列表</a> </p>
    <p><a href="demo.do?type=demo&menuName=forum&FORUMID=1" target="_blank">只看java分類</a> </p>
    <p><a href="demo.do?type=demo&menuName=thread" target="_blank">所有文章</a> </p>

    上面是幾種不同的參數。主要的差別是menuName不同。然后也可以加數據庫需要的參數,比如java分類的forumId=1。就在參數中加FORUMID=1,注意大小寫要跟XML中的動態參數相同,此處全是大寫。

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

     

    主站蜘蛛池模板: 国产精品99久久免费观看| 又粗又长又爽又长黄免费视频 | 成年人视频在线观看免费| 久久精品国产亚洲av影院| 久久国产高潮流白浆免费观看| 亚洲精品无码不卡在线播HE| 久久免费观看视频| 亚洲精品无码久久久久去q| jizz18免费视频| 国产亚洲精品一品区99热| 国产精品免费无遮挡无码永久视频| 亚洲av永久无码精品网站| 香港a毛片免费观看 | AV片在线观看免费| 亚洲AV无码精品国产成人| 国产免费牲交视频| 国产99精品一区二区三区免费| 亚洲午夜久久久久久久久电影网| 最近免费中文字幕中文高清| 亚洲国产精品久久| 动漫黄网站免费永久在线观看| jzzijzzij在线观看亚洲熟妇| 亚洲女人被黑人巨大进入| 日本人成在线视频免费播放| 亚洲不卡视频在线观看| 国产一级做a爱免费视频| a一级毛片免费高清在线| 久久精品国产精品亚洲艾草网| 四虎1515hh永久久免费| 亚洲爆乳少妇无码激情| 亚洲日韩精品一区二区三区| 麻豆高清免费国产一区| 亚洲av永久无码天堂网| 亚洲日韩精品射精日| 国产一卡2卡3卡4卡无卡免费视频| 国产亚洲一卡2卡3卡4卡新区| 亚洲综合AV在线在线播放| 69av免费视频| 免费看一级一级人妻片| 久久99亚洲网美利坚合众国| 日本高清免费中文字幕不卡|