树形菜单

转载 2007年09月30日 14:59:00
树形菜单一
大家知道,树型菜单在应用中有着十分广泛的用途。实现树型菜单的途径较多,本文介绍的一种觉得理解起来比较直观,与上篇文章的方法比较类似:就是将树型菜单的节点保存在数据库表中(当然,在实际项目中,节点的信息往往并不是放在一个单一的表中的。比如:在一个权限管理系统中,这些信息可能分别放在用户表、角色表、功能表等表中,只要设法让查询出来的结果与下面给出的表格的内容相似就可以了。只要稍微有些数据库方面的知识做到这点并不难,详细的实现细节超出了本文的主题,不在此细说)。通过数据访问对象将其从数据库中查出后放在一个集合对象中,并将该集合对象传递给客户端,再用一段现存的JavaScript 代码--dtree(一个免费的JavaScript程序)来操作集合中的数据。大方向确定之后,我们就来具体着手来实现它。

    根据dtree的要求,我们来建一个数据库表来存储树的节点信息,表名为functions,其结构如下:

id字段:varchar 10 主键--节点标识码
pid字段:varchar 10 not null--父节点标识码
name字段:varchar 20 not null
url字段:varchar 50 not
null--这个字段存储的是点击该节点时,要定位的资源(比如一个页面的url),
为了不使本文的篇幅过长,暂时不给出相应的页面,
您可以随便输入一个字母比如:a,以使本例能够正常运行。
title字段:varchar 20
target字段:varchar 10
icon字段:varchar 20
iconopen字段:varchar 20
opened字段:char 1



    在表中输入如下一些记录以供后面的实验用:

0、-1、我的权限、javascript: void(0);
00、0、用户管理、javascript: void(0);
0001、00、创建新用户;
0002、00、删除用户;
01、0、    文章管理、javascript: void(0);
0101、01、添加新文章;
0102、01、修改文章;
0103、01、删除文章;



    到此,数据库方面的准备工作就告一段落。

    接下来的工作我们仍然在先前介绍的mystruts项目中进行。先编写一个名为:FunctionsForm的ActionForm,其代码如下:

package entity;
import org.apache.struts.action.*;
import javax.servlet.http.*;

public class FunctionsForm extends ActionForm {
  private String icon;
  private String iconOpen;
  private String id;
  private String name;
  private String opened;
  private String pid;
  private String target;
  private String title;
  private String url;
  public String getIcon() {
    return icon;
  }
  public void setIcon(String icon) {
    this.icon = icon;
  }
  public String getIconOpen() {
    return iconOpen;
  }
  public void setIconOpen(String iconOpen) {
    this.iconOpen = iconOpen;
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getOpened() {
    return opened;
  }
  public void setOpened(String opened) {
    this.opened = opened;
  }
  public String getPid() {
    return pid;
  }
  public void setPid(String pid) {
    this.pid = pid;
  }
  public String getTarget() {
    return target;
  }
  public void setTarget(String target) {
    this.target = target;
  }
  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }
  public String getUrl() {
    return url;
  }
  public void setUrl(String url) {
    this.url = url;
  }
}



    因为我们的树型节点的数据都存储在数据库表中,接下来,要做一个数据访问对象类,名称为:FunctionsDao.java,其代码如下:

package db;
import java.sql.*;
import java.util.*;
import entity.FunctionsForm;

public class FunctionsDao {
  private static Connection con = null;

  public FunctionsDao(Connection con) {
    this.con=con;
  }

  public static Collection findTree() {
    PreparedStatement ps=null;
    ResultSet rs = null;
    ArrayList list=new ArrayList();

    String sql="select * from functions";

    try{
      if(con.isClosed()){
        throw new IllegalStateException("error.unexpected");

      }
      ps=con.prepareStatement(sql);

      rs=ps.executeQuery();
      while(rs.next()){
        FunctionsForm functionsForm=new FunctionsForm();
        functionsForm.setId(rs.getString("id"));
        functionsForm.setPid(rs.getString("pid"));
        functionsForm.setName(rs.getString("name"));
        functionsForm.setUrl(rs.getString("url"));
        functionsForm.setTitle(rs.getString("title"));
        functionsForm.setTarget(rs.getString("target"));
        functionsForm.setIcon(rs.getString("icon"));
        functionsForm.setIconOpen(rs.getString("iconOpen"));
        functionsForm.setOpened(rs.getString("opened"));
        list.add(functionsForm);

      }
      return list;
    }
    catch(SQLException e){
        e.printStackTrace();
        throw new RuntimeException("error.unexpected");
    }
    finally{
      try{
        if(ps!=null)
          ps.close();
        if(rs!=null)
          rs.close();
      }catch(SQLException e){
        e.printStackTrace();
        throw new RuntimeException("error.unexpected");
      }
    }
  }
}



     这里值得注意的是:在以往我们见到的一些显示树型菜单的程序,如:一些asp程序中往往简单地采用递归调用的方法来查找到树的各个节点。这对那些树的深度不确定的场合还是有些用处,但这种处理方法也有一个致命的弱点,那就是反复地进行数据库查询,对一些节点较多的应用,对应用程序性能的影响是非常大的,有时会慢得让人难以接受;而在实际的应用中大多数情况下树的深度往往是有限的,如:用于会计科目的树一般最多也在六层以下。又如:用作网页功能菜单的情况,网页设计的原则就有一条是:达到最终目的地,鼠标点击次数最好不要多于三次。因此,在实际设计存储树型结构的表时要考虑查询的效率。对能确定树的最大深度的情况下,要设法尽量优化查询语句,减少查询次数,以提高应用程序的性能同时减少数据库的负荷。

    本例对应的Action的名称为FunctionsAction,其代码如下:

