<绪-自从一群牛人整出Ext这个框架之后,WEB世界就变得更加完美,特别是对追求唯美而却没有多少美术细胞的WEB程序员而言,Ext的出现弥补了他们这方面的缺陷,因为从此以后大多数的美工他们可以用程序来实现,插上了Ext的翅膀,摇身一变,突然你会发现他们居然真的一个个美感十足>
       
下面我们我们以Microsoft SQLServer2000为后台数据库,结合Jsp和Ext来用递归来实现无限级菜单树的生成。
 
1,数据库结构,后面的节点生成树依据此表生成
 
CREATE TABLE [dbo].[tree] (
    [intId] [ int] IDENTITY (1, 1) NOT NULL , --节点ID
    [intParentId] [ int] NOT NULL , --父节点ID
    [strText] [ varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL , --节点名称
    [strLink] [ varchar] (200) COLLATE Chinese_PRC_CI_AS NULL , --
节点链接的URL
    [strTips] [ varchar] (250) COLLATE Chinese_PRC_CI_AS NULL , --节点提示说明
    [strTargetForm] [ varchar] (50) COLLATE Chinese_PRC_CI_AS NULL --节点目标Frame
) ON [ PRIMARY]
 
2,数据库连接类dbCon,本来是用连接池实现数据库连接,为方便起见,临时写了一个连接类,只用到一个查询功能
package sqlDBconnect;
import java.sql.*;

public class dbCon {
   private Connection con;
   private Statement st;
   private ResultSet rs;
   private String host= "192.168.39.62";
   private String user= "test";
   private String pw= "test";
   private String db= null;
   private String Dri= "com.microsoft.jdbc.sqlserver.SQLServerDriver";
   private String url= null;
    
   public ResultSet query(String sql,String dbName, int ResultSetType, int ResultSetCursor) throws Exception{
       try{
        db=dbName;
        url= "jdbc:microsoft:sqlserver://" +host+ ":1433;DatabaseName="+db;
          Class.forName(Dri).newInstance();
          con=DriverManager.getConnection(url,user,pw);
          st=con.createStatement(ResultSetType,ResultSetCursor);
          rs=st.executeQuery(sql);
          return rs;
       }catch(SQLException e){
          System.out.print(e.getMessage());
          return null;
       }
   }      
    
   public void close(){//关闭连接
       try{
           if(rs!=null)rs.close();
       }catch(Exception e){
           System.out.print("rs"+e.getMessage());
       }
       try{
           if(st!=null)st.close();
       }catch(Exception e){
           System.out.print("st"+e.getMessage());
       }

       try{
           if(con!=null)con.close();
       }catch(Exception e){
           System.out.print("con"+e.getMessage());
       }
   }    
}
 
3,节点类Nodes
/**
* @author victor.wen
* @time  2008-3-12  上午09:25:59
* @function 根据节点ID返回以该节点为根节点的树,返回值为JSON格式的字符串

*/


package javaBeans;

import java.sql.ResultSet;
import java.sql.SQLException;
import sqlDBconnect.dbCon;

public class Nodes{
  
     /*
  * 该函数根据指定的ID值返回以该ID为根节点的树,应该返回类似的JSON格式,注,不含最外层的[]
  {
    id: 1,
    text: 'A leaf Node',
    leaf: true
    },{
    id: 2,
    text: 'A folder Node',
    children: [
  {
        id: 3,
        text: 'A child Node',
        leaf: true
  }
    ]
    }
  */

     public static String getResultByRootId( int rootId) throws SQLException,Exception{
  dbCon dbConnect  = new dbCon();
  String result="";
   //查看该节点的相关信息
  String strSql= "select * from tree where intId="+rootId;
  ResultSet rs=dbConnect.query(strSql, "bpdb",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
  String    strText="";
  String  strLink="";
  String  strTips="";
  String  strTargetForm="";
   if(rs.next()){
      strText=rs.getString( "strText");
      strLink=rs.getString( "strLink");
      strTips=rs.getString( "strTips");
      strTargetForm=rs.getString( "strTargetForm");
  } else
       return result;
  
   //首先查看该节点是否为叶子节点
  strSql= "select * from tree where intParentId="+rootId;
  ResultSet rs1=dbConnect.query(strSql, "bpdb",ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
   if(rs1.next()){ //该节点不为叶子节点,即其下有子节点
      result= "{"
    + "id:"+rootId+ ","
    + "text:'"+strText+ "',"
    + "qtip:'"+strTips+ "',"
    + "children:";
    
      rs1.last();
       int rowCounts=rs1.getRow(); //记录数
      rs1.beforeFirst();
    
       while(rs1.next()){
     int intChildId=rs1.getInt( "intId");
     if(rowCounts==1)  
        result=result+ "["+getResultByRootId(intChildId)+ "]";
     else if(rowCounts>1){
         if(rs1.getRow()==rowCounts)
      result=result+getResultByRootId(intChildId)+ "]";
         else if(rs1.getRow()==1)
      result=result+ "["+getResultByRootId(intChildId)+ ",";
         else
      result=result+getResultByRootId(intChildId)+ ",";      
    }
      }
    
      result=result+ "}";

    
  } else{ //该节点为叶子节点

      result= "{"
    + "id:"+rootId+ ","
    + "text:'"+strText+ "',"
    + "hrefTarget:'"+strTargetForm+ "',"
    + "href:'"+strLink+ "',"
    + "qtip:'"+strTips+ "',"
    + "leaf: true"
    + "}";  

    
  }
  
  dbConnect.close();
   return result;  
    }
  
    }
 
4,页面输出文件Nodes.jsp,调用生成树节点实用类Nodes
说明:根据不同的需要可以传入不用的节点ID来显示不同的树,如果能和权限管控结合在一起就可以做到不同权限的人只能看到属于他权限范围内的树,项目中这个功能我已实现,效果还不错,实现起来也不难,读者不防自己动手试一下。
<%@page  contentType= "text/html; charset=GB2312" language= "java" import= "javaBeans.Nodes" errorPage="" %>
<%
//现指定节点ID为1,即显示以1为根节点的树,注意最后显示时加上最外层[]
String tempResponse= new String(Nodes.getResultByRootId(1).getBytes( "ISO-8859-1"), "GBK");
out.print( "["+tempResponse+ "]");
%>
 
5,显示树的JS文件treeview.js
说明:本来是想用servlet来作输出以传给dataurl属性来生成树,可折腾了好半天后发现
dataurl属性好像不支持servlet,压根访问不到所写的servlet,更谈不上response回值,无奈之余只有用jsp来作输出,不排除我技术不到家或方法有误,毕竟Ext2.0我也没研究过多久,如果有哪位读者朋友有办法做到的话,不妨拿出来大家分享一下,这里不胜感激!
/*
** Ext TreeView function
** By victor.wen
** 2008-03-12
*/


Ext.onReady( function(E){
    Ext.BLANK_IMAGE_URL ='ext2.0/p_w_picpaths/ default/s.gif';
    Ext.QuickTips.init();

     var tree = new Ext.tree.TreePanel({
  el : document.body,
  border: false,
  rootVisible: false,
    useArrows: true,
    autoScroll: true,
    animate: true,
    enableDD: true,
    containerScroll: true,  
  loader : new Ext.tree.TreeLoader({
      dataUrl :'Nodes.jsp'
  })
    });

     var root = new Ext.tree.AsyncTreeNode({
  text :'导航栏',
   //enableDD : false,
  id : '0'
    });
    tree.setRootNode(root);
    tree.render();
    root.expand( true, false);
});
 
6,最后一步,整合前面的,用Ext2.0给我们种树,以此作为植树节的礼物
<%@page  contentType= "text/html; charset=GB2312" language= "java" import= "" errorPage="" %>
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=GB2312">
<title>献给植树节的礼物</title>

<link rel= "stylesheet" type= "text/css" href= "ext2.0/css/ext-all.css" />
<script type= "text/javascript" src= "ext2.0/js/ext-base.js"></script>
<script type= "text/javascript" src= "ext2.0/js/ext-all.js"></script>
<script type= "text/javascript" language= "JavaScript" src= "ext2.0/js/treeview.js"></script>

</head>
<body height= "300">
</body>  
</html>
 
OKOK,终于讲完了,最后要提醒一点的是,要保证上面所述例子能够成功,你要注意两点:
    1,正确配置好Tomcat服务器,我用的是这个,你也可以按照需要配置别的服务器.
 2,数据库正确配置,这个应该不用我多说了
 3,搭建好Ext2.0框架,上面例子中,比如应用是examples,我的Ext2.0框架目录是这样的,
examples\ext2.0 下面分别就是框架中的css,p_w_picpath和js目录