JSONP 跨域请求
是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通(会被拦截),而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
使用
1. 在客户端调用提供JSONP支持的URL Service,获取JSONP格式数据。
<script type=
"text/javascript"
src=
"http://www.yiwuku.com/myService.aspx?jsonp=callbackFunction"
></script>
<
div
id
=
"divCustomers"
></
div
>
<script type=
"text/javascript"
>
function
CustomerLoaded(result,methodName)
{
var
html=
'<ul>'
;
for
(
var
i=0;i<result.length;i++)
{
html+=
'<li>'
+result[i]+
'</li>'
;
}
html+=
'</ul>'
;
document.getElementById(
'divCustomers'
).innerHTML=html;
}
</script>
<script>
$(document).ready(function(){
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
function(data){
$.each(data.items,
function(i,item){
$("<img/>").attr("src",item.media.m).appendTo("#images");
if(i==3)return false;
});
});
});
$.ajax({
dataType:
'jsonp'
,
data:
'id=10'
,
jsonp:
'jsonp_callback'
,
success:
function
(){
//dostuff
},
});
<!--使用script解决跨域-->
<script>
function showData(result){
var data = JSON.stringify(result)
$("#text").val(data);
}
$(document).ready(function(){
$("#btn").click(function(){
$("head").append("<script src='http://localhost:9090/student?callback=showData'><\/script>")
})
})
//服务端:
//前端传过来的回调函数名称
//String callback = request.getParameter("callback");
//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
//result = callback + "(" + result + ")";
</script>
第二种:
<!--jquery 的jsonp方式跨域请求-->
<script>
function showData (data) {
console.info("调用showData");
var result = JSON.stringify(data);
$("#text").val(result);
}
$(document).ready(function(){
$("#btn").click(function(){
$.ajax({
url:"http://localhost:8080/student",
type:"GET",
dateType:"jsonp",//指定服务器返回的数据类型
jsonpCallback:"showData",//指定回调函数名称(可选参数)//看调用结果,发现,请求时带的参数是:callback=showData;调用回调函数的时候,先调用了指定的showData,然后再调用了success
success:function (data) {
var result = JSON.stringify(data);
$("#text").val(result);
}
})
})
})
</script>
第三种:
$(document).ready(function(){
$("#btn").click(function(){
$.ajax({
url:"http://localhost:8080/student",
type:"GET",
dateType:"jsonp",//指定服务器返回的数据类型
jsonp:"theFunction",//指定参数名称
jsonpCallback:"showData",//指定回调函数名称(可选参数)
success:function (data) {
var result = JSON.stringify(data);
$("#text").val(result);
}
})
})
})
指定callback这个名称后,后台也需要跟着更改。
服务器:
//前端传过来的回调函数名称
String callback = request.getParameter("theFunction");
//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
result = callback + "(" + result + ")";
最后看看jsonp是否支持POST方式:ajax请求指定POST方式
可以看到,jsonp方式不支持POST方式跨域请求,就算指定成POST方式,会自动转为GET方式;而后端如果设置成POST方式了,那就请求不了了。
jsonp的实现方式其实就是<script>脚本请求地址的方式一样,只是ajax的jsonp对其做了封装,所以可想而知,jsonp是不支持POST方式的。
再补充一点,回到第一条:CORS头缺少“Access-Control-Allow-Origin”。
有时候你会发现其它都没问题,出现这个错误:这个错误代表服务端拒绝跨域访问。如果出现这个错误,就需要在服务端设置允许跨域请求。
response.setHeader("Access-Control-Allow-Origin", "*"); 设置允许任何域名跨域访问
后台代码添加:
// * 表示允许任何域名跨域访问
response.setHeader("Access-Control-Allow-Origin", "*");
// 指定特定域名可以访问
response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/");
总结:jQuery ajax方式以jsonp类型发起跨域请求,其原理跟<script>脚本请求一样,因此使用jsonp时也只能使用GET方式发起跨域请求。跨域请求需要服务端配合,设置callback,才能完成跨域请求。