extjs4 tree oracle json

来源:互联网 发布:软件代理出口 编辑:程序博客网 时间:2024/05/17 04:40

用递归方式动态组建Extjs tree的JSON字符串

递归调用是一种强大的嵌套循环方式,它可以在递归过程中按照条件和参数完成其他循环语句无法完成的工作,比如动态组建有规律的字符串等。

最近在使用Extjs4做一个网站的后台管理系统,用户登录成功后,页面左边要显示一个该用户的可操作菜单列表,这里要用到Extjs tree组建来实现。tree组建支持同步和异步两种方式用JSON来组建树节点,对于多用户系统,每个用于的权限分配不一样,左边显示出来的可操作菜单也就不一样,这样一来,左边的树菜单节点只能动态加载了,也就是用Extjs的Ajax能力从服务器获得节点信息的JSON字符串来构建树菜单。

一个简单的Tree Node的JSON字符串:

?
1
2
[{"children":[{"children":[],"cls":"file","id":11,"leaf":true,"text":"子菜单1-1"},{"children":[],"cls":"file","id":12,"leaf":true,"text":"子菜单1-2"}],"cls":"folder","id":10,"leaf":false,"text":"二级菜单目录1"},{"children":[{"children":[],"cls":"file","id":21,"leaf":true,"text":"子菜单2-1"},{"children":[],"cls":"file","id":22,"leaf":true,"text":"子菜单2-2"}],"cls":"folder","id":20,"leaf":false,"text":"二级菜单目录2"}]

但是如果节点数据是从数据库里读取出来的,在java处理类里怎么去构建这个字符串呢?

这里,如果使用while或者for循环的方式,不可取,因为不知道节点的深度,要嵌套多少层。如果知道节点的深度并写死在处理类里,也降低了程序的智能化程度,一旦修改了节点数据,程序里也要做相应的修改,也不可取。

其实,办法总是有的,语言是无所不能的。在这里可以写一个递归方法,根据节点在数据库里的id标识获取其所有的下级节点组建JSON字符串并返回。

实现相关源码:

数据库tree节点数据(本设计考虑到其他比如JQuery、DTree等AJAX框架的兼容,树节点数据库表设计采用了通用的模式):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#菜单表
create table sys_menu
(
    menu_idint auto_incrementprimary key,             #菜单编号
    menu_titlevarchar(50) not null,                    #菜单文本
    menu_levelint not null,                    #菜单级别
    menu_superiorint default-1  not null,             #父菜单编号
    menu_urlvarchar(500) not null                 #指定URL
);
insert into sys_menu values(null,'系统管理',1,-1,'');
    insertinto sys_menu values(null,'用户管理',2,1,'mgr/pages/user_mgr.html');
    insertinto sys_menu values(null,'修改密码',2,1,'mgr/pages/pwd_modify.html');
    insertinto sys_menu values(null,'友情链接',2,1,'mgr/pages/link_mgr.html');
insert into sys_menu values(null,'业务管理',1,-1,'http://www.youdao.com');
    insertinto sys_menu values(null,'行业类别管理',2,5,'http://www.zhongsou.com');
    insertinto sys_menu values(null,'客户信息管理',2,5,'http://www.163.com');
    insertinto sys_menu values(null,'广告资费管理',2,5,'http://www.sina.com.cn');
    insertinto sys_menu values(null,'广告信息管理',2,5,'http://www.sohu.com');
    insertinto sys_menu values(null,'流量统计',2,5,'http://www.taobao.com');
    insertinto sys_menu values(null,'留言管理',2,5,'http://www.alibaba.cn');

tree菜单节点查询并组装成JSON字符串的java递归方法(类)源码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package util;
  
import java.util.Map;
import java.util.List;
import access.DB;
  
public class TreeBuild {
  
