近段时间做了一个项目,项目的前台框架是基于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> [产品列表]</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)"><a 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技术可以生成静态和动态的菜单,功能非常强大,但是对于小型的又常常需要数据库的动态数据的需求,用这种方法不失为一种便捷,高效的方法,希望能与大家共享。
本文介绍了一种使用Java生成动态树型菜单的方法,该方法通过业务类处理并返回HTML字符串,提高了菜单生成效率。通过递归调用实现了多级菜单结构,并在前端仅需一行代码即可调用。
238

被折叠的 条评论
为什么被折叠?



