一份完整的Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree

来源:互联网 发布:外国域名注册 编辑:程序博客网 时间:2024/05/16 18:11
 在各种论坛上看了很久,没见到完整extJs树的生成代码。研究了很久终于实现了Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree。 

     一、树的对象模型。
        
Java代码
  1. package com.ssgly.model;   
  2.   
  3. import java.util.List;   
  4. import java.util.Set;   
  5.   
  6.     
  7. public class Region {   
  8.     
  9.     private Long id;   
  10.     private String name;   
  11.     private String code;   
  12.     private Region parent;   
  13.     private Set<Region> children = new java.util.HashSet<Region>();   
  14.   
  15.     public Region() {}   
  16.   
  17.     public Region(String name, String code, Region parent) {   
  18.         this.name = name;   
  19.         this.code = code;   
  20.         if(parent!=null) parent.addChild(this);        
  21.     }   
  22.   
  23.     public Long getId() {   
  24.         return id;   
  25.     }   
  26.   
  27.     public void setId(Long id) {   
  28.         this.id = id;   
  29.     }   
  30.   
  31.     public String getName() {   
  32.         return name;   
  33.     }   
  34.   
  35.     public void setName(String name) {   
  36.         this.name = name;   
  37.     }   
  38.   
  39.     public String getCode() {   
  40.         return code;   
  41.     }   
  42.   
  43.     public void setCode(String code) {   
  44.         this.code = code;   
  45.     }   
  46.   
  47.     public Region getParent() {   
  48.         return parent;   
  49.     }   
  50.   
  51.     public void setParent(Region parent) {   
  52.         this.parent = parent;   
  53.     }   
  54.   
  55.     public Set<Region> getChildren() {   
  56.         return children;   
  57.     }   
  58.   
  59.     public void setChildren(Set<Region> children) {   
  60.         this.children = children;   
  61.     }   
  62.         
  63.   
  64. }   
  65.            