package action;

import entity.*;
import org.apache.struts.action.*;
import javax.servlet.http.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import db.FunctionsDao;

public class FunctionsAction extends Action {
  public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm,
  HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
  {
    DataSource dataSource;
    Connection cnn=null;
    ActionErrors errors=new ActionErrors();
    try{
      dataSource = getDataSource(httpServletRequest,"A");
      cnn = dataSource.getConnection();
      FunctionsDao functionsDao=new FunctionsDao(cnn);
      Collection col=functionsDao.findTree();
      httpServletRequest.setAttribute("treeList",col);

      return actionMapping.findForward("success");
    }
    catch(Throwable e){
      e.printStackTrace();
      //throw new RuntimeException("未能与数据库连接");
      ActionError error=new ActionError(e.getMessage());
      errors.add(ActionErrors.GLOBAL_ERROR,error);
    }
    finally{
      try{
        if(cnn!=null)
          cnn.close();
      }
      catch(SQLException e){
        throw new RuntimeException(e.getMessage());
      }
    }
    saveErrors(httpServletRequest,errors);
    return actionMapping.findForward("fail");
  }
}



    在struts-config.xml文件中加入如下内容:

<form-beans>   
    <form-bean name="functionsForm" type="entity.FunctionsForm" />
  </form-beans>
<action-mappings>
    <action name="functionsForm" path="/functionsAction" scope="request"
    type="action.FunctionsAction" validate="false" >
<forward name="success" path="/testDTree.jsp" />
<forward name="fail" path="/genericError.jsp" />
    </action>
  </action-mappings>



    为了对应配置中的,我们还要提供一个显示错误信息的jsp页面,其代码如下:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>
genericError
</title>
<link href="css/mycss.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#ffffff">
<html:errors/>
</body>
</html>



    下面,我们来看一下我们显示树型菜单的页面代码,从配置中可以看出,页面的名称为testDTree.jsp,代码如下:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
<head>
<title>
testDTree
</title>
<link rel="StyleSheet" href="css/dtree.css" type="text/css" />
</head>
<body bgcolor="#eeeeee">
<body leftmargin="0" topmargin="0"><table width="180">
<tr><td height="300" valign="top" nowrap>
<script type="text/javascript" src="js/dtree.js"></script>
<script type='text/javascript'>
tree = new dTree('tree');
tree.config.folderLinks=false;
tree.config.useCookies=false;
<logic:iterate id="functionsForm" name="treeList" scope="request"
type="entity.FunctionsForm">
    tree.add("<bean:write name="functionsForm" property="id"/>","<bean:write
    name="functionsForm" property="pid"/>","<bean:write name="functionsForm"
    property="name"/>","<bean:write name="functionsForm"
    property="url"/>","<bean:write name="functionsForm"
    property="title"/>","<bean:write name="functionsForm"
    property="target"/>","<bean:write name="functionsForm" property="icon"/>");
</logic:iterate>
      document.write(tree);
</script>
    </td>
  </tr>
</table>
</body>
</html>



    从 可以看出,我们要在mystruts目录下,建一个名为js的目录,并将下载的dtree文件dtree.js放在该目录中。

    再在mystruts目录下分别建一个名为img和名为css的目录,将dtree中用到的图标和层叠样式表单文件分别放在相应的目录中。

    有关dtree的使用方法,详见其说明文档,如:api.html。笔者在此要感谢dtree的作者为我们提供了一个结构如此清晰的javascript程序!

    现在,可以编译执行这个例子程序了,编译后在浏览器中输入:http://127.0.0.1:8080/mystruts/functionsAction.do就可以看到运行效果。效果图为:

点击在新窗口中打开图片

    注:dtree的下载地址为: http://www.destroydrop.com/javascripts/tree/

网页树形菜单

  • 2016年06月23日 18:58
  • 3KB
  • 下载

树形菜单treeview

  • 2015年11月20日 10:50
  • 1KB
  • 下载

前端框架 (一)zTree 从数据库中动态加载树形菜单

这几天做动态菜单用到了这个插件,目前用的很广泛的一个开源框架,最新发布的QUI框架就是用这个插件开发的菜单部分,因此还是很值得深入研究和学习,通过使用感觉功能很丰富,好多函数不用自己开发和编写,官网上...

多种树形菜单

  • 2014年06月11日 15:23
  • 3.7MB
  • 下载

树形菜单应用

  • 2014年02月26日 19:21
  • 2KB
  • 下载

轻松学习jQuery插件EasyUI EasyUI创建树形菜单

一、EasyUI使用标记创建树形菜单 一个树形菜单(Tree)可以从标记创建。easyui 树形菜单(Tree)也可以定义在 元素中。无序列表的 元素提供一个基础的树(Tree)结构。每一个 ...

一个js树形菜单

  • 2013年04月18日 16:29
  • 13KB
  • 下载

级联树形菜单

  • 2014年08月26日 14:36
  • 1.45MB
  • 下载

extjs springMVC实现动态树形菜单

最近由于项目需要,做一个树形动态菜单,用extjs3 来做,结合springMVC,实现从后台动态的加载数据形成权限菜单。 一、数据表设计 首先是数据库的设计,数据库表是一张权限表(即菜单表),我把它...

Bootstrap树形菜单JS代码特效

  • 2015年02月11日 14:58
  • 61KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:树形菜单
举报原因:
原因补充:

(最多只允许输入30个字)