一、 JSONP的原理
JSONP即JSON with Padding,由于浏览器同源策略的限制,XmlHttpRequest不能跨域(crossdomain)访问资源。如果想要跨域访问,我们可以通过一个技巧实现。html中的script标签可以加载跨域的Javascript的文件。举一个简单的例子
比如我们在www.example.com域名下有一个html文件,有如下片段内容:
<script type="text/javascript">
var test_abc_callback = function(params) {
alert(params.a + params.b + params.c);
}
</script>
<script src="http://www.test.com/abc.js" type="text/javascript"></script>
而http://www.test.com/a.js的内容如下
test_abc_callback({"a":1, "b": 2, "c":3});
其实第一个script定义了一个名为test_abc_callback的函数
第二个script加载跨域的js文件,在js中其实调用了test_abc_callback函数,并传递一个json格式的参数。
这样就可把跨域生成的数据{"a":1, "b": 2, "c":3}获取下来。
行了,这个就是最为简单的JSONP的例子了。
上述这个例子没有任何实际价值,现在让我们看看我们通常都是如何使用JSONP的。
1. 通常我们会有一个url根据传递参数的不同,动态生成数据,如:
http://www.test.com/add.php?a=1&b=2&c=3&callback=addabc
add.php的内容如下:
<?
$a = $_GET('a') + 1;
$b = $_GET('b') + 1;
$c = $_GET('c') + 1;
header("Content-type: text/javascript");
printf("%s({\"a\":%d, \"b\":%d, \"c\":%d})", $_GET('callback'), $a, $b, $c);
?>
这样就根据用户请求的参数返回其想要得到的数据。
二、GWT中的JSONP
GWT即Google Web Toolkit,鼎鼎大名,笔者不用过多解释。GWT中有内建(buildin)的JSONP请求组件
JsonpRequestBuilder.
可以参考JsonpRequestBuilder的JavaDoc文档获取其API的更多使用方法
这里还是结合上一节的例子做一下讲解
JsonpRequestBuilder中有个requestObject的接口,有两个参数
1. url 请求数据的url。上述例子是http://www.test.com/add.php?a=1&b=2&c=3
2. callback AsyncCallback<Object>对象,包括请求成功和失败两个接口。
requestObject这个接口发送一个JSONP的请求,并期望返回一个Javascript Object类型的结果。但GWT是Java编写的,我们可以使用JSONObject来解析Javascript Object。或者使用JavaScript overlay class(下述会做讲解和演示)
下面来看一个例子:
public class JsonpTest implements EntryPoint {
public void onModuleLoad() {
String url = "http://www.test.com/add.php?a=1&b=2&c=3";
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.requestObject(url, new AsyncCallback<Abc>() {
public void onFailure(Throwable throwable) {
Window.alert("Error: " + throwable);
}
public void onSuccess(Abc result) {
Window.alert("a=" + result.a() + ", b=" + result.b() + ", c=" + result.c());
}
});
}
}
JsonpRequestBuilder会在请求是加入参数callback=__gwt_jsonp__.I0.onSuccess。如果callback的名字以被使用,可使用setCallbackParam(String)来设置
上面代码中未定义的类就是JavaScript overlay class, 下面我们来定义它。
public class Abc extends JavaScriptObject {
protected Abc() {
}
public final native int a() /*-{
return this.a;
}-*/;
public final native int b() /*-{
return this.b;
}-*/;
public final native int c() /*-{
return this.c;
}-*/;
}
可以参考JavaScript Overlay Types获取关于其更多的信息
当然JavaScript Overlay Types还提供数组的实现,可使用JsArray<T>表示数组,T是数组类型,但必须也是JavascriptObject的子类型。
浙公网安备 33010602011771号