? ? ? ? 另外,如果最后一个参数是一个对象,这个对象中有一个callback成员,并且它是个函数,那么这个对象就是元数据对象,其他的都是Java方法参数。
另外,如果第一个参数是 null ,我们就假设没有回调函数,并且其他的都是Java方法参数。尽管如此,我们会检查最后一个参数是不是null,如果是就发出警告。 最后如果最后一个参数是null,那么就没有callback函数。 另外,发出错误信号是个糟糕的请求格式。
创造一个与Java对象匹配的Javascript对象 假设你有这样的Java方法: public class Remote {
public void setPerson(Person p) { this.person = p; } }
Person对象的结构是这样的: public Person { private String name; private int age;
private Date[] appointments; // getters and setters ... }
那么你可以在Javascript中这样写: var p = {
name:\ age:42,
appointments:[ new Date(), new Date(\};
Remote.setPerson(p);
在Javascript没有出现的字段,在Java中就不会被设置。
因为setter都是返回'void',我们就不需要使用callback函数了。如果你想要一个返回void的服务端方法的完整版,你也可以加上callback函数。很明显DWR不会向它传递任何参数。
传递额外的数据到callback函数
通常我们需要传递额外的数据到callback函数,但是因为所有的回调函数都只有一个参数(远程方法的返回结果),这就需要一些小技巧了。 解决方案就是使用Javascript的闭包特性。 例如,你的回调函数原本需要像这个样子:
function callbackFunc(dataFromServer, dataFromBrowser) { // 用dataFromServer和dataFromBrowser做些事情...... }
那么你可以像这个组织你的函数:
var dataFromBrowser = ...;
// 定义一个闭包函数来存储dataFromBrowser的引用,并调用dataFromServer var callbackProxy = function(dataFromServer) { callbackFunc(dataFromServer, dataFromBrowser); };
var callMetaData = { callback:callbackProxy };
Remote.method(params, callMetaData); (调用元数据在脚本介绍中有解释)
换句话说,现在你作为callback函数传递过来的不是一个真正的callback,他只是一个做为代理的闭包,用来传递客户端的数据。 你可以用更简介的形式:
var dataFromBrowser = ...; Remote.method(params, {
callback:function(dataFromServer) {
callbackFunc(dataFromServer, dataFromBrowser); }
});
使用DWR的一些技巧
这里有些东西可以帮你使用DWR。如果你也有什么使用技巧,也添加进来吧。
创建一个\组件
我不建议你做自己的suggest组件。让一些基础的东西工作起来是很容易的,但是让键盘导航正常的工作却不那么容易。有一些库里面已经包含的suggest组件:
Script.aculo.us 里有一个 Autocompleter.Local 函数,可以和DWR整合起来。让Local版的组件和DWR的远程调用结合起来要比直接让Remote版的组件工作起来更容易一些,因为Remote版的组件一般对服务器上的工作又特殊要求。你会可以在DWR的用户邮件列表中找到相关的信息,也可以看Rubens的blog
另外,Rimu Hosting的Peter实现了一个自己的Suggest组件,也是可以和DWR一起用的,查看这里 增强文件上传
Pierre Losson写了一个如何把DWR和Commons-Fileupload组件结合起来的文章。很不错,并且源码和演示都有。 改进加载信息
DWR 1.0 中的useLoadingMessage()函数有点问题,你可以自己定义这一信息,但是要小心调用。你也可以把这个函数中的问题修正一下。更多信息可以参看useLoadingMessage()的文档。 使用Server控制台
DWR可以报告出详细的错误信息,这些信息可以帮你找出你的程序错在哪里。如果你的程序出现什么异常,你应该仔细查看你的web容器开始或运行过程中出现的错误信息。一般错误信息会在WARNING或ERROR级别,但是INFO级别的信息也很有用。
如果你的log信息中又什么错误,但是你想知道的更详细的信息,可以查看INFO级别的信息,因为有时错误信息和后台信息会被一起输出到log里。 使用debug/test页面
debug/test页面对于查找错误也很有用。查看 http://localhost:8080/[YOUR-WEBAPP ]/
开始指南中有基本使用方法。但是一定要记住在发现错误时可以在这些页面找到有用的信息。
访问HttpServletRequest 详细参见这里 向回调函数传递参数
通常我们需要把额外的信息传递给callback函数,但是所有的callback函数只有一个参数(远程方法的返回码),这就需要一些技巧了。这里有一整篇文章阐述这个问题。 服务器性能优化
CPU瓶颈:经过严格的测试DWR的性能没什么问题。DWR上性能消耗同web服务器和网络比起来可以忽略不计。如果你真的需要提升DWR的性能的话,可以把log级别设置ERROR或FATAL,但是主要还是要看你的编码情况。
Network瓶颈: DWR没有管理你的浏览器缓存的功能,所以它会不断的重复读取DWR的javascript文件。这里有一个简单的解决办法,把javascript文件复制到你的web-app中,这样web服务器就可以更好的利用它了。你也可以考虑把所有的javascript文件合并成一个文件,然后用DOJO的压缩程序处理一个来节省流量。
我们可以做一个补丁,让DWR在web-app启动的时候用时间做为javascript文件的时间戳,但是这个并不十分重要,因为上面的补丁太简单了而且可以压缩合并Javascript文件。
WEB-INF/web.xml 参考手册
在web.xml中最简单的配置就是简单加入DWR的servlet,没有这个配置DWR就不会起作用:
此外还可以加入一些重要和有用的参数。
Logging
DWR可以工作在JDK1.3上,而JDK1.3不支持java.util.logging,但是我们想强迫任何人使用commons-logging或者log4j,所以当没有logging类的时候DWR就使用HttpServlet.log()方法。尽管如此,如果DWR发现了commons-logging,就是使用它。 Commons-Logging
几乎每一个人都在使用commons-logging,因为大多数的servlet容器在使用它。所以如果你的web应用中没有明显的加入commons-logging包,它也会默认的配置好。 在这种情况下,logging是由java.util.logging或者log4j配置文件控制的。详细配置查看文档。
HttpServlet.log()
如果你用HttpServlet.log(), 下面的配置控制logging:
可用的值有:FATAL, ERROR, WARN (默认), INFO 和 DEBUG。
多个dwr.xml文件 和 J2EE安全
一般来说,你只需要一个dwr.xml文件,并且放置在默认的位置:WEB-INF/dwr.xml。 如果那样的话,你可以不用了解下面的配置。 有三个原因使你希望指定不同位置的dwr.xml文件。
?
你希望让dwr.xml文件和它能访问到的资源在一起。在这种情况下你需要一个这样的配置:
你有大量的远程调用类,希望把他们分成多个文件。在这种情况下你需要重复下面的配置几次,每一个中有不同的 param-name,并且以 'config' 开头。DWR会依次把他们都读进来。
DWR可以使用Servlet规范的J2EE的URL安全机制来给不同的用户不同的访问权限。你只需要简单的定义多个dwr servlet,并且制定不同的名字,url和访问权限。
?
?
如果你希望使用这一功能,那么语法是这样的: