把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]

要读懂我这篇文章估计需要一些前期知识:
你要知道Spring是什么,并且要知道Spring已经出了2.0的版本了。
你要知道DWR是什么,并且要知道DWR也要出2.0的版本了。

呵呵,开个玩笑……。这年头在BlogJava上混的,估计没几个不知道上面这两个项了。

好了,现在言归正传。DWR本身就提供对Spring的支持,可以直接把Spring中的Bean暴露给客户端浏览器的Javascript调用。在dwr.xml中的写法是这样的:

< dwr >
    
< allow >
        
< create  creator ="spring"  javascript ="AjaxPortalService" >
            
< param  name ="beanName"  value ="AjaxPortalService" />
            
< include  method ="changeWondowState" />
            
< include  method ="changeWorkbenchState" />
            
< include  method ="changeWindowOrder" />
        
</ create >
    
</ allow >
</ dwr >


这 样写到也没什么,只是把项目分模块以后,虽有的配置都写到一个dwr.xml文件里面维护起来比较麻烦,尤其再遇到版本管理中的代码合并。所以曾经我扩展 了DWR,让它可以从多个文件读取配置信息。然后每个模块自己一个配置文件,跟着source一起走。这样做也有问题,就是现在Java应用程序的配置文 件太多啦!Spring的配置,WebWork的配置,Hibernate的配置,DWR的配置,再加上一些杂七杂八的xml和properties。看 着这些配置文件简直要疯掉了。

正在此时,spring2横空出世,现在你可以把一些配置文件合并到一起了。正好趁此机会体验一下Spring2的自定义schema特性。

目标:
把DWR的配置写成这样:

<? xml version="1.0" encoding="GBK" ?>
< beans  xmlns ="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx
="http://www.springframework.org/schema/tx"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xmlns:dwr
="http://www.devside.org/schema/spring/dwr"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
           http://www.devside.org/schema/spring/dwr http://www.devside.org/schema/spring/dwr.xsd"

    default-autowire
="byName" >
    
    
< bean  id ="departmentDao"  class ="cn.com.legendapl.hellostruts2.dao.DepartmentDao" />
    
< bean  id ="employeeDao"  class ="cn.com.legendapl.hellostruts2.dao.EmployeeDao" />
    
< bean  id ="companyService"  class ="cn.com.legendapl.hellostruts2.service.CompanyService" />
    
    
< aop:config >
        
< aop:pointcut  id ="companyServiceOperation"  expression ="execution(* cn.com.legendapl.hellostruts2.service.ICompanyService.*(..))"   />
        
< aop:advisor  advice-ref ="txAdvice"  pointcut-ref ="companyServiceOperation"   />
    
</ aop:config >     
    
    
< bean  id ="ajaxCompanyProxy"  class ="cn.com.legendapl.hellostruts2.ajax.AjaxCompanyProxy" />
    
    
< dwr:allow  id ="ajaxCompanyProxyAllow" >
        
< dwr:create  beanName ="ajaxCompanyProxy"  javascript ="CompanyProxy" >
            
< dwr:include  method ="findEmployeeById" />
        
</ dwr:create >
        
< dwr:convert  converter ="bean"  match ="cn.com.legendapl.hellostruts2.entity.*" />
    
</ dwr:allow >
</ beans >


重点在这里:
    < dwr:allow  id ="ajaxCompanyProxyAllow" >
        
< dwr:create  beanName ="ajaxCompanyProxy"  javascript ="CompanyProxy" >
            
< dwr:include  method ="findEmployeeById" />
        
</ dwr:create >
        
< dwr:convert  converter ="bean"  match ="cn.com.legendapl.hellostruts2.entity.*" />
    
</ dwr:allow >

好了现在动手开始做。

原理其实很简单,现在看张图。画的不好,敬请原谅!



把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]

从这样图中我们可以看出我们要做如下工作:
1、做一个dwr.xsd,定义spring配置文件中的dwr这部分配置的schema。
   要做这个需要有一定xml和xsd的知识,我也是现学现用啦!

把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]<? xml version="1.0" encoding="UTF-8" ?>
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]
< xsd:schema  xmlns ="http://www.devside.org/schema/spring/dwr"
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     xmlns:beans
="http://www.springframework.org/schema/beans"
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     targetNamespace
="http://www.devside.org/schema/spring/dwr"  
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     elementFormDefault
="qualified"     
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     attributeFormDefault
="unqualified" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:import  namespace ="http://www.springframework.org/schema/beans"  schemaLocation ="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:element  name ="allow" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:complexType >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]             
< xsd:complexContent >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                 
< xsd:extension  base ="beans:identifiedType" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                     
< xsd:sequence >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                         
< xsd:element  name ="create"  type ="createType"  minOccurs ="0"  maxOccurs ="unbounded" />                 
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                         
< xsd:element  name ="convert"  type ="convertType"  minOccurs ="0"  maxOccurs ="unbounded" />                 
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                     
</ xsd:sequence >   
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]                 
</ xsd:extension >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]             
</ xsd:complexContent >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
</ xsd:complexType >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:element >     
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:complexType  name ="createType" >         
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:sequence >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]             
< xsd:element  name ="auth"  type ="authType"  minOccurs ="0"  maxOccurs ="unbounded" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]             
< xsd:element  name ="include"  type ="includeType"  minOccurs ="0"  maxOccurs ="unbounded" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]             
< xsd:element  name ="exclude"  type ="excludeType"  minOccurs ="0"  maxOccurs ="unbounded" />                             
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
</ xsd:sequence >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="beanName"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="javascript"  type ="xsd:string"  use ="required" />                                                 
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:complexType >    
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:complexType  name ="convertType" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="converter"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="match"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:complexType >   
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:complexType  name ="authType" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="method"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="role"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:complexType >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:complexType  name ="includeType" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="method"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:complexType >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
< xsd:complexType  name ="excludeType" >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]         
< xsd:attribute  name ="method"  type ="xsd:string"  use ="required" />
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]     
</ xsd:complexType >
把DWR的配置写到Spring的配置文件里(Spring2 新特性-自定义schema初体验)[转]
</ xsd:schema >

2、 我们要做一个DWRNamespaceHandler来处理DWR的配置信息,其实里面就做一件事把AllowBeanDefinitionParser 注册给allow节点。因为我们dwr的配置部分根节点就一个标签allow,所以我们就做一个用于解析allow标签的 AllowBeanDefinitionParser解析器就行。如果我们的根节点还有其他的标签,同样也要做相应的解析器。

public   class  DWRNamespaceHandler  extends  NamespaceHandlerSupport {

    
public   void  init() {
        
// 把AllowBeanDefinitionParser注册到allow节点
        registerBeanDefinitionParser( " allow " new  AllowBeanDefinitionParser());
    }

}


其实难点是做AllowBeanDefinitionParser,这里你需要一些DOM模型的知识,来操作配置节点的内容。然后根据内容进行处理。在这里我们,需要做三件事:
   [1]  把配置节点的内容转换成对象模型,即AllowBean(其实就是一些POJO罢了)。
   [2]  把这个AllowBean注册给Spring的Context,这一步是可选的。因为我们主要是把这个Bean给DWR,当然顺道给Spring一份也没什么问题。
   [3] 把这个AllowBean注册到AllowBeanHolder。

3、AllowBeanHolder。
   其实这就是个简单的singleton类,整个运行期只有一个实例。它就像一个容器,AllowBeanDefinitionParser往里放,DWR的Configuration再从这里取。

4、扩展DWR的DefaultConfiguration,我们做一个SpringConfiguration。DWR的DefaultConfiguration是负责读取配置信息的。我们在其中加入从AllowBeanHolder读取配置信息的功能即可。

5、扩展DWR的DWRServlet,我们做一个SpringDWRServlet,原来的DWRServlet加载的是DefaultConfiguration,我们的Serlvet加载我们自己的SpringConfiguration即可。

6、万事俱备,只欠东风啦。就是让Spring知道我们干了这些!
   在META-INF目录下(如果没有在src目录下创建一个)加入spring.handlers和spring.schemas两个文件。
   spring.handlers中的内容:
   http\: // www.devside.org/schema/spring/dwr=org.devside.core.support.dwr.DWRNamespaceHandler
   spring.schemas中的内容:
   http\://www.devside.org/schema/spring/dwr.xsd=org/devside/core/support/dwr/dwr.xsd
   
  
注意不要写错字哦,我一开始就写错一个字母,结果怎么调试都不能成功,还以为Spring2有问题呢。

ok了,下面我们就可以写一个spring的配置文件来试试喽。

下面提供两个源码包,一个是spring-dwr的源码,一个是hellosturts2,一个struts2+spring2+hibernate3.2的例子,其中有用到spring-dwr的例子。

为了减小容量,我把jar都去掉了,lib目录下提供了一个列表,你可以自己去找相关的jar包。

http://www.blogjava.net/Files/mstar/HelloStruts2.zip

http://www.blogjava.net/Files/mstar/spring-dwr.zip