??xml version="1.0" encoding="utf-8" standalone="yes"?>
M一个dwr.xml的文仉需要包含DWR DOCTYPE的声明行Q格式如下:(x)
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
整个配置文g的大体结构如下:(x)
<dwr>
<init>
<creator id="..." class="..."/>
<converter id="..." class="..."/>
</init>
<allow>
<create creator="..." javascript="..." scope="...">
<param name="..." value="..."/>
</create>
<convert convertor="..." match="..."/>
</allow>
<signatures>
...
</signatures>
</dwr>
有几个术语有必要理解,参数叫做converted,q程Bean叫做created.如果q程Bean A有个Ҏ(gu)A.blah(B),那么你需要ؓ(f)A建立一个created,为B建立一个converted.
配置文ginit部分声明那些用于建立q程bean和在Ҏ(gu)调用中{换bean的类.q部分是可选择性配|的,多数情况下可以不必用它,如果你想定义一个新的creator或者converter那么必d部分中声?but do double check on the ones that are currently available first.
在init部分的作用是告诉DWR一些类实例和关于这些类怎样q行的信?实际上ƈ不会(x)使用.q有点向java中的import语句,多数cd使用之前需要引?但引入了cdƈ不意味着q些在?每个creator和converter需要有个id属性来允许以后q行引用.
配置文g的allow部分定义哪些cd以徏立和转换,每个被准许的c都可以有一?create'或?convert'配置?下面列出的类的{换在默认情况下不需要进一步的讄.
1、所有基本类?boolean,int,double{等
2、基本类型的对象形式实现的类,Boolean,Integer{等
3、java.lang.String
4、java.util.date 和三个SQL形式的派生类
5、以上所有类型的数组形式
6、以上所有类型的集合,List,Set,Map(有些局限?
However nothing is added to the list of classes that can be created (i.e. put up for remoting) without you declaring it.
2、The Converters
DWR已经默认定义和初始化了常用的Converter,他们分别如下Q?/font>
<converter id="null"
class="uk.ltd.getahead.dwr.convert.NullConverter"/>
<converter id="primitive"
class="uk.ltd.getahead.dwr.convert.PrimitiveConverter"/>
<converter id="bignumber"
class="uk.ltd.getahead.dwr.convert.BigNumberConverter"/>
<converter id="string"
class="uk.ltd.getahead.dwr.convert.StringConverter"/>
<converter id="date"
class="uk.ltd.getahead.dwr.convert.DateConverter"/>
<converter id="array"
class="uk.ltd.getahead.dwr.convert.ArrayConverter"/>
<converter id="map"
class="uk.ltd.getahead.dwr.convert.MapConverter"/>
<converter id="collection"
class="uk.ltd.getahead.dwr.convert.CollectionConverter"/>
<converter id="bean"
class="uk.ltd.getahead.dwr.convert.BeanConverter"/>
<converter id="hibernate"
class="uk.ltd.getahead.dwr.convert.HibernateBeanConverter"/>
<converter id="dom"
class="uk.ltd.getahead.dwr.convert.DOMConverter"/>
<converter id="dom4j"
class="uk.ltd.getahead.dwr.convert.DOM4JConverter"/>
<converter id="jdom"
class="uk.ltd.getahead.dwr.convert.JDOMConverter"/>
<converter id="xom"
class="uk.ltd.getahead.dwr.convert.XOMConverter"/>
<converter id="servlet" class="uk.ltd.getahead.dwr.convert.ServletConverter"/>
q里仅仅是定义了Converterq且单的攑֜<convert….>元素之内,M?lt;convert….>元素内容都有两个必须定义的属?一个是对converter定义的引用和converter能够转换的类.
例如最单的converter是null converter,它作用是把null和voidD{换成javascript的null和undefined?它是所有converter中最单的,p调用java的静态方法一?所以ƈ不需要创建对?
默认的时候DWRjava voidD{换成javascript的null值就是这栯|?/font>
<convert converter="null" match="void"/>
. 有时java.lang.Void也需要进行这L(fng)转换,所以设|也是相似的<convert converter="null" match="java.lang.Void"/>.从java中传递null值到javascript是没有Q何危险性的,所以DWR这个作为默认的converter,所以你自己不用再把q个converterd到配|文件的<allow>部分中去.
基本cd的converter转换int,boolean,double{?当然q包括对应的对象形式Integerv,Boolean{等.DWR中在allow预定义了16个配|项目分别用于所有基本类型的转换.pq样<convert converter="primitive" match="java.lang.Long"/><convert converter="primitive" match="long"/>.
Stringcd和Date同样预先定义了Converter,q些converter都没有办法进行改变的,所有的String,Date和数值类型都l一采用默认的converter.
2.1 Array Converters
Array的配|项目没有上面介l的那么直观,默认情况下DWR装蝲所有的基本cd和可装蝲的对?q些包括String,Date{先前介l的cd.java高E序员可能会(x)理解Z么match的这行有点奇?
<convert converter="array" match="[Z"/>
<convert converter="array" match="[B"/>
<convert converter="array" match="[S"/>
<convert converter="array" match="[I"/>
<convert converter="array" match="[J"/>
<convert converter="array" match="[F"/>
<convert converter="array" match="[D"/>
<convert converter="array" match="[C"/>
<convert converter="array" match="[L*"/>
*W号在上面没有提?其实q是个可以表CZQ何字W的通配W号.q些数组可装载的的类型和其他可装载的cd是一L(fng).
2.2 Bean Converters
一U不能采用默认方式定义的converter是Bean Converter,q个是将POJO对象转换成javascript相关的数l?反向也一?Z安全因素的考虑q种cd的converter不能采用默认的方式实?
假设有个beanq且通过<create ...>语句讄成远E可?有种cd的参C本n是一个带有setter的java bean,但setter?x)生严重的隐(zhn)?d者可能促使这隐?zhn)的发?通过下面的语句就可以讄但个cȝbean converter
<convert converter="bean" match="your.full.package.BeanName"/>
要想允许转换指定包或子包下所有类的{换可以按照下面的讄
<convert converter="bean" match="your.full.package.*"/>
很明?可以采用下面的方式来转换所有的java bean
<convert converter="bean" match="*"/>
2.3 Restricting Property Conversion(指定属性{?
象用exclude和incluce来通知DWR隔离creator的方法一?converter也有一个类似的配置Ҏ(gu).因ؓ(f)指定属性{换只有针对bean才有?基本cd的{换没有必要指定属?,q个功能只能应用与特定的converter即BeanConverter和从ơ类z的所有类.相关配置语法如下
<convert converter="bean" match="com.example.Fred"/>
<param name="exclude" value="property1, property2"/>
</convert>
q样可以限定DWR不能调用Fred对象的getProperty1()和getProperty2()Ҏ(gu),通常q被成ؓ(f)拒绝讉K方式,当然你也可以采用下面的方式配|可以访问的Ҏ(gu)(授权讉K方式)
<convert converter="bean" match="com.example.Fred"/>
<param name="include" value="property1, property2"/>
</convert>
较好的安全控制大部分都是采用授权讉K方式.
2.4 Collection Converters
DWR最后两个默认的converter是Maps和Collections
<convert converter="collection" match="java.util.Collection"/>
<convert converter="map" match="java.util.Map"/>
通常converter是采用递归Ҏ(gu)转换集合中的所有对?
q里有两个地斚w要注意:(x)
仅仅通过反射Ҏ(gu)没有办法知道集合元素中的cd,所以上面的两个converter能将M集合转换成相对javascript而言有意义的对象.然而没有办法将不同的集合类cd分别采用不同的{换方?因ؓ(f)没有办法完全自动q行转换,我们可以应用dwr.xml文g的special signatures syntax配置部分讄cd的{换处理过E?
2.5 DOM Objects
DWR 自动DOM、DOM4J、JDOM和XOM转换成DOM?前面q几U类型都仅仅q回Document,Element,Node.DWR?x)自动将q些转换成浏览器DOM对象.通常在启动JDOM Converter时会(x)有一个提CZ?除非你想采用JDOMconverter否则可以忽略.
INFO: Missing classdef for converter 'jdom'. Failed to load uk.ltd.getahead.dwr.convert.JDOMConverter. Cause: org/jdom/Document
因ؓ(f)DWR没有办法知道你是否采用jdom converter,所以提CZ息是infoU别.如果你想采用jdom converter,你必d清楚地知道jdom converter是否可以被加?q就是DWR保留上面的提CZ息的原因.
3 The Creators
DWR共有三种Creator,最单的”new”是调用bean的默认构造函数创建实?”scripted”允许采用其他脚本语言创徏实例.如BeanShell.在远Ebean的默认构造函C能进行进一步配|的情况下这U类型的creator比较有用.”Spring”cd允许你通过spring创徏实例.
下面是关于creator的参考资料和配置参数说明.
Creator
Parameter
User
new
class
cȝ全名U?包括包\?
scripted
language
BSF框架支持的脚本语a名称(BSF为apache目)
scripted
script
q回q程对象的脚?脚本可以指定一些属?多数情况下一般只讄param节点配置.属性很设|?
spring
Location*
M以location开头的参数,每个参数都是指定一个spring的配|文?在参数没有设|的情况下DWR?x)去dspring的全局的配|文?
spring
beanName
从配|文件中d的bean的名U?br />
“scope参数允许你配|creator的生命周?共有以下几个选项:application,session,request,page.q些参数对于用过jsp或servlet的开发h员ƈ不陌?
3.1 Uing static methods
如果你想q程调用一个creator的静态方?q且creator是newcd.因ؓ(f)调用q程bean的方法前DWR不会(x)将要执行的Ҏ(gu)是不是静态方?如果是静态方法那么creator׃用创?q种机制可以适用Mcd的creator,但newcd的creator是最单配|的.
3.2 Security
Creator可以配置cȝ成员函数的访问权?creator有授权访?指明可以被访问的Ҏ(gu))和拒l访?指明不允许访问的Ҏ(gu))两种配置方式.
如果要设|除了setWibbleҎ(gu)之外的所有方法都不可讉K可以采用下面的设|?
<create creator="new" javascript="Fred">
<param name="class" value="com.example.Fred"/>
<exclude method="setWibble"/>
</create>
如果采用j2ee讉K角色控制的模?/p>
<create creator="new" javascript="Fred">
<param name="class" value="com.example.Fred"/>
<auth method="setWibble" role="admin"/>
</create>
3.3 The 'spring' Creator
3.4 The 'new' Creator
DWR已经默认定义了new creator.
<creator id="new" class="uk.ltd.getahead.dwr.create.NewCreator"/>DWR已经这配置C内置的dwr.xml文g?q不需要进行额外的配置.
Creator通过调用cȝ默认的构造方法创建实?应用new creator有以下几个优?
? 安全?nbsp;
生命周期比较短的creator可以得到更好的安全?通过不同的应用情况设|适合的生命周?
? 低内存开销
在访问量比较大的情况?可以不用担心发生内存泄露的情?
配置一个creator的创建和q程Ҏ(gu)调用讄:
<allow>
<create creator="new" javascript="Blah">
<param name="class" value="java.util.Date"/>
</create>
...
</allow>
上面的配|信息表C将java.util.date提供l客L(fng)调用,q且引用名称是Blash.当你在客L(fng)调用Blash.toString(reply)?后台采用java.util.date的默认构造方法创Z个实?然后调用实例的tostringҎ(gu).客户端的javascript返回给reply对象(此时reply是java.util.date的字W串形式)
3.5 The 'scripted' Creator
DWR 已经默认配置了scripted creator配置,
<creator id="script" class="uk.ltd.getahead.dwr.create.ScriptedCreator"/>q种cd的creator采用BSF执行脚本语言q返回bean.例如
<allow>
...
<create creator="script" javascript="EmailValidator">
<param name="language" value="beanshell"/>
<param name="script">
import org.apache.commons.validator.EmailValidator;
return EmailValidator.getInstance();
</param>
</create>
...
</allow>
4 Signatures in dwr.xml
Signatures部分用于配置Collections中装载对象元素的cd.举个例子来说:下面的java代码没有办法对List集合中的对象q行转换.
public class Check
{
public void setLotteryResults(List nos)
{
...
}
}
Singatures配置允许我们对DWR要操作的对象cdq行配置.对于了解JDK5泛型~程的开发h员来说下面的格式是很Ҏ(gu)理解?
<signatures>
<![CDATA[
import java.util.List;
import com.example.Check;
Check.setLotteryResults(List<Integer> nos);
]]>
</signatures>
DWR有个专门用于解析上面配置语句的解析器,虽然上面的是JDK5中才有的Ҏ(gu)?因ؓ(f)有解析器的原因这也可以应用与JDK5之前的版?
解析规则是不可见?但有两种例外情况.
一U情冉|因ؓ(f)DWR1.0的解析器中有个Bug,在有些场合会(x)无法处理q回值的cd.所以应该要避免q种情况的发?
一U情冉|因ؓ(f)解析器是一个语法宽杄解析?他不象编译器一样对语法有非怸格的要求,所有有时可能一些重要的语句没有配置而无法事先发?
<signatures>
<![CDATA[
import java.util.List;
Check.setLotteryResults(List<Integer>);
]]>
</signatures>
DWR的将来版本可能会(x)采用W合java官方规范的解析器,q样可以避免许多出错的情?
Signature部分只用于泛型参数到基本cd参数的{?对于其他的类型DWR采用反射机制或运行时cd来确?在没有泛型参数的情况下可以不配置Signature.
public void method(String p);
public void method(String[] p);
下面的就需要配|?因ؓ(f)反射机制无法完成ơ类功能.
public void method(List<Date> p);
public void method(Map<String, WibbleBean> p);
下面可以不用配置,DWR可以自动完成转换.
public void method(List<String> p);
public void method(Map<String, String> p);
下面可以不用讄,DWR可以采用q行时{?
public List<Date> method(String p);
有一个值得注意的地Ҏ(gu)在javascript中所有对象的keys都是一个字W串,你也可以把其他对象作为keys.他们在用之前都?x){换成字符串Ş?DWR1.x采用这个特性来转换成String.以后对象的{换将?x)在服务器端完?
5 Scripting Introduction
DWR生成的javascript代码和java代码很相似ƈ通过dwr.xml配置输出.相比普通java异步调用之下,通过ajax生成q程接口和java 代码的最大挑战是AJAX异步功能.
DWR通过引入一个回调函敎ͼ当数据从服务q回数据是调用这个函数。有两种推荐的方法用回调函数。一在参数列表加入回调功能。二增加调用元数据对象调用?/p>
也可以将回调的功能放在参数列表的前头Q但是不使用q样的用?因ؓ(f)在处理自动HTTP对象时候会(x)出现问题。这些方法一般会(x)保持向后兼容?/p>
5.1 Simple Callback Functions
假设有个下面的javaҎ(gu)?/p>
public class Remote
{
public String getData(int index) { ... }
}
在javascript中就可以以下面的方式引用?/p>
<script type="text/javascript"
src="[WEBAPP]/dwr/interface/Remote.js"> </script>
<script type="text/javascript"
src="[WEBAPP]/dwr/engine.js"> </script>
...
function handleGetData(str)
{
alert(str);
}
Remote.getData(42, handleGetData);
“42”只是一个传lgetdataҎ(gu)的参数。当然你可以采用下面的写法?/p>
Remote.getData(42, function(str) { alert(str); });
5.2 Call Meta-Data Objects
另一U用回调功能的Ҏ(gu)是指定一个回调功能选项或其他可选项。上面的例子变成下面的形式?/p>
Remote.getData(42, {
callback:function(str) { alert(str); }
});
q个Ҏ(gu)h以下几个优点Q可以依照你的编码习(fn)惯来~写E序Q更重要的是允许你增加额外的调用选项?/p>
5.3 Timeouts and Handling Errors
除了使用回调功能你还可以指定时旉和错误处理方法。例如:(x)
Remote.getData(42, {
callback:function(str) { alert(str); },
timout:5000,
errorHandler:function(message) { alert("Oops: " + message); }
});
5.4 Finding the callback method
下面有几个实例来说明回调功能各个参数选项的配|?因ؓ(f)javascript是不支持函数重蝲的?/p>
Remote.method({ timeout:3 }, { errorHandler:somefunc });
上面的两个参C个是bean的参C个是回调元数据对象。但是没有方法去区别q两U参数选项。在抛开特定的浏览器环境Q我们假设null==undefinedQ所以具有以下规则:(x)
一、如果一个函数的每个调用都是回调函数Q那么他没有调用元数据对象Q所有的参数都是普通java参数?/p>
二、如果一个最后一个参数具有一个回调功能,那么q个参数是调用元数据对象。其余的是普通java参数?/p>
三、如果第一个参Cؓ(f)nullQ我们就认ؓ(f)没有回调功能。其余的是普通java参数。此外还要检查最后一个参数是否ؓ(f)nullQ如果是则会(x)l予提示信息?/p>
四、如果最后一个参Cؓ(f)nullQ则没有回调功能?/p>
五、还有一个不是很好的U定格式Q要表示错误信息?/p>
6 Engin.js文g
q个文g是DWR的引擎文Ӟ他承担着把后台自动生成的javascript接口与前台调用之间的衔接责Q。所以Q何用DWR的地斚w需要这个文件?/p>
每个使用DWR的页面都必须引入q个文gQ?/p>
<script type='text/javascript'
src='/[YOUR-WEB-APP]/dwr/engine.js'>
</script>
6.1 Call Batching
应用扚w功能可以一ơ性调用多个远EbeanҎ(gu)Q因Z是将多个调用做ؓ(f)一ơ请求,q就减少了与服务器的交互。可以减许多的开销?/p>
一个批量方法调用以DWREngine.beginBatch()开始WREngine.endBatch()l束。当DWREngine.endBatch()被调用时p明开始调用批量方法,DWR将q些Ҏ(gu)打包在一起作Zơ请求发送给服务器?/p>
DWR?x)确保所有的Ҏ(gu)都回被调用,所以用批量功能是要注意是否提交了扚w调用Q如果没有提交批量调用那么这些需要调用的Ҏ(gu)永q排在调用队列中直到提交扚w调用?/p>
注意Q批量调用方法会(x)有一些缺点,比如他不能在那些已经帮定在一L(fng)Ҏ(gu)调用序不能保证同步?/p>
例如所有的调用元数据对象的接管函数Q超时设?错误处理{的调用都是在批量的U别上,而不是在调用的别上。如果一个批量调用含有两个不同超时时间设定的Ҏ(gu)Q那么除了最后一个之外的所有其他方法的时讑֮都被忽略?/p>
6.2 Call Ordering
因ؓ(f)AJAX是个普通的异步q程Ҏ(gu)调用模式Q所以远E调用的q回l果的顺序可能和你发送请求的序不一致。DWREngine.setOrdered(boolean)Ҏ(gu)允许你设|远E调用返回结果的序和你发送调用请求的序保持一致。DWR是通过一个远E方法调用已l结束后在发送下一个调用请求来实现q个功能的?/p>
一般情冉|们ƈ不需要返回结果顺序和发送请求顺序保持一致。DWR默认是不保持一致的?/p>
提示Q因Z持上面的序?x)对应用E序的性能和响应时_(d)如果其中的一个消息发生丢失那么浏览器可能?x)有意想不到以外情况发生。在使用q个功能的时候必认真考虑是否真的有必要用。通常比较好的Ҏ(gu)是用异步模式调用?/p>
6.3 Handling Errors and Warnings
对于一些服务器端发生的错误或警告情况DWR都回调用默认的错误和警告Ҏ(gu)q且传递一个相关信息,通常q些发生的错误和异常对于用户来说是不可见的?/p>
下面q个Ҏ(gu)主要用于以消息框的方式或者在状态栏里显CZ个错误或警告的消息?/p>
要改变错误的处理Ҏ(gu)可以使用q个Ҏ(gu)QDWREngine.setErrorHandler(function),
改变警告的处理方法可以用这个方法:(x)DWREngine.setWarningHandler(function).
6.4 Remoting Hooks
参?DWREngine.setPreHook(function) and DWREngine.setPostHook(function).
如果你想在执行远E方法调用之前或之后q行一些处理的话,你可以用上面的两个Ҏ(gu)。上面参C讄的目标方法必L没有参数的。如果你想限制特定的lg在一ơ方法调用没有结束之前不允许再次调用Q那么用上面的Ҏ(gu)很有用?/p>
Post 执行Hooks通常是设|pre-hooksQ一般用来撤消先前的操作。关于Hooks的例子可以参照;DWRUtil.useLoadingMessage() 函数?/p>
6.5 Remoting Options(q程调用讄)
关于DWR处理q程调用有若q个讄选项QMethod和Verbs对于用户来说是透明的,但对于不同的览器可能会(x)有媄响。通常DWR?x)选择正确的方法处理,如果想饶q某些浏览器产生的媄响这些参数设|将非常有用?/p>
DWREngine.setMethod(newmethod)
讄Method的实际执行方法,但被讄的方法不能确保被调用。只是DWR首先?x)尝试调用这个方法。newmethod 必须是DWREngine.XMLHttpRequest 或着 DWREngine.IFrame.
DWREngine.setVerb(verb)
允许讄iframe ?XMLHttpRequest提交数据时的方式,必须是POST或者GETQ如果浏览器不支持POST形式QDWR?x)自动切换到GET方式?br />