    privatestatic String buildTreeJSON(intnodeId,int c){
        Map<String, Object> node = DB.query("select * from sys_menu where menu_id="+nodeId).get(0);
  
        String ss ="";
  
        String sql ="select * from sys_menu where menu_superior="+nodeId;
        List<Map<String, Object>> nodes = DB.query(sql);
        if(nodes!=null&& nodes.size()>0){
  
            ss +="{\"children\":[";
            intcc = nodes.size();
            for(Map<String, Object> n:nodes){
                ss += buildTreeJSON(Integer.parseInt(n.get("menu_id").toString()),cc);
                cc--;
            }
  
            ss +="],\"cls\":\"folder\",\"id\":"+node.get("menu_id")+",\"leaf\":false,\"text\":\""+node.get("menu_title")+"\"}";
  
        }else{
            ss +="{\"children\":[],\"cls\":\"file\",\"id\":"+node.get("menu_id")+",\"leaf\":true,\"text\":\""+node.get("menu_title")+"\"}";
  
        }
  
        if(c>1){
            ss +=",";
        }
        returnss;
  
    }
  
    publicstatic String getTree(int[] par){
  
        String ss ="[";
        intc = par.length;
        for(intnodeId:par){
            ss+=buildTreeJSON(nodeId,c);
            c--;
        }
        String es ="]";
        returnss+es;
    }
  
}

 

调用时,调用本类的getTree方法,传入几个根节点的id标识,该方法会自动完成JSON字符串的最组装,并返回组装好的JSON字符串。Ext UI端直接用AJAX调用该JSON返回控制器URL即可。

另外一种很强大的方法(将Tree Node用Java对象封装起来,然后再将对象转换成JSON字符串,这种方式应该用得最多):

Ext4 + Servlet异步树形菜单
分类:Web前端技术    围观1474    评论 3    2012-02-12 20:39:00
ExtJS用的当前最新版:ext-4.0.7-gpl,现在实现了树形菜单展示功能,Ajax进行数据交互,异步加载子节点。

效果截图:



在线Demo:freedomsmile.net/Ext_Demo (打开有点慢,JS文件1MB多)

Google code svn:http://photon86.googlecode.com/svn/trunk

本例war包:  Ext_Demo    2.53MB  (运行环境:JRE1.6,Tomcat6)


下面贴出实现代码:
JAVASCRIPT代码
  1. /*********************************   Tree  Begin  ************************************/  
  2. var treeStore = Ext.create("Ext.data.TreeStore",{   
  3.     proxy : {   
  4.         type : "ajax",   
  5.         url : "BaseAction?method=getTreeData"  
  6.     },   
  7.     nodeParam : "id"    //设置传递给后台的参数名,值是树节点的id属性  
  8. });   
  9. Ext.create("Ext.tree.Panel", {   
  10.     renderTo: 'left',   
  11.     width: '100%',   
  12.     height: '100%',   
  13.     title : "开发技术",   
  14.     rootVisible : true//显示根节点  
  15.     root: {   
  16.         id: 'root',   
  17.         text: '根节点',   
  18.         expanded: false,   
  19.         leaf: false  
  20.     },   
  21.     viewConfig : {   
  22.         loadingText : "加载数据..."  
  23.     },   
  24.     store : treeStore   
  25. });   
  26. /****************************   Tree  End  ********************************/  



数据实体类(Technology.java):
JAVA代码
  1. package com.demo.entity;   
  2.   
  3. public class Technology{   
  4.   
  5.     private String id;  //主键ID  
  6.     private String name;    //技术名称  
  7.     private String pid;     //父ID  
  8.        
  9.     public String getId(){   
  10.         return id;   
  11.     }   
  12.     public void setId(String id){   
  13.         this.id = id;   
  14.     }   
  15.     public String getName(){   
  16.         return name;   
  17.     }   
  18.     public void setName(String name){   
  19.         this.name = name;   
  20.     }   
  21.     public String getPid(){   
  22.         return pid;   
  23.     }   
  24.     public void setPid(String pid){   
  25.         this.pid = pid;   
  26.     }   
  27.        
  28. }  



