« 上一篇: select下拉菜单的实现 下一篇: 人言可畏 »
黄毛丫头 @ 2008-09-18 14:21

将树型菜单的节点保存在数据库表中(当然,在实际项目中,节点的信息往往并不是放在一个单一的表中的。比如:在一个权限管理系统中,这些信息可能分别放在用户表、角色表、功能表等表中,只要设法让查询出来的结果与下面给出的表格的内容相似就可以了。只要稍微有些数据库方面的知识做到这点并不难,详细的实现细节超出了本文的主题,不在此细说)。通过数据访问对象将其从数据库中查出后放在一个集合对象中,并将该集合对象传递给客户端,再用一段现存的JavaScript代码--dtree(一个免费的JavaScript程序)来操作集合中的数据。
1、根据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















2、 在表中输入如下一些记录以供后面的实验用:
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、删除文章;

 







到此,数据库方面的准备工作就告一段落。
3、接下来的工作我们仍然在先前介绍的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;
    }
}

     
























































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

     







































6、在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>

     












7、为了对应配置中的,我们还要提供一个显示错误信息的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>

     










8、下面,我们来看一下我们显示树型菜单的页面代码,从配置中可以看出,页面的名称为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" 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>


































9、从上图可以看出,我们要在mystruts目录下,建一个名为js的目录,并将下载的dtree文件dtree.js放在该目录中。
再在mystruts目录下分别建一个名为img和名为css的目录,将dtree中用到的图标和层叠样式表单文件分别放在相应的目录中。(有关dtree的使用方法,详见其说明文档,如:api.html。笔者在此要感谢dtree的作者为我们提供了一个结构如此清晰的javascript程序!)
10、现在,可以编译执行这个例子程序了,编译后在浏览器中输入:http://127.0.0.1:8080/mystruts/functionsAction.do就可以看到运行效果。效果图为:

 

     
注:dtree的下载地址为: http://www.destroydrop.com/javascripts/tree/
转自http://hi.baidu.com/china8jie/blog/item/977fa3b75fae00f030add16a.html



曾经的这一天...



评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定