二、树结构的数据库(mySql)DDL
Java代码 复制代码
  1. CREATE TABLE `region` (   
  2.   `id` bigint(20) NOT NULL,   
  3.   `name` varchar(100default NULL,   
  4.   `code` varchar(100default NULL,   
  5.   `parent_id` bigint(20default NULL,   
  6.   PRIMARY KEY  (`id`),   
  7.   KEY `FK91AD1314568C1D72` (`parent_id`),   
  8.   CONSTRAINT `FK91AD1314568C1D72` FOREIGN KEY (`parent_id`) REFERENCES `region` (`id`)   
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  

三、对象模型到数据库的Hibernate映射关系
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">   
  4. <hibernate-mapping>   
  5.         
  6.     <class name="com.ssgly.model.Region" table="region"  >   
  7.         <id       name="id"   column="id"  type="java.lang.Long">   
  8.              <generator class="assigned" />   
  9.         </id>           
  10.         <property name="code" column="code" type="java.lang.String" />   
  11.         <property name="name" column="name"  type="java.lang.String"  />   
  12.         <many-to-one name="parent"   column="parent_id"    cascade="save-update"  />   
  13.         <set name="children"   inverse="true" cascade="save-update"  lazy="false">   
  14.              <key column="parent_id"  ></key>   
  15.              <one-to-many class="com.ssgly.model.Region"></one-to-many>   
  16.         </set>   
  17.     </class>   
  18. </hibernate-mapping>  

四、用Spring框架来管理和支撑持久层、业务逻辑层和展示层
【一】持久层采用了DAO模式 。具体设计了一个类型安全的泛型DAO。由于这不是我要讲的重点部分,感兴趣的朋友可以
查阅有关文档。要生成一个树,必须要从后台数据库中按一定类型(我用了适配器模式)取出java对象--TreeNode 对象  。及要实现方法 public List<Region> listRegionByParent(Region parent)。
TreeNode类型为:
Java代码 复制代码
  1. package com.ssgly.model;   
  2.   
  3.   
  4.   
  5. ublic  class TreeNode {   
  6. private String id;   
  7. private String Text;   
  8. private boolean leaf;   
  9. private String cls="";    
  10.   
  11. private Region region;   
  12.   
  13. public TreeNode(Region region)   
  14. {   
  15.         this.region=region;   
  16. }      
  17.   
  18. public String getId() {        
  19.         return region.getId().toString();   
  20. }   
  21.     
  22. public boolean getLeaf() {         
  23.         return region.getChildren().size()<1;   
  24. }          
  25.   
  26. public String getText() {              
  27.         return region.getName();   
  28. }   
  29.   
  30. public String getCls() {   
  31.     return region.getChildren().size()<1?"file":"folder";   
  32. }   
  33.   
  34.     
  35.   
  36.     


具体生成树的泛型DAO实现是:
Java代码 复制代码
  1. package com.ssgly.dao;   
  2.   
  3.     
  4.   
  5. import java.io.IOException;   
  6. import java.sql.SQLException;   
  7. import java.text.SimpleDateFormat;   
  8. import java.util.List;   
  9.   
  10. import com.ssgly.model.Region;   
  11.   
  12. import com.ssgly.model.Page;   
  13.   
  14.   
  15. public class RegionDAOImpl extends GenericHibernateDAOCrud<Region> implements IRegionDAO {   
  16.        
  17.     public RegionDAOImpl(){   
  18.            
  19.         super(Region.class);   
  20.     }   
  21.   
  22.     public void deleteRegion(Region region) {   
  23.         hibernateTemplate.delete(region);   
  24.            
  25.     }   
  26.   
  27.     public void deleteRegion(Long id) {   
  28.         hibernateTemplate.delete(hibernateTemplate.get(Region.class, id));   
  29.            
  30.     }   
  31.   
  32.     public Region getRegion(Long id) {   
  33.             
  34.         return (Region)hibernateTemplate.get(Region.class, id);   
  35.     }   
  36.   
  37.     public Long saveRegion(Region region) {   
  38.         hibernateTemplate.save(region);   
  39.         return region.getId();   
  40.     }   
  41.   
  42.     public void updateRegion(Region region) {   
  43.            
  44.         hibernateTemplate.saveOrUpdate(region);   
  45.     }   
  46.        
  47.     /**  
  48.      * 查询父节点的所有子节点  
  49.      * @param parent   父节点  
  50.      * @return  该父节点对应的子节点  
  51.      *   
  52.      *   
  53.      **/  
  54.     public List<Region> listRegionByParent(Region parent) {   
  55.          if (parent==null){   
  56.              return (List<Region>)hibernateTemplate.find("from Region as r where r.parent is null");    
  57.          }else{   
  58.              return (List<Region>)queryForLists("from Region as r where r.parent=?"  
  59.                          ,new Object[]{parent});   
  60.                 
  61.          }   
  62.            
  63.     }   
  64.   
  65.        
  66. }  


从上面java代码中可以看到:DWR需要解析的是 List<Region> 类型的对象。
【二】业务逻辑层主要采用一个实现类BusinessServiceImp 。将所有的业务逻辑放在一个类中,一是便于spring中bean好管理,二是方便权限控制。BusinessServiceImp 中的一个很重要的属性是: private IRegionDAO regionDAO; regionDAO的生命周期依赖于spring容器,在spring中管理和维护。逻辑层的代码如下:
Java代码 复制代码
  1. package com.ssgly.business.impl;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.Serializable;   
  5. import java.sql.SQLException;   
  6. import java.util.ArrayList;   
  7. import java.util.Iterator;   
  8. import java.util.List;   
  9.   
  10. import com.ssgly.model.*;   
  11. import com.ssgly.util.Hzxs;   
  12.   
  13. import com.ssgly.business.BusinessService;   
  14. import com.ssgly.dao.*;   
  15.   
  16.   
  17. public class BusinessServiceImpl implements BusinessService {   
  18.         
  19.         private IRegionDAO regionDAO;   
  20.            
  21.         public void setRegionDAO(IRegionDAO regionDAO) {   
  22.             this.regionDAO = regionDAO;   
  23.         }   
  24.         
  25.         public List<TreeNode> getAllChildren(Long parentId) throws IOException,   
  26.                 SQLException {   
  27.             List<Region> listRegion=regionDAO.listRegionByParent(regionDAO.getRegion(parentId));   
  28.             List<TreeNode> listTreeNode=new ArrayList<TreeNode>();   
  29.             for(Region region:listRegion){   
  30.                 System.out.println(">>"+region.getName());   
  31.                 listTreeNode.add(new TreeNode(region));   
  32.             }   
  33.             //System.out.println("List<TreeNode> getAllChildren 方法已执行!");   
  34.             return listTreeNode;   
  35.         }   
  36.             
  37.            
  38. }  

【三】Spring容器的配置主要是通过xml方式体现。
一是:web.xml的配置如下:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
  3.     "http://java.sun.com/dtd/web-app_2_3.dtd">   
  4. <web-app>   
  5.    <context-param>   
  6.         <param-name>contextConfigLocation</param-name>   
  7.         <param-value>   
  8.             /WEB-INF/dispatcherServlet-servlet.xml,   
  9.             /WEB-INF/model-config.xml               
  10.         </param-value>   
  11.     </context-param>   
  12.   <!-- log4j config -->   
  13.     <context-param>   
  14.         <param-name>log4jConfigLocation</param-name>   
  15.         <param-value>/WEB-INF/log4j.properties</param-value>   
  16.     </context-param>      
  17.  <!--========================================================================   
  18.         Filters   
  19.     =========================================================================-->   
  20.   
  21.     <filter>   
  22.         <filter-name>encodingFilter</filter-name>   
  23.         <filter-class>com.ssgly.web.filter.EncodingFilter</filter-class>   
  24.         <init-param>   
  25.             <param-name>encoding</param-name>   
  26.             <param-value>utf-8</param-value>   
  27.         </init-param>   
  28.     </filter>   
  29.     <filter-mapping>   
  30.         <filter-name>encodingFilter</filter-name>   
  31.         <url-pattern>*</url-pattern>   
  32.     </filter-mapping>       
  33.  <!--========================================================================   
  34.         Listeners   
  35.     =========================================================================-->   
  36.   
  37.     <listener>   
  38.         <listener-class>   
  39.             org.springframework.web.util.Log4jConfigListener   
  40.         </listener-class>   
  41.     </listener>   
  42.     <listener>   
  43.         <listener-class>   
  44.             org.springframework.web.context.ContextLoaderListener   
  45.         </listener-class>   
  46.     </listener>   
  47.       
  48.   <!--========================================================================   
  49.         Servlets   
  50.     =========================================================================-->   
  51.     <servlet>   
  52.         <servlet-name>dispatcherServlet</servlet-name>   
  53.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>   
  54.         <load-on-startup>0</load-on-startup>   
  55.     </servlet>   
  56.   
  57.     <servlet-mapping>   
  58.         <servlet-name>dispatcherServlet</servlet-name>   
  59.         <url-pattern>*.do</url-pattern>   
  60.     </servlet-mapping>   
  61. <!--========================================================================   
  62.         DWR 配置   
  63.     =========================================================================-->   
  64.     <!--配置DWR拦截器-->      
  65.      <servlet>      
  66.           <servlet-name>dwr-invoker</servlet-name>      
  67.           <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>      
  68.           <init-param>      
  69.            <param-name>debug</param-name>      
  70.            <param-value>true</param-value>      
  71.           </init-param>   
  72.           <init-param>   
  73.             <param-name>classes</param-name>   
  74.             <param-value>java.lang.Object</param-value>   
  75.           </init-param>   
  76.           <load-on-startup>100</load-on-startup>   
  77.      </servlet>      
  78.      <servlet-mapping>      
  79.       <servlet-name>dwr-invoker</servlet-name>      
  80.       <url-pattern>/dwr/*</url-pattern>      
  81.      </servlet-mapping>   
  82.  <!--========================================================================   
  83.         Session   
  84.     =========================================================================-->   
  85.   
  86.     <session-config>   
  87.         <session-timeout>30</session-timeout>   
  88.     </session-config>   
  89.   
  90.         
  91.     
  92.     
  93. </web-app>  

二是:bean生成的配置。model-config.xml
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"    
  3.  "http://www.springframework.org/dtd/spring-beans.dtd">    
  4.  <beans>   
  5.         
  6.      <bean id="propertyConfigurer"  
  7.         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">   
  8.         <property name="locations">   
  9.             <list>   
  10.                 <value>/WEB-INF/jdbc.properties</value>                   
  11.             </list>   
  12.         </property>   
  13.     </bean>   
  14.         
  15.    <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  16.         <property name="driverClassName" value="${jdbc.driver}" />   
  17.         <property name="url" value="${jdbc.url}" />   
  18.         <property name="username" value="${jdbc.username}" />   
  19.         <property name="password" value="${jdbc.password}" />   
  20.     </bean>       
  21.   
  22.   
  23.     <bean id="sessionFactory"  
  24.                  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"  destroy-method="close">   
  25.             <property name="dataSource">   
  26.                  <ref local="myDataSource" />   
  27.             </property>   
  28.             <property name="mappingResources">   
  29.                 <list>   
  30.                    <value> com/ssgly/model/Region.hbm.xml</value>                   
  31.                 </list>   
  32.             </property>   
  33.             <property name="hibernateProperties">   
  34.               <props>   
  35.                 <prop key="connection.characterEncoding">utf-8</prop>   
  36.                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>   
  37.                 <prop key="hibernate.jdbc.batch_size">50</prop>    
  38.                 <prop key="hibernate.show_sql">true</prop>   
  39.                 <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>   
  40.                 </props>   
  41.             </property>   
  42.         </bean>   
  43.      
  44.     <bean id="transactionManager"    
  45.           class="org.springframework.orm.hibernate3.HibernateTransactionManager">    
  46.         <property name="sessionFactory">    
  47.             <ref bean="sessionFactory"/>    
  48.         </property>    
  49.     </bean>   
  50.        
  51.     <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">   
  52.          <property name="sessionFactory"> <ref bean="sessionFactory"/> </property>   
  53.     </bean>   
  54.        
  55.     
  56.      <bean id="regionDao"  class="com.ssgly.dao.RegionDAOImpl">   
  57.         <property name="hibernateTemplate">    
  58.             <ref bean="hibernateTemplate"/>   
  59.         </property>               
  60.      </bean>                                      
  61.    <bean id="businessService" class="com.ssgly.business.impl.BusinessServiceImpl">   
  62.        <property name="regionDAO"><ref  bean="regionDao" /></property>   
  63.           
  64.    </bean>   
  65.       
  66.    <bean id="todoSsglyService"  class="com.ssgly.ext.ToDoImpl">   
  67.         <property name="businessServiceImpl">    
  68.             <ref bean="businessService"/>   
  69.         </property>               
  70.    </bean>   
  71.       
  72.       
  73. </beans>  

三是:servlet配置 dispatcherServlet-servlet.xml
Java代码 复制代码
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"    
  3.  "http://www.springframework.org/dtd/spring-beans.dtd">    
  4.   
  5. <beans>   
  6.     <!--============================================================================   
  7.         URL Mapping configuration   
  8.     =============================================================================-->   
  9.   
  10.     <bean id="beanNameUrlMapping"  
  11.         class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">   
  12.         <property name="alwaysUseFullPath" value="true" />   
  13.     </bean>   
  14.    <!--============================================================================   
  15.         Velocity configuration   
  16.     =============================================================================-->   
  17.   
  18.     <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">   
  19.         <property name="contentType"><value>text/html;charset=GBK</value></property>   
  20.     </bean>   
  21.   
  22.     <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">   
  23.         <property name="configLocation" value="/WEB-INF/velocity.properties" />   
  24.         <property name="resourceLoaderPath" value="/" />   
  25.     </bean>   
  26.     
  27.     <bean id="treeRegionServlet"  name="/treeRegionServlet.do" class="com.ssgly.web.TreeRegionServlet">   
  28.         <property name="businessService">   
  29.             <ref bean="businessService"/>   
  30.         </property>   
  31.     </bean>   
  32. </beans>  

    有了这些xml的配置。Spring能将三层很好地组合起来。以上是java部分。还没有讲到extJs。extJs可以接受asp、php、java等服务器端生成的json格式的对象。就java来说 ,extJs能接受三种方式的json对象,一是servlet中拼接json对象;其次是引用json lib 包;三是DWR方式,绕过Controller(就Spring来说)或servlet,在javascript中 直接调用java业务逻辑层中的方法(通过DWR引擎),利用dwr代理或者javascript 回调函数返回json对象并在页面展示。
    本人采用了第三种DWR方式实现ExtJs生成树。要使用dwr 就的要在以上几个配置文件中配置DWR(已配)。具体的下次再说吧。
    今天就写到这里吧。不知写的怎么样?有朋友关注这一块?若支持,请鼓励一下;写的不好、不对或不懂的地方,请拍砖。(续)

    抱歉啊,这几天忙着考驾照,把这事给耽搁啊。书接上回吧。
【四】基于Spring方式的DWR配置说明。
一、首先在WEB.xml中配置dwr拦截器 代码如下(节选):
Java代码
  1. <!--配置DWR拦截器-->      
  2.      <servlet>      
  3.              <servlet-name>dwr-invoker</servlet-name>      
  4.       <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>      
  5.           <init-param>      
  6.            <param-name>debug</param-name>      
  7.            <param-value>false</param-value>      
  8.           </init-param>   
  9.           <init-param>   
  10.             <param-name>classes</param-name>   
  11.             <param-value>java.lang.Object</param-value>   
  12.           </init-param>   
  13.           <load-on-startup>100</load-on-startup>   
  14.      </servlet>      
  15.      <servlet-mapping>      
  16.       <servlet-name>dwr-invoker</servlet-name>      
  17.       <url-pattern>/dwr/*</url-pattern>      
  18.      </servlet-mapping>  

二、dwr.xml的配置。这里将Spring管理的bean映射成javascipt操作的对象。更直观的说法就是使得页面中javascript能直接使用java中对象的方法。代码如下:
Java代码
  1.  <?xml version="1.0" encoding="utf-8"?>   
  2. <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"  
  3.     "http://getahead.ltd.uk/dwr/dwr20.dtd">   
  4.   
  5. <dwr>   
  6.     <allow>   
  7.         <convert converter="bean"  match="com.ssgly.model.*"/>   
  8.         <convert converter="map" match="org.directwebremoting.convert.MapConverter"/>    
  9.         <create creator="spring" javascript="treeBusinessService">   
  10.           <param name="beanName" value="businessService"/>   
  11.           <include method="getAllChildren" />   
  12.         </create>   
  13.     </allow>   
  14.      
  15. </dwr>  


    从上面的代码可以看出,javascript使用treeBusinessService.getAllChildren 方法就能够直接取出 Spring维持的业务逻辑层定义的bean----- businessService。从而完成了DWR的功能。这里当然存在安全问题,在这里暂时没有讨论,关于如何在DWR中进行安全控制,大家可以参考有关文档。本文暂不考虑。
【五】ext和服务器端交互的机制和具体实现
    一般说来,按照上面DWR的配置,就已经实现了在页面中使用java的方法。但java方法执行后生成的List 传回到页面还需要靠回调函数实现。例如下面代码就是包含了回调函数的测试页。
Java代码
  1. <html>   
  2. <head>         
  3.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">      
  4. <title>ExtJS-树示例</title>   
  5. <link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />   
  6. <script type="text/javascript" src="ext2/adapter/ext/ext-base.js"></script>   
  7. <script type="text/javascript" src="ext2/ext-all.js"></script>   
  8.     
  9. <PRE class=java name="code"><script type="text/javascript" src="dwr/interface/treeBusinessService.js "></script>   
  10. <script type="text/javascript" src="dwr/engine.js "></script>   
  11. <script type="text/javascript" src="dwr/util.js "></script></PRE>    
  12. <BR><script type="text/javascript">   
  13. <BR>           
  14. <BR>    treeBusinessService.getAllChildren(1,function(ret){   
  15. <BR>                                     alert("一共有"+ret.length+"个子节点");   
  16. <BR>                                   });   
  17. <BR>   
  18. <BR></script>   
  19. <BR></head>   
  20. <BR>       
  21. <BR><body>   
  22. <BR><div id="tree-div"></div>        
  23. <BR></body>   
  24. <BR></html>   
  25. <BR>  


现在分析一下上面页面主要代码:

Java代码
  1. <script type="text/javascript" src="dwr/interface/treeBusinessService.js "></script>   
  2.    

这句中的treeBusinessService就是DWR.xml中定义的
Java代码
  1. <create creator="spring" javascript="treeBusinessService">  


下面两句是使用DWR所必需的,原样加上即可。
Java代码
  1. <script type="text/javascript" src="dwr/engine.js "></script>   
  2. <script type="text/javascript" src="dwr/util.js "></script>  

有了上面的这些DWR配置,就能够以DWR的方式使用java的方法啦:
Java代码
  1. <script type="text/javascript">   
  2.            
  3.     treeBusinessService.getAllChildren(1,function(ret){   
  4.                                      alert("一共有"+ret.length+"个子节点");   
  5.                                    });   
  6.   
  7. </script>  

   function(ret)就是回调函数。因为treeBusinessService.getAllChildren执行的结果是List类型,DWR解析List到页面应该是javascript的对象数组,所以ret应该是个数组,ret.length是这个数组的长度。

   上面的例子只不过是原理性的介绍,帮助我们理解javascript如何和后台进行的交互。真正要实现DWRTree 还需要专门的DWRTreeLoader代理。下面这段代码很是重要,参考了ext官方bbs上的代码,并做了修改。先提供如下:
Java代码
  1. Ext.tree.DWRTreeLoader = function(config) {   
  2.   Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);   
  3. };   
  4.   
  5. Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {   
  6.    args:[],   
  7.    requestData : function(node, callback) {   
  8.     if (this.fireEvent("beforeload"this, node, callback) !== false) {   
  9.   
  10.         
  11.       var callParams = new Array();   
  12.       var success = this.handleResponse.createDelegate(this, [node, callback], 1);   
  13.       var error = this.handleFailure.createDelegate(this, [node, callback], 1);   
  14.       callParams.push(node.id);   
  15.       callParams.push({callback:success, errorHandler:error});   
  16.   
  17.       //todo: do we need to set this to something else?   
  18.       this.transId=true;   
  19.       this.dataUrl.apply(this, callParams);   
  20.     } else {   
  21.       // if the load is cancelled, make sure we notify   
  22.       // the node that we are done   
  23.       if (typeof callback == "function") {   
  24.         //alert(callback);   
  25.         callback();   
  26.       }   
  27.     }   
  28.   },   
  29.     processResponse : function(response, node, callback){   
  30.         try {   
  31.           for(var i = 0; i < response.length; i++){   
  32.                 var n = this.createNode(response[i]);   
  33.                 if(n){   
  34.                     node.appendChild(n);   
  35.                 }   
  36.             }   
  37.             if(typeof callback == "function"){   
  38.                 callback(this, node);   
  39.             }   
  40.         }catch(e){   
  41.             this.handleFailure(response);   
  42.         }   
  43.     },   
  44.   
  45.     handleResponse : function(response, node, callback){   
  46.         this.transId = false;   
  47.         this.processResponse(response, node, callback);   
  48.         this.fireEvent("load"this, node, response);   
  49.     },   
  50.   
  51.     handleFailure : function(response, node, callback){   
  52.         this.transId = false;   
  53.         this.fireEvent("loadexception"this, node, response);   
  54.         if(typeof callback == "function"){   
  55.             callback(this, node);   
  56.         }   
  57.     }   
  58.   
  59. });    


上面的代码可以直接在项目中使用,无需修改。
【六】最终DWRTree的实现包括 tree.js和 tree.html
tree.js完整代码如下:
Java代码 复制代码
  1.  Ext.onReady(function(){    
  2.      
  3. Ext.tree.DWRTreeLoader = function(config) {   
  4.   Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);   
  5. };   
  6.   
  7. Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {   
  8.    args:[],   
  9.    requestData : function(node, callback) {   
  10.     if (this.fireEvent("beforeload"this, node, callback) !== false) {   
  11.   
  12.         
  13.       var callParams = new Array();   
  14.       var success = this.handleResponse.createDelegate(this, [node, callback], 1);   
  15.       var error = this.handleFailure.createDelegate(this, [node, callback], 1);   
  16.       callParams.push(node.id);   
  17.       callParams.push({callback:success, errorHandler:error});   
  18.   
  19.       //todo: do we need to set this to something else?   
  20.       this.transId=true;   
  21.       this.dataUrl.apply(this, callParams);   
  22.     } else {   
  23.       // if the load is cancelled, make sure we notify   
  24.       // the node that we are done   
  25.       if (typeof callback == "function") {   
  26.         //alert(callback);   
  27.         callback();   
  28.       }   
  29.     }   
  30.   },   
  31.     processResponse : function(response, node, callback){   
  32.         try {   
  33.           for(var i = 0; i < response.length; i++){   
  34.                 var n = this.createNode(response[i]);   
  35.                 if(n){   
  36.                     node.appendChild(n);   
  37.                 }   
  38.             }   
  39.             if(typeof callback == "function"){   
  40.                 callback(this, node);   
  41.             }   
  42.         }catch(e){   
  43.             this.handleFailure(response);   
  44.         }   
  45.     },   
  46.   
  47.     handleResponse : function(response, node, callback){   
  48.         this.transId = false;   
  49.         this.processResponse(response, node, callback);   
  50.         this.fireEvent("load"this, node, response);   
  51.     },   
  52.   
  53.     handleFailure : function(response, node, callback){   
  54.         this.transId = false;   
  55.         this.fireEvent("loadexception"this, node, response);   
  56.         if(typeof callback == "function"){   
  57.             callback(this, node);   
  58.         }   
  59.     }   
  60.   
  61. });     
  62.   
  63.   
  64. var myTree = new Ext.tree.TreePanel({      
  65.         el:Ext.getBody(),     
  66.         autoScroll:true,   
  67.         animate:true,   
  68.         width:'300px',   
  69.         height:'800px',   
  70.         enableDD:true,   
  71.         containerScroll: true,    
  72.         root:new Ext.tree.AsyncTreeNode({   
  73.              text: '单位',   
  74.              draggable:false,   
  75.              id:'1' }),   
  76.         loader:new Ext.tree.DWRTreeLoader({    
  77.                    dataUrl:treeBusinessService.getAllChildren,    
  78.                    listeners : {   
  79.                               'beforeload' : function( node) {   
  80.                                    myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");   
  81.                                 }   
  82.                    }   
  83.                })   
  84.     });   
  85.        
  86.     myTree.render();   
  87.   
  88.   
  89.        
  90. });  

提个醒:这句
Java代码
  1. myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");  
不能错哦,它是和 DWRTreeLoader耦合的。

tree.html是这样的:
Java代码 复制代码
  1. <html>   
  2. <head>         
  3.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">      
  4. <title>ExtJS-树示例</title>   
  5. <link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />   
  6. <script type="text/javascript" src="ext2/adapter/ext/ext-base.js"></script>   
  7. <script type="text/javascript" src="ext2/ext-all.js"></script>   
  8.     
  9. <script type="text/javascript" src="dwr/interface/treeBusinessService.js "></script>   
  10. <script type="text/javascript" src="dwr/engine.js "></script>   
  11. <script type="text/javascript" src="dwr/util.js "></script>   
  12. <script type="text/javascript" src="js/tree.js"></script>    
  13.      
  14. </head>   
  15.        
  16. <body>   
  17.     
  18. </body>   
  19. </html>  



  好了,基于Spring+hibernate+dwr+EXTJs的DWRTreeLoader的实现就是这样。

 

就是那个下拉树。。。
ComboTree

Java代码 复制代码
  1.     Ext.QuickTips.init();   
  2.   
  3.                     var Artform = new Ext.form.FormPanel({   
  4.                         labelAlign: 'right',   
  5.                         labelWidth: 150,   
  6.                         width: 600,   
  7.                         frame: true,   
  8.                         items: [{   
  9.                             layout: 'column',   
  10.                             items: [{   
  11.                                 width:580,   
  12.                                 xtype:'fieldset',   
  13.                                 title: '输入标题',   
  14.                                 autoHeight:true,   
  15.                                 defaults: {width: 300},   
  16.                                 defaultType: 'textfield',   
  17.                                 items: [{   
  18.                                     fieldLabel: '标题',   
  19.                                     name: 'title',   
  20.                                     id:'title',   
  21.                                     allowBlank:false,   
  22.                                     blankText:'标题不能为空'  
  23.                                    // value:'adfadsfasd'   
  24.                                        
  25.                                 },{   
  26.                                     xtype:"combo",   
  27.                                     fieldLabel: '选择',   
  28.                                     name: 'combo',   
  29.                                     id:'combotree',   
  30.                                     store: new Ext.data.SimpleStore({fields:[],data:[[]]}),   
  31.                                     editable:false,//是否可编辑的表格   
  32.                                     selectClass:'',//适用于所有样式   
  33.                                     mode: 'local',   //本地数据   
  34.                                     triggerAction:'all',  //是否自动匹配   
  35.                                     autoHeight: true,   
  36.                                     tpl: "<tpl for='.'><div style='height:200px'><div id='tree'></div></div></tpl>",   //模板 循环   
  37.                                     emptyText:'请选择'  
  38.                                 }]   
  39.                             }]   
  40.                         },{   
  41.                             layout: 'form',   
  42.                             labelAlign: 'top',   
  43.                             items: [{   
  44.                                 xtype: 'htmleditor',   
  45.                                 fieldLabel: '请输入文章内容',   
  46.                                 id: 'context',   
  47.                                 height:400,   
  48.                                 allowBlank:false,   
  49.                                 blankText:'内容不能为空',   
  50.                                 anchor: '98%'  
  51.                              //   value:'adfadfasd'   
  52.                             }]   
  53.                         }] ,   
  54.                             buttons: [{text: '保存',handler:add},   
  55.                                       {text: '取消'}]    
  56.                     });   
  57.                 var treedata = new Ext.tree.TreeLoader({   
  58.                     url:'http://localhost:8080/pkm/register!queryChild.action'  
  59.                 });   
  60.                 var tree = new Ext.tree.TreePanel({   
  61.                     loader:treedata,   
  62.                     border:false,    
  63.                     root:new Ext.tree.AsyncTreeNode({text:'目录结构',id:'1'})   
  64.                 });   
  65.                    
  66.                 tree.on('click',function(node){      
  67.                       Artform.findById('combotree').value=node.id;//设置combo的键值   
  68.                       Artform.findById('combotree').setRawValue(node.text);   //给combo设置显示的值   
  69.                       Artform.findById('combotree').collapse();   //隐藏下拉列表中,如果它展开,这个属性将会完成数据的加载   
  70.                   });      
  71.                 Artform.findById('combotree').on('expand',function(){   
  72.                     tree.render('tree');//ComboBox的tpl里的<div id='tree'>这个ID可以改成别的, 但必须要在'expand'事件里, 将树显示在这个div上   
  73.                 });   
  74.                    
  75.                 function add(){   
  76.                     if(Artform.form.isValid()){   
  77.                         //btn.disabled=true;//确认按钮有效默认为false   
  78.                          Ext.MessageBox.show({   
  79.                            msg: '正在请求数据, 请稍侯',   
  80.                            progressText: '正在请求数据',   
  81.                            width:300,   
  82.                            wait:true,   
  83.                            waitConfig: {interval:200}   
  84.                      });//进度条显示   
  85.                         
  86.                      Ext.Ajax.request({   
  87.                         url:'http://localhost:8080/pkm/article!saveOrupdate.action',   
  88.                         params:{   
  89.                                 title:Ext.getCmp('title').getValue(),   
  90.                                 context:Ext.getCmp('context').getValue(),   
  91.                                 type:Artform.findById('combotree').value   
  92.                                 },   
  93.                         failure:function(){   
  94.                             Ext.MessageBox.alert('友情提示',"异步通讯失败,请与管理员联系!");   
  95.                         },   
  96.                         success:function(request){   
  97.                             Ext.MessageBox.hide();   
  98.                             Ext.MessageBox.alert("友情提示","信息保存成功");   
  99.                         }   
  100.                      });   
  101.                     }else{   
  102.                         Ext.MessageBox.alert("信息","请填写完整");   
  103.                     }   
  104.                 }   
  105.      Artform.render("form");   
  106.   
  107.   
  108. });  




我这是一个form 里面生成的下拉树,单独测试的时候 其实可以用一个简单的comboBox 做的,我这里为了方便就直接把我的代码拿过来和大家分享下

其实上面的代码 最重要的就只有一个部分,下拉树写出来很简单,问题就是怎么能取到值给form 让它提交到后台,

Java代码
  1. tree.on('click',function(node){      
  2.                       Artform.findById('combotree').value=node.id;设置combo的键值   
  3.                       Artform.findById('combotree').setRawValue(node.text);   //给combo设置显示的值   
  4.                       Artform.findById('combotree').collapse();   //隐藏下拉列表中,如果它展开,这个属性将会完成数据的加载   
  5.                   });     



秘诀就在这里,这里能给你提交到后台什么的 ,什么父节点不能选择,根节点不能选择什么的,那个简单,你直接把你的树写好,就OK 在哪里判断 如有不对,请拍砖—-—!!

原创粉丝点击