论文部分内容阅读
【摘要】任何涉及菜单较多的业务系统,优化菜单的展现,减少登录时等待的时间都是很有必要的。通常CS结构下实现的下拉菜单需要读取全菜单,以某种格式组织在一起并展现。文章介绍了一种使用Java+JSP+JavaScript实现的多级下拉菜单,可以在短时间内在读取所有菜单的情况下成功登录系统。
【关键词】Java;JSP;JavaScrip;多级下拉菜单;节点;数据集
【中图分类号】 TP311 【文献标识码】A
【文章编号】1671-5969(2007)21-0185-02
一、实现基本思想
为了减少Client端的数据处理时间,即客户登录时间,在服务器端除了取得所有菜单的基础数据集外,根据设计的算法,生成三个层次的节点ID,和节点名称构成的TreeMap类型的数据集合返回给JSP页面。
JSP将服务器返回的数据集,放入隐藏的下拉框控件中,并调用JavaScript脚本进行处理。对于这个特殊的结果数据集,根据一定的循环调用算法,生成JSP页面上显示的源代码,并打印出来,形成最终的下拉菜单结果。
二、关键算法简介
1.从数据库取得菜单数据集,生成可排序,并且包含菜单真正路径的数据集合的遍历算法简介:
步骤一:从数据库取得符合条件的以下字段的数据集:节点ID,节点名称,父节点ID,热键字符,快捷键,是否终结菜单。
步骤二:遍历初始数据集一次,将快捷键扩展为4位,节点ID扩展为5位,并将快捷键,是否终结菜单,节点名称合并在节点名称字段中。本次遍历目的是生成两个结果集:(节点ID,父节点ID)TreeMap结果集,以及(节点ID,节点名称)TreeMap结果集。
步骤三:遍历(节点ID,父节点ID)TreeMap结果集一次,以节点ID寻找到根节点ID的方式,获得节点ID路径,并划分节点ID所属的菜单层次,最终得到结果集第一层(节点ID,节点名称)TreeMap,第二层(节点ID,节点名称)TreeMap,第三层(节点ID,节点名称)TreeMap。其中节点ID是节点的完全路径,前缀是4位的快捷键,连接字符是“-”号。之所以前4加入扩展后的快捷键,是因为数据集返回到JSP页面时页面控件有自动排序的功能;节点名称的第一位是“是否终结菜单”字段,该字段用于判断叶子或非叶子菜单。
2.JSP页面保存从服务器传来的数据结果集,调用JavaScript脚本处理算法简介:
步骤一:设计菜单展开函数,作为下拉菜单的基础函数,在遍历菜单数据集时使用。设计菜单打开函数,有非叶子菜单函数nodeLeftMenu(A,B),叶子菜单函数nodeView(A,B,0)。
步骤二:定义N层数据集合,对应页面上的各层数组,定义各种基本元素,例如数组长度,名称,是否终结菜单等,与从服务器返回的数据集合相对应。
步骤三:遍历第一层,根据“是否终结菜单”判断是否有子菜单:如果有,继续第二层数组遍历;否则,打印该菜单页面代码。菜单项采用IFRAME的格式,确保菜单项的独立性,并且加入菜单项页面菜单调用函数,如果该菜单项也是非叶子菜单,则加入调用非叶子菜单函数nodeLeftMenu(A,B),如果该菜单项是叶子菜单则加入调用叶子菜单函数nodeView(A,B,0)。如果第二层菜单也是非叶子菜单,则继续遍历第三层,并判断菜单是否叶子菜单,按照上述处理方式调用nodeLeftMenu()或者nodeView()。最后,将页面代码打印处理。
三、优缺点分析
1.优点:可以充分利用服务器的快速处理能力,生成基础数据集合。可以让最终的结果集在客户端处理,减轻了服务器的处理负担。实践证明,只要JavaScript对结果集的处理算法得当,浏览器的解析处理时间就很快速。
2.缺点:当菜单越来越多,并且多到满屏的时候,这种方式实现的下拉菜单就会部分看不到。虽然可以采用展现滚动条方式实现,但又影响了页面美观。处于菜单展开区域的页面如果有类似下拉框控件等就会影响菜单的显示,这也是JSP页面Style方式的缺点。
四、实现源代码
1.服务器从数据库取得数据,生成结果集合,并返回这个集合给JSP页面。算法源代码如下:
//LOGIC处理结果集,关键算法
public TreeMap getNodeMap2(String userID,String roleID) {
TreeMap IDPreIDMap = new TreeMap();
——多层结构在这里定义
TreeMap nodeMap = new TreeMap();
try { String sql = "";
if(roleID.equals("")){
sql = "SELECT DISTINCT 受理目录标识… FROM … …";
}
this.setMyDB(1004, 1007);
ResultSet rs = myDB.executeQuery(sql);//总数据集
while (rs.next()) {
String nodeID = Integer.toString(rs.getInt("受理目录标识"));
… … //从数据库数据获取,并赋予定义的变量
IDPreIDMap.put(nodeID, preNodeID);//ID,preID集合
this.IDNameMap.put(nodeID,nodeName);//ID,Name集合
}
//对数据集遍历一次,取得所有节点路径,节点名称
Iterator keyItor = IDPreIDMap.keySet().iterator();
String key = "",preKey = "",saveKey = "",nodeName = "";
int count = 0,size = IDPreIDMap.size();
for(int i=0;i key = keyItor.next().toString();//取得节点ID
preKey = IDPreIDMap.get(key).toString();//取得父节点ID
saveKey = key;//保存当前节点ID
count = 0;
//取得节点路径,使用符号-连接父子节点
while(!preKey.equals("0")){
}
//節点路径开始加上快捷键以做排序,节点路径结尾使用符号“-”结束
nodeName = IDNameMap.get(saveKey).toString();//根据key取得Name
key = nodeName.substring(0, 4) + "-" + key;
nodeName = nodeName.substring(4);
//最终得到nodeMap结果
if(count==0) nodeMap.put(key,nodeName);… …
}
}
catch (Exception ex) {… …
}
finally {
this.setMyDBDisconnect();
}
return nodeMap;
}
2.JSP頁面得到这个结果集,放入隐藏的下拉集合中,并调用JavaScript对这个下拉数据集进行处理。相关源代码如下:
<table width="100%" height="5%" border="0" style='BACKGROUND: #ACB8E8;' >
<tr><td align="left" >
<script language="javascript">
printNodeMenu();
</script>
</td> </tr> </table>
3.JavaScript对下拉控件数据集进行处理,生成页面代码并打印出来,最终展现成多级下拉菜单。算法源代码如下:
//根据节点数据集合打印出菜单
function printNodeMenu(){
var nodeIDs = document.all.nodeIDs;//节点路径以及节点名称的集合
var maxLen = nodeIDs.length;
var nodeID="",nodeName="",path="",isEnd="",text="";
var len=0;//节点路径长度
var firstNodeID = document.all.firstNodeID;//第二层节点路径以及节点名称的集合
var maxLen1 = firstNodeID.length;//第二层元素个数
//遍历打印出菜单页面元素
for(var i=0;i<maxLen;i++){
path = nodeIDs.options[i].value;//节点路径
nodeID = path.substring(5);//去除节点路径开始的快捷键
//打印第一层
if(nodeID.length==5){//确认为第一层节点ID
nodeName = nodeIDs.options[i].text;//第一位为叶子节点标识的节点名称
isEnd = nodeName.substring(0,1);//是否叶子节点
nodeName = nodeName.substring(1);//节点名称
if(isEnd=="0"){//第一层非叶子节点
text += "<p>"+nodeName+"</p>";
text += "… …";
document.writeln(text);//将第一层脚本生成的内容写在页面上
//再次遍历一次数据集判断是否有子节点
for(var i1=0;i1<maxLen1;i1++){
var path1 = firstNodeID.options[i1].value;//节点路径
var nodeID1 = path1.substring(5);//去除节点路径开始的快捷键
var text1 = "";
//打印第二层… …
}
}
}
else {//第一层叶子节点
text = "… …";
document.writeln(text);// 打印非叶子节点内容
}
}
}
window.parent.document.all.waiting.style.display='none';
}
【作者简介】范泽武,男,华南理工大学计算机软件学院 2005年秋季班在职软件工程硕士。
【关键词】Java;JSP;JavaScrip;多级下拉菜单;节点;数据集
【中图分类号】 TP311 【文献标识码】A
【文章编号】1671-5969(2007)21-0185-02
一、实现基本思想
为了减少Client端的数据处理时间,即客户登录时间,在服务器端除了取得所有菜单的基础数据集外,根据设计的算法,生成三个层次的节点ID,和节点名称构成的TreeMap类型的数据集合返回给JSP页面。
JSP将服务器返回的数据集,放入隐藏的下拉框控件中,并调用JavaScript脚本进行处理。对于这个特殊的结果数据集,根据一定的循环调用算法,生成JSP页面上显示的源代码,并打印出来,形成最终的下拉菜单结果。
二、关键算法简介
1.从数据库取得菜单数据集,生成可排序,并且包含菜单真正路径的数据集合的遍历算法简介:
步骤一:从数据库取得符合条件的以下字段的数据集:节点ID,节点名称,父节点ID,热键字符,快捷键,是否终结菜单。
步骤二:遍历初始数据集一次,将快捷键扩展为4位,节点ID扩展为5位,并将快捷键,是否终结菜单,节点名称合并在节点名称字段中。本次遍历目的是生成两个结果集:(节点ID,父节点ID)TreeMap结果集,以及(节点ID,节点名称)TreeMap结果集。
步骤三:遍历(节点ID,父节点ID)TreeMap结果集一次,以节点ID寻找到根节点ID的方式,获得节点ID路径,并划分节点ID所属的菜单层次,最终得到结果集第一层(节点ID,节点名称)TreeMap,第二层(节点ID,节点名称)TreeMap,第三层(节点ID,节点名称)TreeMap。其中节点ID是节点的完全路径,前缀是4位的快捷键,连接字符是“-”号。之所以前4加入扩展后的快捷键,是因为数据集返回到JSP页面时页面控件有自动排序的功能;节点名称的第一位是“是否终结菜单”字段,该字段用于判断叶子或非叶子菜单。
2.JSP页面保存从服务器传来的数据结果集,调用JavaScript脚本处理算法简介:
步骤一:设计菜单展开函数,作为下拉菜单的基础函数,在遍历菜单数据集时使用。设计菜单打开函数,有非叶子菜单函数nodeLeftMenu(A,B),叶子菜单函数nodeView(A,B,0)。
步骤二:定义N层数据集合,对应页面上的各层数组,定义各种基本元素,例如数组长度,名称,是否终结菜单等,与从服务器返回的数据集合相对应。
步骤三:遍历第一层,根据“是否终结菜单”判断是否有子菜单:如果有,继续第二层数组遍历;否则,打印该菜单页面代码。菜单项采用IFRAME的格式,确保菜单项的独立性,并且加入菜单项页面菜单调用函数,如果该菜单项也是非叶子菜单,则加入调用非叶子菜单函数nodeLeftMenu(A,B),如果该菜单项是叶子菜单则加入调用叶子菜单函数nodeView(A,B,0)。如果第二层菜单也是非叶子菜单,则继续遍历第三层,并判断菜单是否叶子菜单,按照上述处理方式调用nodeLeftMenu()或者nodeView()。最后,将页面代码打印处理。
三、优缺点分析
1.优点:可以充分利用服务器的快速处理能力,生成基础数据集合。可以让最终的结果集在客户端处理,减轻了服务器的处理负担。实践证明,只要JavaScript对结果集的处理算法得当,浏览器的解析处理时间就很快速。
2.缺点:当菜单越来越多,并且多到满屏的时候,这种方式实现的下拉菜单就会部分看不到。虽然可以采用展现滚动条方式实现,但又影响了页面美观。处于菜单展开区域的页面如果有类似下拉框控件等就会影响菜单的显示,这也是JSP页面Style方式的缺点。
四、实现源代码
1.服务器从数据库取得数据,生成结果集合,并返回这个集合给JSP页面。算法源代码如下:
//LOGIC处理结果集,关键算法
public TreeMap getNodeMap2(String userID,String roleID) {
TreeMap IDPreIDMap = new TreeMap();
——多层结构在这里定义
TreeMap nodeMap = new TreeMap();
try { String sql = "";
if(roleID.equals("")){
sql = "SELECT DISTINCT 受理目录标识… FROM … …";
}
this.setMyDB(1004, 1007);
ResultSet rs = myDB.executeQuery(sql);//总数据集
while (rs.next()) {
String nodeID = Integer.toString(rs.getInt("受理目录标识"));
… … //从数据库数据获取,并赋予定义的变量
IDPreIDMap.put(nodeID, preNodeID);//ID,preID集合
this.IDNameMap.put(nodeID,nodeName);//ID,Name集合
}
//对数据集遍历一次,取得所有节点路径,节点名称
Iterator keyItor = IDPreIDMap.keySet().iterator();
String key = "",preKey = "",saveKey = "",nodeName = "";
int count = 0,size = IDPreIDMap.size();
for(int i=0;i
preKey = IDPreIDMap.get(key).toString();//取得父节点ID
saveKey = key;//保存当前节点ID
count = 0;
//取得节点路径,使用符号-连接父子节点
while(!preKey.equals("0")){
}
//節点路径开始加上快捷键以做排序,节点路径结尾使用符号“-”结束
nodeName = IDNameMap.get(saveKey).toString();//根据key取得Name
key = nodeName.substring(0, 4) + "-" + key;
nodeName = nodeName.substring(4);
//最终得到nodeMap结果
if(count==0) nodeMap.put(key,nodeName);… …
}
}
catch (Exception ex) {… …
}
finally {
this.setMyDBDisconnect();
}
return nodeMap;
}
2.JSP頁面得到这个结果集,放入隐藏的下拉集合中,并调用JavaScript对这个下拉数据集进行处理。相关源代码如下:
<table width="100%" height="5%" border="0" style='BACKGROUND: #ACB8E8;' >
<tr><td align="left" >
<script language="javascript">
printNodeMenu();
</script>
</td> </tr> </table>
3.JavaScript对下拉控件数据集进行处理,生成页面代码并打印出来,最终展现成多级下拉菜单。算法源代码如下:
//根据节点数据集合打印出菜单
function printNodeMenu(){
var nodeIDs = document.all.nodeIDs;//节点路径以及节点名称的集合
var maxLen = nodeIDs.length;
var nodeID="",nodeName="",path="",isEnd="",text="";
var len=0;//节点路径长度
var firstNodeID = document.all.firstNodeID;//第二层节点路径以及节点名称的集合
var maxLen1 = firstNodeID.length;//第二层元素个数
//遍历打印出菜单页面元素
for(var i=0;i<maxLen;i++){
path = nodeIDs.options[i].value;//节点路径
nodeID = path.substring(5);//去除节点路径开始的快捷键
//打印第一层
if(nodeID.length==5){//确认为第一层节点ID
nodeName = nodeIDs.options[i].text;//第一位为叶子节点标识的节点名称
isEnd = nodeName.substring(0,1);//是否叶子节点
nodeName = nodeName.substring(1);//节点名称
if(isEnd=="0"){//第一层非叶子节点
text += "<p>"+nodeName+"</p>";
text += "… …";
document.writeln(text);//将第一层脚本生成的内容写在页面上
//再次遍历一次数据集判断是否有子节点
for(var i1=0;i1<maxLen1;i1++){
var path1 = firstNodeID.options[i1].value;//节点路径
var nodeID1 = path1.substring(5);//去除节点路径开始的快捷键
var text1 = "";
//打印第二层… …
}
}
}
else {//第一层叶子节点
text = "… …";
document.writeln(text);// 打印非叶子节点内容
}
}
}
window.parent.document.all.waiting.style.display='none';
}
【作者简介】范泽武,男,华南理工大学计算机软件学院 2005年秋季班在职软件工程硕士。