遞歸算法在樹型菜單中的應用

近段時間做了一個項目,項目的前臺框架是基於webwork+freemarker。需要一個樹型菜單,於是研究了一下樹型菜單的編寫方法,發現大多數樹型菜單都是利用xml通過javascript生成的,對於dom不太熟悉的開發這來說,顯得太複雜,而且層次感不強。 我們項目採用的是另外一種方法,把菜單的動態生成的所有工作交給業務類處理,然後處理,返回一個html代碼以字符串的形式給界面(freemarker),前臺只需調用即可以了,這樣做的一個最大的好處就是菜單動態數據的生成是在java編譯階段生成,而且只需要生成一次,即保存在內存中,這樣就減少了界面重複查詢數據的負擔,項目運行結果發現菜單運行的效率非常高,一下是它實現核心代碼:
package com.sunrise.baselib.action.home;

import
 java.sql.SQLException;
import
 java.util.Iterator;
import
 java.util.List;
import
 java.util.Map;

import
 com.opensymphony.xwork.ActionContext;
import
 com.opensymphony.xwork.ActionSupport;
import
 com.sunrise.baselib.domain.FunctionView;
import
 com.sunrise.baselib.domain.ProductView;
import
 com.sunrise.baselib.domain.TechView;
import
 com.sunrise.baselib.service.KnowledgeQueryService;

public class LoadKnowledgeSortAction extends ActionSupport 
{

    List products;
    
//service操縱數據庫

    KnowledgeQueryService knowledgeQueryService;
    
    
//設置產品視圖的菜單

