当前位置: 代码迷 >> Web前端 >> DWR学习札记(三)
  详细解决方案

DWR学习札记(三)

热度:165   发布时间:2012-10-13 11:38:17.0
DWR学习笔记(三)

四.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);

  相关解决方案