树节点实体对象(TreeNode.java),主要作用是简化前端Javascript编码,直接返回tree需要的数据格式,所以此类中定义的关键属性必须跟ExtJS API定义的一样,比如:id、text、leaf。如果是ajax异步加载数据,每次加载一级数据,则不需要递归,也就不需要属性:private List<TreeNode> children = new ArrayList<TreeNode>();,否则不显示加号,无法加载子节点。当某一级数据已经加载,第二次展开的时候不会重复请求后台,这点Ext做得好。
JAVA代码 复制代码
  1. package com.demo.entity;   
  2.   
  3. public class TreeNode{   
  4.     private String id;   
  5.     private String text;   
  6.     private Boolean leaf = true;    //是否子叶子节点,默认是  
  7.     private String cls;     //图标  
  8.     private String iconCls;   
  9.     private String action;  //请求路径  
  10.     private String model;   
  11.     private Boolean expanded;   //展开  
  12.     //private List<TreeNode> children = new ArrayList<TreeNode>();  
  13.        
  14.     public String getId(){   
  15.         return id;   
  16.     }   
  17.     public void setId(String id){   
  18.         this.id = id;   
  19.     }   
  20.        
  21.     public String getText(){   
  22.         return text;   
  23.     }   
  24.     public void setText(String text){   
  25.         this.text = text;   
  26.     }   
  27.        
  28.     public Boolean getLeaf(){   
  29.         return leaf;   
  30.     }   
  31.     public void setLeaf(Boolean leaf){   
  32.         this.leaf = leaf;   
  33.     }   
  34.        
  35.     public String getCls(){   
  36.         return cls;   
  37.     }   
  38.     public void setCls(String cls){   
  39.         this.cls = cls;   
  40.     }   
  41.        
  42.     public String getIconCls(){   
  43.         return iconCls;   
  44.     }   
  45.     public void setIconCls(String iconCls){   
  46.         this.iconCls = iconCls;   
  47.     }   
  48.        
  49.     public String getAction(){   
  50.         return action;   
  51.     }   
  52.     public void setAction(String action){   
  53.         this.action = action;   
  54.     }   
  55.        
  56.     public String getModel(){   
  57.         return model;   
  58.     }   
  59.     public void setModel(String model){   
  60.         this.model = model;   
  61.     }   
  62.        
  63.     public Boolean getExpanded(){   
  64.         return expanded;   
  65.     }   
  66.     public void setExpanded(Boolean expanded){   
  67.         this.expanded = expanded;   
  68.     }   
  69.        
  70. //  public List<TreeNode> getChildren(){  
  71. //      return children;  
  72. //  }   
  73. //  public void setChildren(List<TreeNode> children){  
  74. //      this.children = children;  
  75. //  }   
  76.        
  77. }  



测试数据(TreeAction.java),为简化操作,暂时未用数据库。大概想了下,如果用数据库,也是异步加载子节点,那最好在实体类Technology里封装一个 leaf 属性,代表此Technology是否为叶子节点,这样的好处是封装TreeNode对象的时候方便判断 leaf 的值,少查询一次数据库,但记得每次修改节点的时候同时更新 leaf 。
JAVA代码
  1. package com.demo.action;   
  2.   
  3. import java.io.PrintWriter;   
  4. import java.util.ArrayList;   
  5. import java.util.List;   
  6.   
  7. import javax.servlet.http.HttpServletRequest;   
  8. import javax.servlet.http.HttpServletResponse;   
  9.   
  10. import com.demo.entity.Technology;   
  11. import com.demo.entity.TreeNode;   
  12.   
  13. import net.sf.json.JSONArray;   
  14.   
  15. @SuppressWarnings("unchecked")   
  16. public class TreeAction{   
  17.   
  18.     public void getTreeData(HttpServletRequest request, HttpServletResponse response){   
  19.         try{   
  20.             String id = request.getParameter("id");   
  21.             //System.out.println("父节点ID:" + id);  
  22.                
  23.             List<Technology> list = TreeData();   
  24.             List<TreeNode> tn = new ArrayList<TreeNode>();   
  25.             if(id == null || id.equals("root")){   
  26.                 for(Technology t : list){   
  27.                     if(t.getPid().equals("0")){   
  28.                         TreeNode treeNode = new TreeNode();   
  29.                         treeNode.setId(t.getId());   
  30.                         treeNode.setText(t.getName());   
  31.                         treeNode.setLeaf(false);   
  32.                         tn.add(treeNode);   
  33.                     }   
  34.                 }   
  35.             }else{   
  36.                 for(Technology t : list){   
  37.                     if(t.getPid().equals(id)){   
  38.                         TreeNode treeNode = new TreeNode();   
  39.                         treeNode.setId(t.getId());   
  40.                         treeNode.setText(t.getName());   
  41.                         tn.add(treeNode);   
  42.                         for(Technology te : list){   
  43.                             if(t.getId().equals(te.getPid())){   
  44.                                 treeNode.setLeaf(false);   
  45.                             }   
  46.                         }   
  47.                     }   
  48.                 }   
  49.             }   
  50.   
  51.             JSONArray ja = JSONArray.fromObject(tn);   
  52.             //System.out.println(ja);  
  53.             PrintWriter out = response.getWriter();   
  54.             out.print(ja.toString());   
  55.         }catch(Exception e){   
  56.             e.printStackTrace();   
  57.         }   
  58.     }   
  59.        
  60.     public List<Technology> TreeData(){   
  61.         List<Technology> list = new ArrayList<Technology>();   
  62.         Technology t1 = new Technology();   
  63.         t1.setId("1");   
  64.         t1.setName("前端");   
  65.         t1.setPid("0");   
  66.         list.add(t1);   
  67.   
  68.         Technology t2 = new Technology();   
  69.         t2.setId("2");   
  70.         t2.setName("后端");   
  71.         t2.setPid("0");   
  72.         list.add(t2);   
  73.   
  74.         Technology t3 = new Technology();   
  75.         t3.setId("3");   
  76.         t3.setName("C");   
  77.         t3.setPid("2");   
  78.         list.add(t3);   
  79.   
  80.         Technology t4 = new Technology();   
  81.         t4.setId("4");   
  82.         t4.setName("C#");   
  83.         t4.setPid("2");   
  84.         list.add(t4);   
  85.   
  86.         Technology t5 = new Technology();   
  87.         t5.setId("5");   
  88.         t5.setName("Java");   
  89.         t5.setPid("2");   
  90.         list.add(t5);   
  91.   
  92.         Technology t6 = new Technology();   
  93.         t6.setId("6");   
  94.         t6.setName("PHP");   
  95.         t6.setPid("2");   
  96.         list.add(t6);   
  97.   
  98.         Technology t7 = new Technology();   
  99.         t7.setId("7");   
  100.         t7.setName("Servlet");   
  101.         t7.setPid("5");   
  102.         list.add(t7);   
  103.   
  104.         Technology t8 = new Technology();   
  105.         t8.setId("8");   
  106.         t8.setName("JSP");   
  107.         t8.setPid("5");   
  108.         list.add(t8);   
  109.   
  110.         Technology t9 = new Technology();   
  111.         t9.setId("9");   
  112.         t9.setName("Struts");   
  113.         t9.setPid("5");   
  114.         list.add(t9);   
  115.   
  116.         Technology t10 = new Technology();   
  117.         t10.setId("10");   
  118.         t10.setName("Spring");   
  119.         t10.setPid("5");   
  120.         list.add(t10);   
  121.   
  122.         Technology t11 = new Technology();   
  123.         t11.setId("11");   
  124.         t11.setName("Hibernate");   
  125.         t11.setPid("5");   
  126.         list.add(t11);   
  127.   
  128.         Technology t12 = new Technology();   
  129.         t12.setId("12");   
  130.         t12.setName("HTML");   
  131.         t12.setPid("1");   
  132.         list.add(t12);   
  133.   
  134.         Technology t13 = new Technology();   
  135.         t13.setId("13");   
  136.         t13.setName("JavaScript");   
  137.         t13.setPid("1");   
  138.         list.add(t13);   
  139.   
  140.         Technology t14 = new Technology();   
  141.         t14.setId("14");   
  142.         t14.setName("CSS");   
  143.         t14.setPid("1");   
  144.         list.add(t14);   
  145.            
  146.         Technology t15 = new Technology();   
  147.         t15.setId("15");   
  148.         t15.setName("Session");   
  149.         t15.setPid("11");   
  150.         list.add(t15);   
  151.            
  152.         Technology t16 = new Technology();   
  153.         t16.setId("16");   
  154.         t16.setName("SessionFactory");   
  155.         t16.setPid("11");   
  156.         list.add(t16);   
  157.            
  158.         Technology t17 = new Technology();   
  159.         t17.setId("17");   
  160.         t17.setName("Transaction");   
  161.         t17.setPid("11");   
  162.         list.add(t17);   
  163.            
  164.         Technology t18 = new Technology();   
  165.         t18.setId("18");   
  166.         t18.setName("Query");   
  167.         t18.setPid("11");   
  168.         list.add(t18);   
  169.            
  170.         Technology t19 = new Technology();   
  171.         t19.setId("19");   
  172.         t19.setName("Criteria");   
  173.         t19.setPid("11");   
  174.         list.add(t19);   
  175.            
  176.         Technology t20 = new Technology();   
  177.         t20.setId("20");   
  178.         t20.setName("Configuration");   
  179.         t20.setPid("11");   
  180.         list.add(t20);   
  181.            
  182.         return list;   
  183.     }   
  184.   
  185. }  



servlet(BaseAction.java),负责跳转,调用对应方法:
JAVA代码 复制代码
  1. package com.demo.action;   
  2.   
  3. import java.io.IOException;   
  4.   
  5. import javax.servlet.ServletException;   
  6. import javax.servlet.http.HttpServlet;   
  7. import javax.servlet.http.HttpServletRequest;   
  8. import javax.servlet.http.HttpServletResponse;   
  9.   
  10. import com.demo.action.GridAction;   
  11. import com.demo.action.TreeAction;   
  12.   
  13. @SuppressWarnings("unchecked")   
  14. public class BaseAction extends HttpServlet{   
  15.   
  16.     private static final long serialVersionUID = 1L;   
  17.        
  18.     public BaseAction(){   
  19.         super();   
  20.     }   
  21.     public void destroy(){   
  22.         super.destroy();   
  23.     }   
  24.     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{   
  25.         response.setContentType("text/html;charset=utf-8");   
  26.            
  27.         GridAction ga = new GridAction();   
  28.         TreeAction ta = new TreeAction();   
  29.            
  30.         String method = request.getParameter("method");   
  31.         if(method != null){   
  32.             if(method.equals("getGridData")){   
  33.                 ga.getGridData(request, response);   
  34.             }else if(method.equals("getTreeData")){   
  35.                 ta.getTreeData(request, response);   
  36.             }else{   
  37.                 //404  
  38.             }   
  39.         }else{   
  40.             //404  
  41.         }   
  42.     }   
  43.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{   
  44.         doGet(request, response);   
  45.     }   
  46.     public void init() throws ServletException{}   
  47. }  



Tree所需JSON数组格式:
JSON代码 复制代码
  1. [   
  2.     {   
  3.         "action""",   
  4.         "cls""",   
  5.         "expanded": false,   
  6.         "iconCls""",   
  7.         "id""1",   
  8.         "leaf": false,   
  9.         "model""",   
  10.         "text""前端"  
  11.     },   
  12.     {   
  13.         "action""",   
  14.         "cls""",   
  15.         "expanded": false,   
  16.         "iconCls""",   
  17.         "id""2",   
  18.         "leaf": false,   
  19.         "model""",   
  20.         "text""后端"  
  21.     }   

 

原创粉丝点击