`
donnki
  • 浏览: 45271 次
  • 性别: Icon_minigender_1
  • 来自: 火星
文章分类
社区版块
存档分类
最新评论

个人还比较满意的一段代码:EXTJS排序树,只访问一次数据库即可得到整个树结构

阅读更多
项目有个需求需要写个类似 windows资源管理器的树结构。
一开始想偷懒到网上随便找段代码,可是找下来看了半天还没看懂。要是去一行一行的读源码去理解的话,就违背了偷懒的初衷,而且估计都满足不了需求~~于是DIY一个。
需求:
1)减轻数据库压力,访问一次数据库(只执行一条select * from 表名)便要读出所有树结构;
2)排序,目录要优先于结点显示在树形结构中,同级同种结点排序按填入的排序号大小来排序
3)有个界面可以随时增加、编辑、删除树的结点或目录。

于是花了一天时间把这个搞定了~~自我感觉还比较满意,因此把关键的代码贴上来共享下,有兴趣有经验的朋友请多教。

效果如下:



环境:webwork/spring/hibernate/extjs-json-tree

数据库表:
mid number          Not null 目录id,编号,唯一
mname varchar2(30) Not null 目录名
pid number    Not null 父目录id,顶级目录默认为0
pname String(30) 父目录名称
mtype char 是目录还是结点,'dir' or 'rpt'
leveidx number    同级目录中的排列顺序
state String(10) (一个业务字段,无关紧要)
reptid String(30) (一个业务字段,无关紧要)
bz String(100) (一个业务字段,无关紧要)

HibernateSynchronizer生成hbm.xml、DAO、pojo
web.xml中增加spring监听器将DAO自动注入至webwork的action
“界面可以随时增加、编辑、删除树的结点或目录”。就是一个普通的crud操作,地球人都会写,代码忽略。

EXTJS呈现,代码很短,就是请求一个action,返回一串json并解析该JSON为一棵树,不是关键,可以忽略。也将代码贴出来吧,AJAX请求的地址是sysrMenutreeAction!gettree.action
Ext.onReady(function(){
	var loader = new Ext.tree.TreeLoader({url:"sysrMenutreeAction!gettree.action"});
	loader.processResponse = function(response, node, callback){
		var json = response.responseText;
		try{
			var json = eval("(" + json + ")");
			node.beginUpdate();
					
			var o = json["key"];
			for(var i=0, len=o.length; i<len; i++){
				var n = this.createNode(o[i]);
				if(n){
					node.appendChild(n);
				}
			}
			node.endUpdate();
			if(typeof callback == "function"){
				callback(this,node);
			}
		}catch(e){
			this.handleFailure(response);
		}
	}
	var tree = new Ext.tree.TreePanel({
		el : 'tree',
		loader : loader,				
		border :false
	});
	var root = new Ext.tree.AsyncTreeNode({
		id : '1',
		text : "根结点"
	});
	tree.setRootNode(root);
	tree.on("click", function(node){
		top.mainFrame.location = "sysrMenutreeAction!getnode.action?node=" + node.id;		//在主frame中显示结点的具体信息
	});
	tree.render();
			
});


上面请求的sysrMenutreeAction!gettree.action,在对应的action中对应的gettree()方法如下:
public String gettree() {
	List<SysrMenutree> list = sysrMenutreeDAO.getSession()
			.createQuery("from SysrMenutree ").list();		//执行查询,取得所有记录
	Map<Integer, SysrMenutree> map = new HashMap<Integer, SysrMenutree>();
	
	SysrMenutree root = null;		//根结点
	for (SysrMenutree treeNode : list) {	//第一次循环,将结果集放到一个"Map键-值对"结构中,方便取出指定元素
		map.put(treeNode.getId(), treeNode);
		if(treeNode.getPid() == 0){
			root = treeNode;
		}
	}
	
	/*
	第二次循环所有结点,将每个结点的子结点存入一个TreeSet中。
	使用TreeSet比较关键,我的排序的代码全写在这个TreeSet的Comparator中,见下文
	*/
	for(SysrMenutree treeNode : list){	
		if(treeNode.getPid() != 0){		
			map.get(treeNode.getPid()).addChild(treeNode);
		}
	}

	System.out.println(root.toJsonString());
	HttpServletResponse response = ServletActionContext.getResponse();
	response.setContentType("application/x-json;charset=utf-8");
	try {
		PrintWriter out = response.getWriter();
		if(root != null){
			out.write("{key:[" + root.toJsonString() + "]}");		//向客户端写json。递归方法toJsonString()
		}
		out.flush();
	} catch (IOException e) {	
		e.printStackTrace();
	}
	return NONE;
}


关键的代码在pojo对象SysrMenutree中。如下:
public class SysrMenutree  implements Comparable<SysrMenutree> {
	//实现了Comparable接口
		
	/*
		........
		省略pojo属性以及对应的getter/setter
	*/
	private Set<SysrMenutree> children = new TreeSet<SysrMenutree>(
			new Comparator<SysrMenutree>() {		//匿名内部类实现Comparator接口
				public int compare(SysrMenutree o1, SysrMenutree o2) {					
					return -o1.compareTo(o2);
				}
			});

	public void addChild(SysrMenutree node) {
		children.add(node);
	}

	public String toJsonString() {
		StringBuffer buf = new StringBuffer();
		buf.append("{ id : " + getId() + ", text : '" + this.getMname()
						+ "', ");
		if (children.size() > 0) {
			buf.append("children : [");
			for (SysrMenutree node : children) {
				buf.append(node.toJsonString() + ",");	//对子结点递归
			}
			buf.deleteCharAt(buf.length() - 1);
			buf.append("]}");
		} else {
		/*
		如果不定义leaf=true,EXTJS就认为那是一个目录并以文件夹的图标显示。
		但是如果没子结点,则会进入一个死循环。
		因此在这里做特殊处理:
		如果没有子结点,就设置leaf为true,但对数据库中标识为"dir"目录的结点,就指定显示图标为文件夹。
		*/
			if (this.getMtype().equals("dir")) {
				buf.append("icon : 'folder.gif', ");
			}
			buf.append("leaf : true }");
		}
		return buf.toString();
	}

	public int compareTo(SysrMenutree o) {		//Comparable接口具体实现
		if (getMtype().equals(o.getMtype())) {
			return this.getLeveidx() > o.getLeveidx() ? 1
					: (this.getLeveidx() == o.getLeveidx() ? 0 : -1);
		} else if (getMtype().equals("dir")) {
			return 1;
		} else {
			return -1;
		}
	}
}
  • 大小: 100.3 KB
分享到:
评论
8 楼 kjj 2009-07-20  
访问过的缓存一下嘛,这样有用没用都加载,如果节点修改了,又全部加载一次
7 楼 donnki 2009-07-20  
seele 写道
还不错哦。。不过一般都是大树

希望动态地去读取

动态的读取,对EXTJS来说更方便一些,只要加上一个异步请求就可以了,就没这么多代码没这么复杂了
我一开始也是想要动态读取,后来领导要求少访问数据库,只好一次加载出来
6 楼 donnki 2009-07-20  
stworthy 写道
toJsonString()不严谨,没考虑this.getMname()带',",\n等其他字符情况。


在结点名字入库前就做了相应的过滤处理了,因此不存在带特殊字符的情况
5 楼 donnki 2009-07-20  
异步取子结点的话,初次访问时,每次都要去执行一条sql查询

而一次加载出整个树结构,可以不用多次访问数据库~~由于是树结构,有点像菜单,不可能有很多结点。。

假如有很多节点,每次去用where parentId=''来执行查询,不也会很慢啊?而且在网速不好的情况下要让用户每打开一个结点就要等上好一阵子,多不好

4 楼 kjj 2009-07-17  
节点多得话异步获取字节点会更好,我就是这么搞的!!用dwr 去读取他的子树,这样每次都加载很少几个节点,不用的不需要加载上来!!
3 楼 stworthy 2009-07-17  
toJsonString()不严谨,没考虑this.getMname()带',",\n等其他字符情况。
2 楼 达达乐队 2009-07-17  
动态的好一些。
1 楼 seele 2009-07-17  
还不错哦。。不过一般都是大树

希望动态地去读取

相关推荐

    EXTJS4.0视频教程配套代码

    第一讲:extjs4.0概述和HELLO WORD程序 [01]EXTJS4.0的概述和HELLOWORD程序.wmv 第二讲:extjs4.0的新特性(附件较大做了分包压缩大家只要下载3个包运行001就ok了) [02]EXTJS4.0的新特性.003.zip (14.41M)[02]...

    Extjs教程源码

    Extjs教程源码 介: ***************第一部分基础知识**************** 第一讲: EXTJS4.0概述和HelloWorld程序 第二讲: EXTJS4.0的新特性 第三讲: EXTJS4.0数据模型——Model 第四讲: EXTJS4.0的数据代理——Proxy ...

    使用java,extjs,配合后台oracle数据库的代码框架

    使用java,extjs,配合后台oracle数据库的代码框架,这段代码是extjs的grid的一个详细案例使用java,extjs,配合后台oracle数据库的代码框架,这段代码是extjs的grid的一个详细案例使用java,extjs,配合后台oracle...

    extjs4中文视频下载地址

    extjs4.0 技术中文视频讲解,内容非常的全,而且讲的也不错,这是第一部分,里面有下载地址 可用迅雷下载。 第一讲:extjs4.0概述和HELLO WORD程序 第二讲:extjs4.0的新特性 第三讲:extjs4.0数据模型--Model 第...

    Extjs 动态树 数据库

    使用JDBC访问sqlserver 获得数据 生成Json串 Extjs 动态加载Tree 这是个完整项目 但是数据源需要自己配置 重在演示整个流程

    ExtJs 连接数据库并且生成动态树

    ExtJs 连接数据库并且生成动态树 ExtJs 连接数据库并且生成动态树 ExtJs 连接数据库并且生成动态树

    Extjs4.0视频教程和源代码,另附文档翻译

    第一讲:extjs4.0概述和HELLO WORD程序 [01]EXTJS4.0的概述和HELLOWORD程序.wmv 第二讲:extjs4.0的新特性(附件较大做了分包压缩大家只要下载3个包运行001就ok了) [02]EXTJS4.0的新特性.003.zip (14.41M)[02]EXTJS...

    免费 Extjs4.0教程视频

    第一讲:extjs4.0概述和HELLO WORD程序 [01]EXTJS4.0的概述和HELLOWORD程序.wmv 第二讲:extjs4.0的新特性(附件较大做了分包压缩大家只要下载3个包运行001就ok了) [02]EXTJS4.0的新特性.003.zip (14.41M)[02]EXTJS...

    ExtJS树形结构.docx

    extjs实现简单的树状结构级联Ext onReady function { Ext QuickTips init ; Ext BLANK IMAGE URL &quot;extjs resources images default s gif&quot;; var mytree new Ext tree TreePanel { el : &quot;...

    extjs editgrid示例代码

    extjs editgrid示例代码extjs editgrid示例代码extjs editgrid示例代码extjs editgrid示例代码

    extjs显示数据库

    extjs显示数据库代码,实例。

    extjs实现动态树

    extjs实现动态树

    Extjs 自定义树结构实现以及动态表头实现

    自定义树结构实现以及动态表头实现,整个程序是完整的,包括后台数据读取,数据赋值,树结构的类定义,前后端函数映射实现等,前端运用Extjs搭建页面

    ExtJs做到学生信息管理系统,Mysql数据库

    ExtJs做到学生信息管理系统,Mysql数据库ExtJs做到学生信息管理系统,Mysql数据库

    extjs异步树-每个节点都异步加载-前后台代码都有-附整个工程

    在家研究了一下extjs异步树,-每个节点都异步加载-前后台代码都有-附整个工程-运行通过-前台代码请看doctree.js,后台代码请看TreeService.java,运行环境:Myeclipse6.5+tomcat7.0.27

    Extjs4树结构异步加载

    extjs4,当点击左边的树,右边会生成相应的面板,代码精简,欢迎大家来学习,有问题可以直接交流。

    EXTJS---完整数据库代码,全网唯一,非常适合EXTJS搭建框架,包含动态树,菜单等

    EXTJS---完整数据库代码,全网唯一,非常适合EXTJS搭建框架,包含动态树,菜单,集成SPIRNGMVC+exjs+jdbc 等

    Extjs树Demo

    用Extjs 实现的 树形结构,仅供参考。

    extjs目录树编辑

    extjs目录树编辑对目录增删改查学习extjs的工具类

    Extjs如何与数据库交互

    ext精髓,Extjs如何与数据库交互,可以很快的叫你EXT一些知识

Global site tag (gtag.js) - Google Analytics