经过一番工作,我找到了一种与 java 运行时通信的简洁方法,每次通信时都不会触发页面刷新。它的灵感来自于 JSONP 在当今大多数浏览器中绕过跨域限制的工作方式。因为 iFrame 也会触发command://
url,所以可以使用这种技术执行类似 JSONP 的操作。客户端(浏览器)的代码:
dojo.provide( "nmpo.io.java" );
dojo.require( "dojo.io.script" );
nmpo.io.java = dojo.delegate( dojo.io.script, {
attach: function(/*String*/id, /*String*/url, /*Document?*/frameDocument){
// summary:
// creates a new tag pointing to the specified URL and
// adds it to the document.
// description:
// Attaches the script element to the DOM. Use this method if you
// just want to attach a script to the DOM and do not care when or
// if it loads.
var frame = dojo.create( "iframe", {
id: id,
frameborder: 0,
framespacing: 0
}, dojo.body( ) );
dojo.style( frame, { display: "none" } );
dojo.attr( frame, { src: url } );
return frame;
},
_makeScriptDeferred: function(/*Object*/args){
//summary:
// sets up a Deferred object for an IO request.
var dfd = dojo._ioSetArgs(args, this._deferredCancel, this._deferredOk, this._deferredError);
var ioArgs = dfd.ioArgs;
ioArgs.id = dojo._scopeName + "IoScript" + (this._counter++);
ioArgs.canDelete = false;
//Special setup for jsonp case
ioArgs.jsonp = args.callbackParamName || args.jsonp;
if(ioArgs.jsonp){
//Add the jsonp parameter.
ioArgs.query = ioArgs.query || "";
if(ioArgs.query.length > 0){
ioArgs.query += "&";
}
ioArgs.query += ioArgs.jsonp
+ "="
+ (args.frameDoc ? "parent." : "")
+ "nmpo.io.java.jsonp_" + ioArgs.id + "._jsonpCallback";
ioArgs.frameDoc = args.frameDoc;
//Setup the Deferred to have the jsonp callback.
ioArgs.canDelete = true;
dfd._jsonpCallback = this._jsonpCallback;
this["jsonp_" + ioArgs.id] = dfd;
}
return dfd; // dojo.Deferred
}
});
当一个请求被发送到 java 运行时,一个回调参数将被提供,并且webBrowser.executeJavascript( callbackName + "(" + json + ");" );
可以执行一个动作来触发浏览器中的回调。
使用示例客户端:
dojo.require( "nmpo.io.java" );
nmpo.io.java.get({
// For some reason the first paramater (the one after the '?') is never in the
// paramater array in the java runtime. As a work around we stick in a dummy.
url: "command://sum?_",
callbackParamName: "callback",
content: {
numbers: [ 1, 2, 3, 4, 5 ].join( "," )
},
load: function( result ){
console.log( "A result was returned, the sum was [ " + result.result + " ]" );
}
});
用法示例java:
webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
@Override
public void commandReceived(WebBrowserCommandEvent e) {
// Check if you have the right command here, left out for the example
// Parse the paramaters into a Hashtable or something, also left out for the example
int sum = 0;
for( String number : arguments.get( "numbers" ).split( "," ) ){
sum += Integer.parseInt( number );
}
// Execute the javascript callback like would happen with a regular JSONP call.
webBrowser.executeJavascript( arguments.get( "callback" ) + "({ result: " + sum + " });" );
}
});
同样在框架中使用 IE,我强烈建议使用 firebug lite,IE 的开发工具不可用。