一,什么是jsonp?
大家在使用ajax的过程中可能都遇到过相似的问题,比如js代码写的都正确,后台代码也没问题,可是ajax就是接收不到返回的数据,其实这是由于
同源策略造成的。同源策略的定义是:
1,同源策略,是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。
2,所谓同源是指《域名,协议,端口》均相同。
如当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,如你电脑上的的一个html页面中,无法通过脚本或ajax获取到你另外一台电脑上的数据。如下图:
2,所谓同源是指《域名,协议,端口》均相同。
如当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,如你电脑上的的一个html页面中,无法通过脚本或ajax获取到你另外一台电脑上的数据。如下图:
但是HTML 的<script> 元素是一个例外,利用 <script> 元素的开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
例如使用jquery调用百度地图的一个地理位置查询接口(根据坐标查询地址),就是使用的jsonp:
$.getScript("http://api.map.baidu.com/geocoder/v2/?ak=771719E5AA0bf28de657530a9b4d3b23&callback=handleModify&location=121.226574,25.145863&output=json");
然后我们可以自定义一个handleModify函数来接收百度返回的地理位置信息,测试说明正常访问到了百度的接口,并接受到了返回的数据,这就是jsonp突破同源策略的一个例子。
二,jsonp原理
【非官方易理解简介】
包括IE6在内的大多浏览器支持的标准跨域数据访问方式。
核心思想是利用JS标签里面的跨域特性进行跨域数据访问,在JS标签里面存在的是一个跨域的URL,实际执行的时候通过这个URL获得一段字符串,这段返回的字符串必须是一个合法的JS调用,通过EVAL这个字符串来完成对获得的数据的处理。
大多JS框架都支持一个包装后的JSONP实现,如jQuery,extjs等。
包括IE6在内的大多浏览器支持的标准跨域数据访问方式。
核心思想是利用JS标签里面的跨域特性进行跨域数据访问,在JS标签里面存在的是一个跨域的URL,实际执行的时候通过这个URL获得一段字符串,这段返回的字符串必须是一个合法的JS调用,通过EVAL这个字符串来完成对获得的数据的处理。
大多JS框架都支持一个包装后的JSONP实现,如jQuery,extjs等。
【以下是官方内容】
JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
三,java+struts2+ajax+jQuery+jsonp的一个例子
1,s代码
$.getJSON("http://192.168.1.116:8080/test?on=1&jsonpcallback=?",function(data){
alert(data.status);
});
其中的jsonpcallback是任意的,要在action中接收的。
$.ajax也可:
$.ajax({
url:"http://192.168.1.116:8080/test",
type:"GET",
dataType:"jsonp",
jsonp:"jsonpcallback",
data:{"on":1},
success:function(data){
handleResult(data.status);
}
});
type不能为post
package com.rick.store.test;
public class TestAction {
private int on;
public void setOn(int on) {
this.on = on;
}
private String jsonpcallback;
public void setJsonpcallback(String jsonpcallback) {
this.jsonpcallback = jsonpcallback;
}
private int status;
public int getStatus() {
return status;
}
public String execute() throws JSONException{
if(on!=0){
switch (on) {
case 1:
status=11;
break;
case 2:
status=21;
break;
case 3:
status=31;
break;
case 4:
status=41;
break;
default:
break;
}
}
return "success";
}
}
jsonpcallback不要提供getter方法
3,struts.xml配置
<action name="test" class="com.rick.store.test.TestAction">
<result type="json">
<param name="callbackParameter">jsonpcallback</param>
</result>
</action>
callbackParameter是struts提供的对jsonp支持的一种格式,如下
root:只包含xx对象 excludeProperties :除了xx之外的集合 includeProperties : 包含xx的集合 wrapPrefix :json结果开头添加xx(比如<paramname="wrapPrefix">[</param>) wrapSuffix :同上,只不过是结尾 ignoreHierarchy :转化时是否忽略继承关系true/false enumAsBean : 是否将枚举当做一个bean处理 enableGZIP :是否支持gzip压缩输出 noCache :是否缓存 excludeNullProperties : 是否转化输出 null值 statusCode :设置响应代号比如 304 callbackParameter : JSONP跨域访问的回调设置 contentType : 输出类型jsonpcallback不需要getter方法,否侧返回的值就不一样了,大家可以自己测试
4,运行结果: