`
boogie
  • 浏览: 235780 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

利用Dojo和JSON建立无限级AJAX动态加载的功能模块树

    博客分类:
  • AJAX
阅读更多
        看了“使用hibernate实现树形结构无限级分类”这篇文章后,我也想将自己在所有开发的项目中使用的功能模块树的实现方法以及完整DEMO(含源码)贴出来和大家分享。其实在我的博客里是老早贴出来的,由于时间关系没好好整理。

       功能模块树是几乎在每个项目里都要用到的东西,利用Dojo的好处就是可以实现树的子节点的动态加载,这在树节点很多的情况下是很有用的。

        下载附件二dojotree.rar,解压后将dist\dojotree.war部署到应用服务器即可浏览DEMO,DEMO中内置HSQLDB数据库,启动时自动加载。DEMO运行截图见附件一。

一、tree.jsp主要代码

1、首先在head中导入Dojo库(dojo.js)和TreeWidget

 
  1. <script type=< span="">"text/javascript" src="ajax/dojo/dojo.js">  
  2. <script type=<span class="string">"text/javascript">  
  3. dojo.require("dojo.widget.Tree");  
  4. dojo.require("dojo.widget.TreeNode");  
  5. dojo.require("dojo.widget.TreeSelector");  
  6. dojo.require("dojo.widget.TreeRPCController");  
  7. dojo.require("dojo.widget.TreeLoadingController");  
  8. dojo.require("dojo.widget.TreeContextMenu");  
  9. </script>  


2、在body中放置TreeWidget,TreeLoadingController中的RPCUrl="treeServlet"为从后台获取数据的servlet名称,TreeNode中的expandLevel表示树初始张开级别

 
  1. <div dojoType="TreeLoadingController" RPCUrl="treeServlet" widgetId="treeController" DNDController="create"><!---->div>  
  2. <div dojoType="TreeSelector" widgetId="treeSelector"><!---->div>  
  3. <div dojoType="Tree" DNDMode="between" selector="treeSelector" widgetId="bandTree" controller="treeController">  
  4. <div dojoType="TreeNode" title="root" widgetId="root" objectId="root" isFolder="true" childIconSrc="images/comm.gif" expandLevel="1"/>  

3、建立TreeSelector事件处理函数

 
  1. function treeSelectFired() {  
  2.     // get a reference to the treeSelector and get the selected node   
  3.     var treeSelector = dojo.widget.manager.getWidgetById('treeSelector');  
  4.     var treeNode = treeSelector.selectedNode;  
  5.     // get a reference to the songDisplay div  
  6.     var hostDiv = document.getElementById("songDisplay");  
  7.     var isFolder = treeNode['isFolder'];  
  8.     //alert(isFolder);  
  9.     if ( !isFolder) {  
  10.        var song = treeNode['title'];  
  11.        var url = treeNode['url'];  
  12.        link(url);  
  13.     } else {   
  14.     }  
  15. }  

4、将select事件处理函数关联到treeSelector

 
  1. function init() {   
  2.   
  3.     //get a reference to the treeSelector  
  4.     var treeSelector = dojo.widget.manager.getWidgetById('treeSelector');  
  5.   
  6.     //connect the select event to the function treeSelectFired()  
  7.     dojo.event.connect(treeSelector,'select','treeSelectFired');   
  8. }  
  9.   
  10. dojo.addOnLoad(init);  


二、主要java代码及数据结构

1、Gnmk.java中tree的属性

 
  1.  private String id;    
  2.    
  3.  private String gnmkdm;  //功能模块代码  
  4.   
  5. private String gnmksm;  //功能模块说明  
  6.    
  7. private String gnmktb;  //功能模块图标  
  8.   
  9.  private String gnmklj;  //功能模块路径  
  10.    
  11.  private String gnmkmc;  //功能模块名称  
  12.     
  13. private String gnmksj;  //功能模块上级代码  
  14.    
  15. private String gnmkbz;  //功能模块标志(‘N’为叶节点)  

2、HSQLDB内存数据库加载SQL(db.sql)

 
  1. CREATE TABLE GNMK (ID VARCHAR, GNMKDM VARCHAR, GNMKMC VARCHAR, GNMKLJ VARCHAR, GNMKTB VARCHAR, GNMKBZ VARCHAR, GNMKSJ VARCHAR);    
  2. INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1', null, 'system.gif', 'Y', '');    
  3. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830001', '0101', '二级目录1', 'cxtjAction.do', 'system.gif', 'N', '01');    
  4. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830001', '0102', '二级目录2', 'cxtjAction.do', 'system.gif', 'N', '01');    
  5. INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780002', '02', '一级目录2', null, 'system.gif', 'Y', '');    
  6. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '0201', '二级目录1', 'cxtjAction.do', 'system.gif', 'N', '02');    
  7. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '0202', '二级目录2', 'cxtjAction.do', 'system.gif', 'Y', '02');    
  8. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '020201', '三级目录1', 'cxtjAction.do', 'system.gif', 'N', '0202');    
  9. INSERT INTO GNMK VALUES ('d098a59f0b765e68010b765fda830002', '020202', '三级目录2', 'cxtjAction.do', 'system.gif', 'N', '0202');   

3、TreeServlet .java主要代码,在getGnmkByParent(String gnmksj)方法中可以实现自己的业务,DEMO中使用GnmkDAO

 
  1. public class TreeServlet extends HttpServlet {  
  2.   
  3.     private static final long serialVersionUID = 1L;  
  4.   
  5.     protected void doGet(HttpServletRequest request,  
  6.             HttpServletResponse response) throws ServletException, IOException {  
  7.         String action = request.getParameter("action");  
  8.         System.out.println("action b=>" + action);  
  9.         System.out.println("action b=>" + action);  
  10.         String data = request.getParameter("data");  
  11.         if (action.equalsIgnoreCase("getChildren")) {  
  12.             JSONTokener jsonTokener = new JSONTokener(data);  
  13.             JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();  
  14.             JSONObject parentNodeObject = (JSONObject) jsonObject.get("node");  
  15.   
  16.             response.setContentType("text/json; charset=gb2312");  
  17.             PrintWriter out = response.getWriter();  
  18.             out.write(getChildren(parentNodeObject));  
  19.         } else {  
  20.         }  
  21.     }  
  22.   
  23.     private String getChildren(JSONObject parentNodeObject) {  
  24.         JSONArray result = new JSONArray();  
  25.         String parentObjectId = parentNodeObject.getString("objectId");// id 唯一  
  26.         // String parentWidgetId = parentNodeObject.getString("widgetId");// dm  
  27.         parentObjectId = parentObjectId.equalsIgnoreCase("root") ? ""  
  28.                 : parentObjectId;  
  29.         System.out.println("parentObjectId=>" + parentObjectId);  
  30.         // 获取子功能模块  
  31.         List listGnmk = this.getGnmkByParent(parentObjectId);  
  32.         System.out.println("listGnmk=>" + listGnmk.size());  
  33.         if (listGnmk != null) {  
  34.             Iterator itGnmk = listGnmk.iterator();  
  35.             while (itGnmk.hasNext()) {  
  36.                 Gnmk qxgnmk = (Gnmk) itGnmk.next();  
  37.                 try {  
  38.                     JSONObject jsonGnmkObject = new JSONObject();  
  39.                     String gnmkbz = qxgnmk.getGnmkbz();  
  40.                     boolean isFolder = gnmkbz.equalsIgnoreCase("Y") ? true  
  41.                             : false;  
  42.                     jsonGnmkObject.put("title", qxgnmk.getGnmkmc());  
  43.                     jsonGnmkObject.put("isFolder", isFolder);  
  44.                     jsonGnmkObject.put("widgetId", qxgnmk.getGnmkdm());  
  45.                     jsonGnmkObject.put("objectId", qxgnmk.getGnmkdm());  
  46.                     jsonGnmkObject.put("childIconSrc""images/"  
  47.                             + qxgnmk.getGnmktb());  
  48.                     jsonGnmkObject.put("url", qxgnmk.getGnmklj());  
  49.                     result.put(jsonGnmkObject);  
  50.                 } catch (JSONException e) {  
  51.                     e.printStackTrace();  
  52.                 }  
  53.             }  
  54.         }  
  55.         return result.toString();  
  56.     }  
  57.   
  58.     private List getGnmkByParent(String gnmksj) {  
  59.         GnmkDAO gnmkDao = new GnmkDAO();  
  60.         return gnmkDao.getGnmkByParent(gnmksj);  
  61.     }  
  62. }  


三、关于DEMO的其它配置说明

1、实现javax.servlet.ServletContextListener接口的contextInitialized方法来加载HSQLDB及其数据,ContextListener.java主要代码

 
  1. public void contextInitialized(ServletContextEvent event) {  
  2.     try {  
  3.         // load the driver  
  4.         Class.forName("org.hsqldb.jdbcDriver");  
  5.         // create the table and add sample data  
  6.         InputStreamReader in = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("db.sql"));  
  7.         BufferedReader reader = new BufferedReader(in);  
  8.         DBUtils.setupDatabase(reader);  
  9.     } catch (ClassNotFoundException e) {  
  10.         e.printStackTrace();  
  11.     }  
  12.       
  13. }  

2、web.xml相关配置

 
  1. <listener>  
  2.     <listener-class>  
  3.        dojo.sample.ContextListener  
  4.     <!----><!---->listener-class>  
  5. <!---->>  

  • 描述: DEMO截图
  • 大小: 8.5 KB
  • dojotree.rar (2.7 MB)
  • 描述: DEMO源代码
  • 下载次数: 10914
分享到:
评论
36 楼 fcllingzi 2007-08-31  
非常的感谢!
35 楼 shenqiang 2007-08-06  
楼主能不能解释下是怎么复写jsp的?是不是dojo自动的?
34 楼 mailzhang 2007-07-16  
多谢多谢
学习中


33 楼 boogie 2007-07-03  
peterwillcn 写道
点击是 报错....parent.MainFrame.location.href 为空或不是对象。。。。这是什么原因
<br/>
树节点的点击动作没有配置,这里仅仅演示树
32 楼 peterwillcn 2007-07-02  
点击是 报错....parent.MainFrame.location.href 为空或不是对象。。。。这是什么原因
31 楼 ppeter 2007-06-27  
<p>
boogie 写道
当有400个节点的时候,应该说都会很慢,不仅仅是Dojo! 所以要实现动态加载,不能400个节点一次性都加载!
</p>
<p>400个节点确实确实很少啊,DOJO不实用.</p>
30 楼 boogie 2007-06-25  
应该是servlet容器报错!
我在tomcat5.028和weblogic816里测试通过!
29 楼 庄严 2007-06-24  
为什么出错呢??
================================================================================
action b=>getChildren

action b=>getChildren

StandardWrapperValve[treeServlet]: Servlet.service() for servlet treeServlet threw exception

javax.servlet.ServletException: Servlet execution threw an exception

javax.servlet.ServletException: Servlet execution threw an exception

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:190)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566)

at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)

at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2347)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566)

at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:170)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:170)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:564)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)

at org.apache.catalina.core.StandardPipeline.invokeNext(StandardPipeline.java:566)

at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:472)

at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:943)

at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor.java:1027)

at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.java:1125)

at java.lang.Thread.run(Thread.java:536)

28 楼 boogie 2007-06-23  
当有400个节点的时候,应该说都会很慢,不仅仅是Dojo!
所以要实现动态加载,不能400个节点一次性都加载!
27 楼 pkqiang 2007-06-23  
Dojo+JSON实现的树速度非常之慢,当有400个节点的时候,IE大概要1分钟才能处理完,不实用啊
26 楼 whistler 2007-06-19  
下载了,学习中,谢谢共享
25 楼 boogie 2007-06-19  
<p>
ppeter 写道
to lz:我将 INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1', null, 'system.gif', 'Y', ''); 改成 INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1㎡㎎㎏', null, 'system.gif', 'Y', ''); 即插入特殊符号后就出现乱码,不知道你有没有发现这个问题.
</p>
<p>这是编码问题,你把编码全部转化为UTF-8,应该就可以了!我这是演示树,就没考虑这么多了!</p>
24 楼 boogie 2007-06-19  
shaoxiongwang@21cn.com 写道
首先十分感谢LZ的分享,现提出一个问题,对节点号的处理,节点号一级节点是01,02,03...,两级是0101,0102,0103....,此节点号是自动生成的,节点号显然必须是唯一的,节点号的产生如果采用父节点+子节点的数量+1,这样产生的节点号会重复,因为用户可能先删除节点,再增加节点,这样的话新增的节点号就会重复,如果采用同一级节点中的最大节点号+1,这样如果增加删除很多,所新产生的节点号会越来越大,大家一般如何处理此类问题,是否只能任任其无限增大?
<hr/>
<br/>
你所说的节点号对应的是GNMKDM即功能模块代码,这只是个编号,我在实际环境中这个编号其实只是为了方便查询而设置的,真正起作用的是Hibernater生成的32位的ID号。
23 楼 shaoxiongwang#21cn.com 2007-06-18  
首先十分感谢LZ的分享,现提出一个问题,对节点号的处理,节点号一级节点是01,02,03...,两级是0101,0102,0103....,此节点号是自动生成的,节点号显然必须是唯一的,节点号的产生如果采用父节点+子节点的数量+1,这样产生的节点号会重复,因为用户可能先删除节点,再增加节点,这样的话新增的节点号就会重复,如果采用同一级节点中的最大节点号+1,这样如果增加删除很多,所新产生的节点号会越来越大,大家一般如何处理此类问题,是否只能任任其无限增大?
22 楼 ppeter 2007-06-04  
to lz:我将
INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1', null, 'system.gif', 'Y', '');     改成
INSERT INTO GNMK VALUES ('d098a59f0b765c30010b765d6b780001', '01', '一级目录1㎡㎎㎏', null, 'system.gif', 'Y', '');     即插入特殊符号后就出现乱码,不知道你有没有发现这个问题.
21 楼 boogie 2007-06-02  
fanth 写道
可是我怎么没有找到动态加载呢?怎么样操作可以看到动态加载的效果?
<br/>
当点击结点前的“+”时才去后台获取其子结点,以后就不会再一次的去获取!
20 楼 fanth 2007-06-01  
搂主说:

"功能模块树是几乎在每个项目里都要用到的东西,利用Dojo的好处就是可以实现树的子节点的动态加载,这在树节点很多的情况下是很有用的。"

  可是我怎么没有找到动态加载呢?怎么样操作可以看到动态加载的效果?另外树节点上也没有右键菜单。想跟你交流一下关于DOJO树刷新的问题,不知道楼主感兴趣不。
19 楼 linginfanta 2007-05-11  
能不能支持拖拽,和加checkbox
18 楼 wshsm 2007-05-04  
好文章!再接再厉
17 楼 ancin 2007-04-19  
感谢;
学习中。

相关推荐

    dojo精品中文教程(包一)

    Dojo和JSON建立无限级AJAX动态加载的功能模块树 Dojo学习笔记( 模块与包) Dojo学习笔记-- djConfig解说 Dojo学习笔记-- dojo.dom Dojo学习笔记-- dojo.event & dojo.event.topic & dojo.event.browser Dojo学习...

    dojo精品中文教程(包二)

    Dojo和JSON建立无限级AJAX动态加载的功能模块树 Dojo学习笔记( 模块与包) Dojo学习笔记-- djConfig解说 Dojo学习笔记-- dojo.dom Dojo学习笔记-- dojo.event & dojo.event.topic & dojo.event.browser Dojo学习...

    dojo精品中文教程(全)

    Dojo和JSON建立无限级AJAX动态加载的功能模块树 Dojo学习笔记( 模块与包) Dojo学习笔记-- djConfig解说 Dojo学习笔记-- dojo.dom Dojo学习笔记-- dojo.event & dojo.event.topic & dojo.event.browser Dojo学习...

    dojo精品中文教程(包三)

    Dojo和JSON建立无限级AJAX动态加载的功能模块树 Dojo学习笔记( 模块与包) Dojo学习笔记-- djConfig解说 Dojo学习笔记-- dojo.dom Dojo学习笔记-- dojo.event & dojo.event.topic & dojo.event.browser Dojo学习...

    使用Dojo,JSON开发ajax

    ### 使用Dojo与JSON开发AJAX应用 #### Dojo与JSON简介 Dojo是一个开源的JavaScript框架,专门设计用于简化富互联网应用(RIA)的开发。它提供了丰富的UI控件和强大的工具集,使得开发者能够轻松创建高性能的前端...

    dojo与json应用

    ### Dojo与JSON应用详解 #### 一、概述 Dojo是一个用JavaScript语言实现的开源DHTML工具包,它提供了一系列强大的功能来帮助开发者构建高度交互式的Web应用程序。随着Web技术的发展,前后端分离成为了一种趋势,而...

    dojo Ajax

    9. **dojo/json**: 提供了JSON序列化和反序列化的功能,如`dojo/json::parse`和`dojo/json::stringify`,帮助开发者在Ajax请求中处理JSON数据。 10. **dojo.stateful**: 对象状态管理是Ajax应用中常见需求,`dojo/...

    dojo与json应用说明.pdf

    Dojo的`dojo/json`模块提供了解析和字符串化JSON的功能,而`dojo/request`模块可以用来异步请求JSON数据。 3. **Taglib的定义**: Taglib(标签库)是一种在Java Web开发中常用的组件,它允许开发者创建可重用的...

    dojo_doc(json+dojo的例子)

    本压缩包“dojo_doc(json+dojo的例子)”显然包含了关于如何使用Dojo与JSON进行交互的实例和文档,这对于理解和掌握Dojo的AJAX(异步JavaScript和XML)功能至关重要。 首先,让我们详细了解一下JSON(JavaScript ...

    dojo dojo实例 dojo例子 dojo资料 dojo项目 dojo实战 dojo模块 dojo编程

    9. **dojo/xhr**:处理AJAX请求的模块,如`dojo/xhrGet`和`dojo/xhrPost`,支持异步和同步请求,以及XML、JSON等多种数据格式。 10. **dojo/json**:提供了JSON序列化和反序列化的功能,方便在JavaScript和服务器...

    dojo-0.3.1-ajax

    当需要处理复杂的跨域场景,如上传文件或处理需要维持会话的请求时,Dojo的`dojo.io.iframe`模块提供了利用隐藏IFrame进行AJAX通信的解决方案。 总结来说,"dojo-0.3.1-ajax"是Dojo工具包的一个版本,专注于提供...

    最棒的AJAX框架DOJO中文手册

    Dojo的动画模块`dojo/fx`提供了一系列的过渡效果和组合动画,使得动态效果的实现变得简单易行。此外,`dojo/_base.fx`包含了基本的淡入淡出、移动和缩放等效果。 ### 7. Dojo中文手册的重要性 对于中文开发者来说...

    基于dojo的动态树

    5. **AJAX通信**:通常利用Dojo的`dojo/xhr`模块与后端进行通信,获取或更新数据库数据。 通过学习这个例子,开发者不仅可以理解Dojo Tree的基本用法,还能了解到如何将树结构与数据库紧密结合,实现动态更新,这...

    Dojo构建Ajax应用程序源码(包括书中用到的dojo-release-1.1.2)

    4. **Ajax通信**:Dojo的`dojo/xhr`模块提供了发送Ajax请求的方法,如`dojo/xhrGet`、`dojo/xhrPost`等,支持JSON、XML等多种数据格式。 5. **动画效果**:`dojo/fx`模块提供了丰富的动画效果,包括基本的淡入淡出...

    dojo-0.4.2-ajax.rar

    使用Dojo进行Ajax开发,开发者可以利用其强大的模块化系统,按需加载所需的部分,减少页面加载时间。Dojo还提供了一套完整的测试框架,确保代码的稳定性和可靠性。同时,Dojo的API设计遵循了统一的命名约定和编程...

    dojo的ajax的jar包

    总结一下,dojo的Ajax功能通过xhr模块提供了强大的异步通信能力,使得Java开发者能够轻松地在Struts1和Struts2框架中构建动态、交互式的Web应用。通过引入dojo-0.4.3-ajax.jar,你可以享受到dojo的Ajax功能,提高Web...

    Requirejs异步加载Dojo1.6

    在加载Dojo模块时,可以利用Requirejs的异步加载特性,只加载当前需要的模块,而不是一次性加载整个Dojo库,这有助于优化性能。 ### 文件结构与压缩包子文件 在名为"**DojoAMD**"的压缩包中,可能包含以下内容: - ...

Global site tag (gtag.js) - Google Analytics