    public String setProductMenu(String choose) throws SQLException {
        List list;
        String modulename 
= ""
;
        String moduleid 
= ""
;
        String source 
= ""
;
        String sql 
= "from ProductView f where f.parentProduct is null Order by f.name"
;
        list 
= this
.knowledgeQueryService.find(sql);
        
if (list.size() > 0
{
            Iterator it 
=
 list.iterator();
            
while (it.hasNext()) 
{
                ProductView produc 
=
 (ProductView) it.next();
                
if (produc.getProductViews().size() > 0
{
                    source 
=
 source
                            
+ "<li nowrap>"

                            
+ "<a href='#'>+</a>"
                            
+"<td><input type='checkbox'  name='product"+produc.getId().toString()+"'></td>"
                            
+produc.getName() + "("
                            
+ produc.getProductViews().size() + ")</li>";
                }
 else {
                    source 
=
 source
                            
+ "<li nowrap>"

                            
+"<a href='#'></a>"
                            
+"<td><input type='checkbox'  name='product"+produc.getId().toString()+"'></td>"
                            
+ produc.getName() + "</li>";
                }

                
if (produc.getProductViews().size() > 0{
                    source 
= source +
 getProductSource(produc,choose);
                }

            }

        }

        System.out.println(source);
        
return source;
    }

                    
                    
//導入字節點的數據
    private String getProductSource(ProductView produc,String choose) throws SQLException {
        String modulename 
= ""
;
        String moduleid 
= ""
;
        String source 
= ""
;
        String rowsex 
= ""
;
        modulename 
=
 produc.getName();
        moduleid 
= produc.getId() + ""
;
        Iterator itx 
=
 produc.getProductViews().iterator();
        
while (itx.hasNext()) 
{
            ProductView producx 
=
 (ProductView) itx.next();
            
if (producx.getProductViews().size() > 0
{
                source 
= source + "<li nowrap>"

                        
+ "<a href='#'>+</a>"
                        
+"<td><input type='checkbox' +
                                                                                                                             +name='product"+producx.getId().toString()+"'></td>"
                        +producx.getName() + "("

                        
+ producx.getProductViews().size() + ")</li>";
            }
 else {
                source 
=
 source
                        
+ "<li nowrap>"

                        
+"<a href='#'></a>"
                        
+"<td><input type='checkbox'  name='product"+producx.getId().toString()+"'></td>"
                        
+ producx.getName() + "</li>";
            }

            
if (producx.getProductViews().size() > 0{
                
//遞歸調用

                source = source + getProductSource(producx,choose);
            }

        }

        source 
= "<ul>" + source + "</ul>";

        
return
 source;
    }

        
    
//導出product列表,放在session中,用於界面調用
    public String loadProducts() throws Exception{
        
this.products=this
.knowledgeQueryService.findProducts();
                                        
                                           
//調用setProductMenu()生成html字符串

                                          String module = this.setProductMenu("module");
        

        ActionContext ctx 
=
 ActionContext.getContext();
        Map session 
=
 ctx.getSession();

        session.put(
"productList"
, module);
        
return
 SUCCESS;
    }


    
public List getProducts() {
        
return
 products;
    }


    
public KnowledgeQueryService getKnowledgeQueryService() {
        
return
 knowledgeQueryService;
    }

    
public void setKnowledgeQueryService(KnowledgeQueryService knowledgeQueryService) {
        
this.knowledgeQueryService =
 knowledgeQueryService;
    }

}

 
界面調用的代碼就簡單的不能再簡單了:
<link rel="stylesheet" href="../css/aqtree3clickable.css">
<script type="text/javascript" src="../js/aqtree3clickable.js"></script>
<script language="javascript">    
        
<#------ 提交時檢查是否選擇至少一項 ------>
    
        
function
 verifyValue()
        
{  
           
var product_num=0
;
           
var product_id_list=""
;
           
var product_name_list=""
;
           
           
           
<#list products as product>

            
             
if(document.all.product${product.id}.checked)
              
{    
                  
if(product_num>0)
{
                     product_name_list
+=","
;
                     product_id_list
+=","
;
                  }

                  product_id_list
+=${product.id};
                  product_name_list
+="${product.name}"
;
                  product_num
++
;
             }
 
           
</#list>

           
if(product_num==0)
           
{
               alert(
"你沒有選擇任何記錄,請選擇! ---否則請點擊'關閉'---"
);
               
return false
;
           }

           
else
           
{
             window.opener.document.all(
"products").value=
product_id_list;
             window.opener.document.all(
"products_name").value=
product_name_list;
              self.close();
           }


        }
    
        
        
<#------------- 全選的功能實現 ------------->

        
function selectAll(current_form)
        
{
          
var current_state=
current_form.configure_check.checked;
          
           
<#list products as product>

             
if(current_state)
                  current_form.product$
{product.id}.checked=true
;
             
else

                 current_form.product$
{product.id}.checked=false;
          
           
</#list>

          
return true;
        }

        
        
function cancel(){
         self.close();
        }

    
</script>    
    
    
<body>

        
<div class="div">
            
            
<table width="100%" border="0" align="center" cellpadding="0" cellspacing="1">
                
<tr>
                
<td nowrap>&nbsp;&nbsp;[產品列表]</td>
                
<td>
                
</td>
                
                
</tr>
                
             
</table>

      
<form name="frmList" id="frmList" method="post" action="" onsubmit="return verifyValue();">
            
<#--  菜單的實現 -->
<ul class="aqtree3clickable">
          
<li><input type="checkbox" name="configure_check" onClick="selectAll(this.form)"><href="#">全部產品</a></li>
          
<ul>
          
<#-- 菜單實現 -->
          ${Session["productList"]?if_exists} 
          
</ul>
          
</ul>
           
<TABLE id="submittable" cellSpacing="1" cellPadding="0" width="99%" align="center" bgColor="#b1b1b1" border="0" Sortable="true" nameColNum="2" idColNums="1" SetRowNumber="true" MoveColable="false" showStatus="true" Editable="false">
                 
<tr class="content_tab_data">
                             
<td><input type="submit" name="submit" value="提交" onClick="verifyValue()">
                             
<input type="button" name="cancel" value="關閉" onClick="self.close()"></td>
                  
</tr>
            
</TABLE>  
          
</div>

    
</form>
form標籤裏面的東東就是生成菜單的地方,只需要一句話${Session["productList"]?if_exists} ,呵呵,是不是很簡單呀?
我的體會是xml技術可以生成靜態和動態的菜單,功能非常強大,但是對於小型的又常常需要數據庫的動態數據的需求,用這種方法不失爲一種便捷,高效的方法,希望能與大家共享。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章