DWR之与客户端的DWR交互

DWR之与客户端的DWR交互
----------
1. 基本的调用语法

如例:

MathDelegate.add(a,b,doMathCallback);
var doMathCallback = function(answer){
    document.getElementById("resultDiv").innerHTML = "<h1>" + 
        "Result: " + a + " " + op + " " + b + " = " + answer + "</h1>";
}
第一行代码是调用客户端代理对象的一个方法。然后,通过DWR客户端代码,该对象发起一个ajax请求,该请求启动DWRServlet运行。接着,这个servlet初始化MathDelegate类的一个实例,传入参数(已经根据需要进行转换),并调用add()方法。该方法完成并返回时,由这个servlet完成必要的类型转换,并将响应返回给客户。DWR获得该ajax请求,调用doMathCallback()函数,并完成其功能。至此,我们知道,DWR会动态地创建代理对象,创建器如何实例化MathDelegate对象,以及对于输入参数和返回值,转换器如何实现在javascript数据类型和java数据类型之间相互转换。
在本例中,把回调函数传给代理存根。也可以使用 内联回调函数来实现,如:

MathDelegate.add(a,b,function(answer){
    document.getElementById("resultDiv").innerHTML = "<h1>" +
        "Result: " + a + " " + op + " " + b + " = " + answer + "</h1>";      
});
两种方法完全等效,具体采用哪一种方法完全依赖个人爱好。

2. 调用元数据对象方法
还可以采用另一种全新的方法来编写这段代码,那就是 使用元数据对象,如:
MathDelegate.add(5,5,{callback:doMathCallback});
function doMathCallback(inResp){
    alert(inResp);
}
在此,我们把一个对象传给代理存根,这个 对象是个关联数组,其中客户端DWR代码会使用到其中部分元素。可以使用callback属性来指定回调函数。同样,可以采用内联回调函数以替代doMathCallback方法,如:
MathDelegate.add(
    7,7,{callback:function(inResp){alert(inResp);}}
); 
实现方法是否存在优劣差异?是的,在有些情况下确实如此。 当使用元数据对象方法时,可以传入另外的调用参数,而其他方法却不能。例如,可以在元数据对象中传入timeout和errorHandler元素。timeout元素指定请求超时前的等待时间,而errorHandler元素指定处理已知错误的函数. 如果只需要指定回调函数,那么采用第一种方法也可以,因为对于多数人而言,其句法更清晰简单。

3. 注意危险的语法
由于DWR的调用方法非常灵活,有时会出现语法错觉,难以判定参数的对应关系。例如:
SomeClass.someMethod({timeout:3},{callback:someFunction});
在该行代码中,第一个参数是传向远程方法的参数,第二个是一个元数据对象。问题是,不同参数的目的并不是很清晰。DWR使用如下检查顺序来做出判定。
a. 如果传向代理存根的第一个参数或者最后一个参数是函数,那么可以认为该函数就是回调函数,同时没有元数据对象,所有其他参数都是传给远程对象方法的参数。
b. 否则,如果最后一个参数是一个javascript对象,其中包含一个回调成员(是个函数),那么就认为该对象是一个元数据对象,所有其他参数是传向远程对象方法的参数。
c. 否则,如果第一个参数是null,就认为没有回调函数,所有其他参数都是传给远程对象方法的参数。如果远程方法没有返回值,这种格式非常有用。但是,应特别注意,如果最后一个参数也是null,DWR就会警告。
d. 最后,如果传向代理存根方法的最后一个参数为null,那么就认为没有回调函数。
e. 如果这些条件都不满足,那么该调用存在形式错误,会抛出错误。


4. 设置远程对象的bean
假如有一个bean,如:
package app;
import java.util.ArrayList;
import java.util.List;
public class StudentRegistry{

    private static List<Student> students = new ArrayList<Student>();

    public String addStudent(final Student inStudent){
        students.add(inStudent);
        return students.toString();
    }    
}
再看下面这个Student类:
package app;
public class Student{

    private static String name="";
    private static float gpa=0.0f;
    
    public void setName(final String inName){
        name=inName;
    }
    public String getName(){
        return name;
    }
    public void setGpa(final float inGpa){
        gpa=inGpa;
    }
    public float getGpa(){
        return gpa;
    }
    public String toString(){
        //省略
    }
}
现在,怎么在javascript中将一个学生加入到StudentRegistry?事实证明,这确实不容易。如例,当单击添加学生测试按钮时,假如会调用
callStudentRegistryAddStudent()函数,代码如下:
var name1 = "Eric Lehnsherr";
var student = {
    name : name1,
    gpa : Math.round(4.0*Math.random())
};
StudentRegistry.addStudent(student,callStudentRegistryAddStudentCallback);
如果不想设置对象中的某些域,需要启用bean转换器或object转换器以支持这种情况,但是一旦启用,就会自动转换。

5. 向回调函数传入更多信息
你可能已经注意到,回调函数只接受一个参数,即远程方法调用的返回值。这通常不够用,你可能希望同时传递其他信息。我们使用闭包来解决这个难题:
var extraInformation = "Susan Storm";
var callbackProxy = function(methodReturn){
    realCallback(methodReturn,extraInformation);
}
var realCallback = function(inMethodReturn,extraInformation){
    alert(inMethodReturn + extraInformation);
}
function CallRemoteClassRemoteMethod(){
    RemoteClass.remoteMethod("Reed Richards",{callback:callbackProxy});
}
我们看到,真正的回调函数是realCallback(),该函数有两个参数,一个是远程方法调用的返回值,另一个是其他附加信息。然而,callBackProxy()函数只接受DWR传来的单个返回值。因此,当响应返回时,DWR会调用callbackProxy()函数,该函数会继续调用realCallback()函数,传入返回值和附加信息。在代理函数中有对应的执行上下文,保证附加信息能够按预期传递。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值