??xml version="1.0" encoding="utf-8" standalone="yes"?> q样我们q道了(jin)Q实际上Demo.javacȝsayHelloҎ(gu)已经被解释到Demo.js中了(jin)Q只不过后面的调用还?sh)是很清楚而已?br />
l箋(hu)Q?br />
public String sayHello(String name) { x(chng)Qdwr的核?j)原理,基本清?/p>
1Q在index.html里面我们嵌入
<script type='text/javascript' src='../dwr/engine.js'> </script>
<script type='text/javascript' src='../dwr/util.js'> </script>
<script type='text/javascript' src='../dwr/interface/Demo.js'> </script>
前面两个都是DWRpȝ默认需要加载的QDemo.js是Demo.java所对应的。按理论Q只要在web.xml和dwr.xml配置好,那么我们可以在客户端操作Demo.jsQ类g操作服务器端的Demo.js?br />
HTML source:
<p>
Name:
<input type="text" id="demoName"/>
<input value="Send" type="button" onclick="update()"/>
<br/>
Reply: <span id="demoReply"></span>
</p>
Javascript source:
function update() {
var name = dwr.util.getValue("demoName");
Demo.sayHello(name, function(data) {
dwr.util.setValue("demoReply", data);
});
}
Java source:
package org.getahead.dwrdemo.simpletext;
public class Demo {
public String sayHello(String name) {
return "Hello, " + name;
}
}
dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
"http://getahead.org/dwr/dwr20.dtd">
<dwr>
<allow>
<create creator="new" javascript="Demo">
<param name="class" value="org.getahead.dwrdemo.simpletext.Demo"/>
</create>
</allow>
</dwr>
在浏览器W一ơ加载本面Ӟ览器第一步发?lt;script type='text/javascript' src='../dwr/engine.js'> </script>Q根据web.xml关于dwr的配|,pȝ?x)激发Servlet的POSTҎ(gu),向客L(fng)输出engine.js文g,q个文g你可以在IE的缓存里面发?当然,E序?x)在最后输ZL较客L(fng)是否已经存在该文Ӟ如果要输出的文g大和和该文g大小一_(d)׃输出?jin),同样util.js、Demo.js也是q么输出的。那么看看Demo.js文g里面的内容如下:(x)
if (typeof this['Person'] != 'function') {
function Person() {
this.address = null;
this.phoneNumber = null;
this.name = null;
this.id = 0;
this.salary = 0;
}
}
// Provide a default path to dwr.engine
if (typeof this['dwr'] == 'undefined') this.dwr = {};
if (typeof dwr['engine'] == 'undefined') dwr.engine = {};
if (typeof this['Demo'] == 'undefined') this.Demo = {};
Demo._path = '/dwr/dwr';
Demo.sayHello = function(p0, callback) {
return dwr.engine._execute(Demo._path, 'Demo', 'sayHello', p0, callback);
};
Demo.getInclude = function(callback) {
return dwr.engine._execute(Demo._path, 'Demo', 'getInclude', callback);
};
return "Hello, " + name;
}
译?br />
Demo._path = '/dwr/dwr';
Demo.sayHello = function(p0, callback) {
return dwr.engine._execute(Demo._path, 'Demo', 'sayHello', p0, callback);
};
在调用engine.execute()Ҏ(gu)Ӟ最l采用无h讉K服务器技术?br />
采用该技术的关键问题是两个参敎ͼ一个是urlQ往什么地方发送;一个是docQ发送什么内?br />
通过跟踪engine.js我们知道
url=/dwr/dwr/call/plaincall/Demo.sayHello.dwr
发送内容如下:(x)
callCount=1
windowName=DWR-442B435
899
c0-scriptName=Demo
c0-methodName=sayHello
c0-id=0
c0-param0=string:Joe
batchId=1
page=/dwr/simpletext/index.html
httpSessionId=
scriptSessionId=1CC3A
.0A3
实际上url=/dwr/dwr/call/plaincall/Demo.sayHello.dwrQ{向的是DwrServletQDwrServlet实际上获取了(jin)两部分信息,一部分是urlQ根据这个能够解析到我们的目标javacR方法,另外一部分是发送信息包Q实际上q就是SayHello所需要的参数输入信息Q最后,q回数据Q这些数据格式通过responseq回Q在engine.js中对应于return batch.reply;通过解析q回对象Q采用javascirpt数据动态刷新到面?/p>
User: 你的注册用户名称
Password: 你的注册用户密码
Host: cvs.dev.java.net
Repository path: /cvs
Use default port
打开cvs后,你会(x)发现好多好多开源工E,扑ֈDWR工程,目前DWR版本?.0Qcheck outQ在把运行环境配备好Q我用的是Tomcat5.5Qjava虚拟?.5版本Q这三个正好配套?br />
eclipse和Tomcat5.5调试好后Q我们就可以工E发布到Tomcat中去?jin),q里注意Q由于DWR工程l织方式是按ant?fn)惯方式l织的,所以你不能按eclipse默认方式d布你的DWR工程Q你需要执行build.xml构徏dwr.war包,该包?x)生成放到工E的\target\ant\目录下,在我机器上是D:\dwr_workspace\dwr\target\ant\dwr.warQ然后你需要将dwr.war拯到D:\Tomcat 5.5\webapps目录Q运行TomcatQ系l会(x)自动dwr.war解包QŞ成dwr目录Q比如在我机器上?x)Ş成文件夹D:\Tomcat 5.5\webapps\dwr?br />
在我机器上访?a href="http://localhost:5050/dwr">http://localhost:5050/dwrQ就可见到首面了(jin)Q但是下半部分报错,看看tomcat后台也报错,查了(jin)查是找不到类的缘故,再查发现~少js.jar包,上网找找Q下载了(jin)一个js.jar包,再将js.jar包添加到目录D:\dwr_workspace\dwr\web\WEB-INF\lib\js.jarQ然后重新发布war包就没问题啦?br />
1. 安装 DWR JAR ?/strong> 2. ~辑 config 文g 下面的代码d?WEB-INF/web.xml 文g中,<servlet>需要放在另外的<servlet>之后Q?lt;servlet-mapping>也是如此?/p>
<servlet> <servlet-mapping> 接下来创?dwr.xml 文gq将此放?web.xml 所在的 WEB-INF 目录下。文件中cM下面的内容:(x) <!DOCTYPE dwr PUBLIC <dwr> DWR 配置文g定义?jin)?DWR 创徏和被 Javascript q程使用的类。在上面的例子中我们在远E创Z(jin)2个类Qƈ且给Z(jin)?Javascript 中的cd?/p>
上面使用?new creator 使用?jin)所有的 JavaBeans 必须含有的公有(publicQ无参(no-argsQ的构造函数。值得一提的是, DWR q有一些限Ӟ(x) 3. 讉K下面的地址 你应该会(x)看到一个页面,上面昄?jin)刚才你在第二步所创徏的类。进入一个链接之后你?x)看到所有等待调用方法的列表。这些动态生的例子你也能通过 DWR 来实现?/p>
亲自试和体?x)下吧?/p>
怎样应用C?Web E序中? 在侧Ҏ(gu)有很多例子演CZ(jin)怎样改变|页中的文本、更新列表、操作表单和动态修改表根{每一个例子都有详l的说明?/p>
另外一个开始方法就是从面中查看源代码Q这些页面你刚刚览q:(x) <script src=’/[YOUR-WEBAPP]/dwr/interface/[YOUR-SCRIPT].js’></script> 你可以根据实际情况修?/[YOUR-WEBAPP]/ 部分?/p>
关于怎样书写 DWR 控制?Javascript 代码h?脚本?/a>?/p>
下蝲 dwr.jar 文gQ然后将它放?web E序?WEB-INF/lib 目录下面Q很可能在这个目录下已经有一?jar 文g?jin)?/p>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
”-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN”
”http://www.getahead.ltd.uk/dwr/dwr10.dtd”>
<allow>
<create creator=”new” javascript=”JDate”>
<param name=”class” value=”java.util.Date”/>
</create>
<create creator=”new” javascript=”Demo”>
<param name=”class” value=”your.java.Bean”/>
</create>
</allow>
</dwr>
http://localhost:8080/[YOUR-WEBAPP]/dwr/
<script src=’/[YOUR-WEBAPP]/dwr/engine.js’></script>
]]>
每个convert都包含两个方法convertInboundQconvertOutbound,q两个方法相?br />
convertInbound q站转换 字W串转换为java可识别的对象 针对调用Ҏ(gu)的输入参?br />
convertOutbound 出站转换 java对象转换为javascript可识别的json格式的字W串 针对调用Ҏ(gu)的返回?/p>
下面q些可以实现Zweb的实时事仉知的方法:(x)
1.HTTP:(x)q种Ҏ(gu)由存在于不间断的HTTPq接响应中或某个XMLHttpRequestq接中的服务器数据流所l成?/p>
2.HTTP拉取方式Q在q种传统的方法中Q客L(fng)以用户可定义的时间间隔去(g)查服务器上的最新数据。这U拉取方式的频率要够高才能保证很高的数据精度Q?br /> 但高频率可能?x)导致多余的(g)查,从而导致较高的|络量。而另一斚wQ低频率则会(x)D错过更新的数据。理惛_Q拉取的旉间隔应该{于服务器状态改变的速度?/p>
3.反{AJAXQ服务流应用到AJAXQ就是所谓的反{AJAX 或者COMET 。它使得服务器在某事件发生时可以发送消息给客户端,而不需要客L(fng)昑ּ的请求?br />
目标在于辑ֈ状态变化的实时更新。COMET使用?jin)HTTP/1.1中的持箋(hu)q接的特性。通过HTTP/1.1Q除非另作说明,服务器和览器之间的TCPq接?x)一直保持连接状态,
直到其中一方发送了(jin)一条明昄“关闭q接”的消息,或者有时以及(qing)|络错误发生?/p>
4.长时间轮询:(x)也就是所谓的异步轮询Q这U方式是U服务器端推送方式和客户端拉取方式的混合。它是基于BAYEUX协议的。这个协议遵循基于主题的发布——订阅机制?br />
在订阅了(jin)某个频道后,客户端和服务器间的连接会(x)保持打开状态,q保持一D事先定义好的时间。如果服务器端没有事件发生,而发生了(jin)时Q?br />
服务器端׃(x)h客户端进行异步重新连接。如果有事g发生Q服务器端会(x)发送数据到客户端,然后客户端重新连?br />
注:(x)CometQ?a >Z HTTP 长连接的“服务器推”技?/a>
?br />
Bayeux是Dojo基金?x)定义的一个协议。dwr在去q的时候就开始支持该协议Q随着dwr目2008q初加入到Dojo基金?x),ajax技?dwr)和comet(cometd)技术将?x)融合的更加紧?说明Qdwr,cometd现在都属于dojo基金?x)下面的?Q本包将来估计会(x)作很大的变化。ajax技术和comet技术的融合Q参?a >使用 Jetty ?Direct Web Remoting ~写可扩展的 Comet 应用E序Q?br />
q个包是dwr外部支持包,q未被其他包引用?br />
org.directwebremoting.bayeux.BayeuxClient Bayeux协议客户?br />
org.directwebremoting.bayeux.BayeuxScriptConduit Bayeux协议Script道
org.directwebremoting.bayeux.BayeuxServletContextAttributeListener 该监听器由web.xml注册Q如果要使用推的技术,那么你就必须注册QBayeuxServletContextAttributeListenerQ会(x)调用BayeuxClientQ按comet原理script推送的客户端。具体细节未作研I?br />
hub
集线器,提供多个ajax互相操作接口Q得一个界面中多个ajax可以互相调用Q参考openajax联盟制定的规则,dwr已经是联盟的?x)员(sh)一
org.directwebremoting.export包会(x)用到Q具体细节不清楚
ScriptBuffer
采用list储存scriptQ功能类gStringBuffer
ServerContext
服务器端上下?br />
WebContext
览器上下文Q?span style="color: red">好像是每个客户一个(U色表示没仔l看Q?br />
auth.js
AuthHandler负责dq个js文g
l节由CachingFileHandlerd
readResource()字节符转换为字W串
l承JavaScriptHandler接口Q专门处理读取js文g
JavaScriptHandler extends TemplateHandler implements CachingFileHandler implements Handler
CachingFileHandler
d数据文gQ根据req的报头属性判断,如果修改q,那么重新下蝲Q否则不?nbsp;
下蝲d资源文gQ由不同的handle处理Q这些handle都承于JavaScriptHandler
如:(x)AuthHandler extends JavaScriptHandler
实际上客L(fng)?x)将js文g下蝲到缓存区Q这U机制可以得浏览的时候检查是否js文g内容发生变化。从而重C载?/p>
dwr20.dtd
org.directwebremoting.impl.DTDEntityResolve处理
dwr20.xsd
实际上没用到
两种xml框架cd文gQ可以被parse识别?/p>
engine.js
引擎js,在浏览器~存?sh)?x)发现q个文g已经下蝲到本地。EngineHandler处理,
messages.properties
语言资源文g
由org.directwebremoting.util.Messagesd
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("org.directwebremoting.messages");
比较l致的环节:(x)
init()调用
createAndSetupDefaultContainer()
调用
setupDefaultContainer(defaultContainer, servletConfig)
调用如下步骤
1)setupDefaults(container);
包括Q?br />
容器相关理工具配置集,也就是要实现的一些接口。这U方式蛮好,当容器需要具备很多接口功能时Q把q些接口全部做成隐射Qƈ讄成可配置的实?br />
container.addImplementation(AccessControl.class, DefaultAccessControl.class);
// Mapping handlers to URLsQ\径配|?br />
createUrlMapping(container, "/index.html", IndexHandler.class, "indexHandlerUrl");
//dservlet配置属?br />
2)setupFromServletConfig(container, servletConfig);
额外处理1)中多选类?br />
3)resolveMultipleImplementations(container, servletConfig);
里面使用?jin)通用yui型压~器
【?YUI Compressor 压羃 Javascript ?CSS
工具下蝲Q?http://www.julienlecomte.net/yuicompressor/
英文介绍Q?http://com3.devnet.re3.yahoo.com/yui/compressor/
YUI Compressor是用Java~写的工P需要Java版本大于{于1.4?
工作原理介:(x)
主要是去掉冗余的I白Q主要包括空|换行W、制表符?nbsp;
对于 JavascriptQ还采用~短变量名的Ҏ(gu)压羃文gQ就是在保证代码正确性的情况下将变量名用只有1个字W的字符串代替,或?个?个字W,M量短?nbsp;
对于 CSSQ还有采用优?值属性值的表示Q优化颜色值的Ҏ(gu)压羃文g?nbsp;
CSS的优化比 CSSTidy 功能弱。CSSTidyq能支持一些相兛_性的合ƈ。?br />
//工具配置?加蝲Q显玎ͼ(g)?br />
4)container.setupFinished();
容器内容bean初始?,包括pȝ默认Q?Q?br />
initContainerBeans