DWR学习笔记(三)

来源:互联网 发布:淘宝信誉买家未评价 编辑:程序博客网 时间:2024/05/16 06:56
四.DWR配置文件dwr.xml文件详解:放置到WEB-INF目录
 
  <dwr>
      <!-- 仅当需要扩展DWR时才需要 -->
      <init>
          <creator id="..." class="..." />
          <converter id="..." class="..." />
      </init>

      <!-- 没有它DWR什么也做不了 -->
      <allow>
          <create creator="..." javascript="..." />
          <convert converter="..." match="..." />
      </allow>

      <!-- 有必要告诉DWR方法签名 -->
      <signatures>...</signatures>
  </dwr>
 
  1.<init>标签:声明被用来创建远程beans和声明能被用来以某种过程转换的类。
      大多数例子你将不需要用它,如果你想去定义一个新的Creator或者Converter,就要在此声明。
      在init部分中定义只是告诉DWR这些扩展类的存在,给出了如何使用的信息。
      这时这里声明的类并没有被使用。这种方式很像Java中的import语句。
      多数类需要在使用前先import一下,但是只有import语句并不表明这个类已经被使用了。
      每一个creator和converter都用是id属性标识,以便后面使用时直接引用。
       
  2.<allow>标签:allow标签中定义了DWR能够创建和转换的类。
  
   A.<create>子标签:一个类对应一个<create>标签.
    
    i.creator属性:告诉DWR产生对应类的对象的方式,因为DWR要在页面通过js调用该类的对象的方法,
          而我们没有手动产生对象,那么对象只能是由DWR来产生,
          所以要告诉DWR产生对象的方式或者是new一个通过构造方法或者是通过从Spring的Ioc容器中取得等,
          总之要指定一个生成对象的方式。
          
       **注意:如果想写自己的creator创建器,必须在<init>里注册声明它,然后才可以在<create>的creator属性中指定并使用。
          
       (1)new创建器:指定DWR生成类的对象的方式是通过Java的new关键字,调用缺省构造(因为DWR将采用反射机制)方法产生对象。
           这也是DWR的默认creator,<create id="new" class="org.directwebremoting.create.NewCreator"/>
           所以这个配置不用放到<init>中声明,因为DWR内部已经加入。
         
       (2)none创建器:告诉DWR不要创建对象。有两种情况适合这种情况!!          
            <1>可以指定一个scope值(page除外),并且在调用该<create>对应类的方法之前已经把这个对象创建到指定的scope中,
            这时就不需要再创建对象了,用到时DWR会从scope指定的作用域中查找对象。
            <2>另一种情况是要调用的方法是静态的,这时也不需要创建对象。
            DWR会在调用创建器之前先检查一下这个方法是不是静态的。如果是静态的直接用就行。
       
       (3)spring创建器:通过Spring框架访问Bean
       
       (4)struts创建器:使用Struts的ActionFormBean
       
       (5)jsf创建器:使用JSF的Bean
       
       (6)pageflow创建器:访问Weblogic或Beehive的PageFlow。
       
       (7)script创建器(不常用):通过BSF使用脚本语言创建对象,例如BeanShell或Groovy。
             要使用这个创造器,你需要把一些辅助库放到lib目录,
             比如BSF的jar包,要用的脚本语言的jar包等。
             <用到时再看文档>
       
       (8)ejb3创建器(测试中,未投入使用):使用EJB3 session bean,一个正在实验的创造器,
                 用来访问EJB Session beans。直到进行更多的测试和正式的维护,
                 否则还不能作为产品被使用
       
    ii.javascript属性:指定<create>对应的类的对象在js中使用时的对象名(变量名),
           即JSP页面中可用指定的名字调用<create>对应的类中的方法。
           
       **注意:页面中还要导入以指定的javascript属性值为文件名的js文件
         <script type='text/javascript' src='dwr/interface/对象名.js'>
         这是DWR加载dwr.xml配置文件时内部在规定目录"dwr/interface/"动态生成的对应对象名的js文件,
         供页面中导入,以便实现调用java对象。
         
    iii.scope属性:和servlet、jsp中的scope属性一样,指定作用域范围,分别有page、request、session、application四个作用域。
          默认为page作用域。
          
    iv.<param>子标签:辅助指定的creator创造器属性值的其他参数,每种创造器对应的<param>子标签的值都不相同。
          例如"new"创造器需要知道要创建的对象类型是什么,<param name="class" value="对应的类全名" />
          每一种creator创造器的对应的<param>子标签的参数在各自的文档中能找到。
    
    v.<include>和<exclude>子标签:用于限定DWR在页面可以调用<create>对应类的方法。
             例如<create creator="new" javascript="dwrTest">
               <param name="class" value="com.lj.dwrproject.DWRTest" />
               <include method="sayHello" />
              </create>
             说明在页面通过DWR只能调用DWRTest类中的sayHello()方法;
             如果用<exclude>指定就是不能调用sayHello()方法,其他方法仍然可以调用。
    
    vi.<auth>子标签(了解):允许指定一个JavaEE的角色作为将来的访问控制检查:
    
            <create creator="new" javascript="dwrTest">
             <param name="class" value="com.lj.dwrproject.DWRTest" />
             <auth method="sayHello" role="admin" />
            </create>
    
    **注意:
      (1)使用静态方法时,DWR会在调用创建器之前先检查一下这个方法是不是静态的,
         如果是那么创造器不会被调用。这个规则适用于所有创造器。
      (2)scope属性:指定的范围是<create>对应的类对象的保存作用域,对于DWR1.x版本,
           它在每次请求时都会调用一次setAttribute()方法,就是每次在页面调用对象的方法时,
           DWR都会调用一侧scope.setAttribute()方法;
           而DWR 2只在第一次创建对象时调用scope.setAttribute()方法,
           解决了如果使用servlet的事件机制时,
           如HttpRequestAttributeListener每次都会触发属性事件的麻烦。
      
      (3)使用单例类时(了解),对于单例类的创建,最好使用BeanShell和BSF来实例化对象,即script创建器。
      
   B.<convert>子标签:为了确保DWR页面调用java对象方法传入参数时所有的参数能被正确的转换。
          之所以涉及到转换的原因就是,我们是通过js来调用的java对象方法,传入的参数也都是js的类型,
          但是DWR会在内部真实的通过传入的js参数调用对应的java对象的方法,
          此时就应该保证js的类型能够正确的转换成java中的参数类型。
          例如java方法sayHello(String name)接受java的String类型,
          但是js调用是传入的是一个var类型的,为了让DWR内部调用sayHello时成功将var类型转换成String类型。
          当然这个是不用特别指出的,但是有时我们会自定义一些类型,此时就要声明转换器。
          
      (1)不需要用<convert>指定转换器的类型有:这些DWR默认支持它们的转换
         
         <1>所有的基本数据类型,boolean, int , double等
         <2>包装类,Boolean, Integer等
         <3>java.lang.String
         <4>java.util.Date 和 java.sql.Times,java.sql.Timestamp
         <5>数组,但是限制为存放以上类型的数组,不包括自定义的或者集合的数组。
         <6>DOM对象(来自于DOM, XOM, JDOM和DOM4J)
         
      (2)Bean和Object转换器:DWR是支持这两种参数的转换的,只不过默认情况是关闭状态。
             Bean转换器可以把POJO转换成Javascript的接合数组(类似与Java中的Map),
             或者反向转换(即java对象的方法返回一个Bean对象,js中接受的将会是转换好了的接合数组)。
             Object转换器与Bean转换器很相似,不同的是它直接应用于对象的成员,而不是通过调用getter和setter方法。
             这也要求作为Bean参数的对象必须符合javaBean的规范(要有getter和setter方法)
         **说明:应用的场合就是当我们定义的java类中的方法的参数中有自定义的Bean规范的自定义对象,
           那么在页面js调用传递参数的时候会出现转换异常,因为DWR不知道怎么转换,
           此时就可以为该参数对象的java类指定开启转换器功能。
           
         **使用方法:
            <1>只为单个类开启Bean转换器功能,也就是说当其他Bean类也作为参数时,它的Bean转换器是关闭的。
               <convert converter="bean" match="your.full.package.BeanName"/>
               
            <2>为一个包中的所有类都打开Bean转换器功能
               <convert converter="bean" match="your.full.package.*"/>
            
            <3>为所有类都打开转换器功能
               <convert converter="bean" match="*"/>
            
            <4>Object转换器的使用方法道理相同
            
         **详细说明:像上面通过converter指定bean属性值为什么就可以开启转换器功能呢?
            是因为DWR内部已经实现了对bean值将会分配一个BeanConverter类作为对应参数类的转换器,
            也就是当涉及到指定的类的转换时,那么BeanConverter就会进行转换功能,这都是DWR内部的实现。
            对于converter="object"的时候,那么DWR将会通过ObjectConverter转换类来处理指定的要进行转换的类。
            
         **限制转换器(基本不会用):类似<create>中的<include>和<exclude>子标签,
              只不过只有BeanConverter及其子转换器HibernateBeanConverter有这个功能。
              也就是只有converter="bean"时才能用此功能。
              <convert converter="bean" match="com.lj.dwrproject.DWRTest">
             <param name="include" value="property1, property2" />
              </convert>
              意思是DWR使用转换器BeanConverter时只能调用getProperty1()和getProperty2()方法完成转换。
              
         **访问对象的私有成员(基本不会用):用的时候可以查看文档。
         
      (3)集合类型转换器:默认是开启的上面已经说明,此处类出DWR内部的配置供了解参考。此处我们分析它的缺点!!
         
         <1><convert converter="collection" match="java.util.Collection"/>
         <2><convert converter="map" match="java.util.Map"/>
         
         **缺点与不足:用反射机制是没有方法明确集合里面是什么类型的。
              所以这两个转换器不能把集合里面的东西转换成有意义的Javascript对象。
              
         **解决方法:可以在dwr.xml中<signatures>标签语法声明集合中元素的类型,使之正确转换。
            <详细见下边>
            
      (4)枚举类型转换器(了解):用时可以查看文档
      
      (5)DOM对象:默认也是开启的。
         DWR可以自动转换来之DOM,DOM4J,JDOM和XOM的DOM树。
         可以简单得用上面这些类库返回一个Document、Element或者Node,DWR会把他们自动转换成浏览器的DOM对象。
        
        **小小的问题(了解):在程序启动的时候会有一个常见的关于JDOM转换器的警告,
             可以放心的忽略它,除非你要用JDOM:
             INFO: Missing classdef for converter 'jdom'. 
             Failed to load uk.ltd.getahead.dwr.convert.JDOMConverter. Cause: org/jdom/Document
             因为DWR没有办法知道你是否想用JDOM,所以这个信息设在INFO级别的。
         
  3.<signatures>标签:DWR使用反射机制在转换过程中找到它应该使用的类型。
          有时候类型的信息无法获得,在这种情况下你要在此处用方法签名给予声明。
          signatures段使DWR能确定集合中存放的数据类型(泛型指定的类型)。
       
   A.**主要目的:就是让DWR在页面中通过js调用java方法时,用来确定集合泛型参数中的类型参数,
        以完成正确的从js类型转换成java类型,正确的传入调用的方法中,完成操作。
      
   B.例如下面的定义中我们无法知道list中存放的是什么类型。
       
    public class Check{
     public void setLotteryResults(List nos){
      ......
     }
    }
    
    **问题:如果在jsp中通过js调用该方法并且传递参数时,
      DWR不知道将js生成的集合中的元素转换成java的什么类型然后传给该方法。
      
    **解决方案:重新声明了一下Check类中的方法,此时通过了泛型,
       这样调用时传的参数集合中的元素DWR就知道转换成java的什么类型进而传给该方法。
       <signatures>
        <![CDATA[
         //导入需要的类,和java中import一样,
         //导入了类就相当于告诉DWR转换的类型是什么类型了,默认java.lang包中的类不用导入!
         import java.util.List;
         import com.example.Check;
         Check.setLotteryResults(List<Integer> nos);
        ]]>
       </signatures>
       
   C.用与不用signatures段举例说明:
     
    i.DWR调用这样的方法传参数时DWR自己会知道
      怎样将js类型转换成对应的java类型,因为没有泛型参数或说成涉及不到泛型参数。
       
      public void method(String p);
      public void method(String[] p);
       
    ii.DWR调用传参数时,可以知道泛型指定的类型怎么转换,不需要signatures段特意标识。
     
      public void method(List<String> p);
      public void method(Map<String, String> p);
      public List<Date> method(String p);
       
    iii.DWR调用传入参数时,将不知道怎样转换,
     其实主要是不知道怎样将js中的类型转换成对应的WibbleBean类型,
     随意应该通过signatures来导入一下该类的全名,以便告诉DWR进而完成转换。
        
      public void method(List<Date> p);
      public void method(Map<String, WibbleBean> p);
原创粉丝点击