Ajax跨域的解决方案有2种:CORS、JSONP。下面一一来介绍。

1、CORS

CrossOrigin Resource Sharing跨域资源共享。

当前几乎所有的浏览器(Internet Explorer 8+,Firefox 3.5+,Safari 4+和Chrome)都可通过名为跨域资源共享(Cross-Origin Resource Sharing)的协议支持ajax跨域调用。 

对一个简单的请求,没有自定义头部,要么使用GET,要么使用POST,它的主体是text/plain,请求用一个名叫Origin的额外的头部发送。Origin头部包含请求页面的头部(协议,域名,端口),这样服务器可以很容易的决定它是否应该提供响应。

服务器端:JSP页面中设置response.addHeader("Access-Control-Allow-Origin", "http://www.yoursite.com:8080")。

在请求信息中,浏览器使用 Origin 这个 HTTP 头来标识该请求来自于 http://www.yoursite.com:8080(发出跨区请求的url)。

在返回的响应信息中,使用 Access-Control-Allow-Origin 头来控制哪些域名的脚本可以访问该资源。

如果设置 Access-Control-Allow-Origin为*,则允许所有域名的脚本访问该资源。如果有多个,则只需要使用逗号分隔开即可。


2、JSONP

JSONP是JSON with Padding的略称,是一个非官方的协议,允许在服务器端集成Script tags返回至客户端,通过JavaScript callback的形式实现跨域访问

JSONP比JSON外面有多了一层,callback()。也就是说,在服务器端需要先将查询结果转换成JSON格式,然后用参数callback在JSON外面再套一层,就变成了JSONP

JSON格式:

{
	"message":"获取成功",
	"state":"1"
}

JSONP格式:

callback({
	"message":"获取成功",
  	"state":"1"
})

(1)JavaScript与JSONP

JSONP的简单实现模式:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

http://www.msnova.net/a.html

<script type="text/javascript">
	function callback(data) {
		alert(data.message);
	}
	function addScriptTag(src){
		var script = document.createElement('script');
		script.setAttribute("type","text/javascript");
		script.src = src;
		document.body.appendChild(script);
	}
	window.onload = function(){
		addScriptTag("http://blogs.msnova.net/b.js");
	}
</script>

http://blogs.msnova.net/b.js

callback({message:"success"}); 

说明:

① 动态创建script:addScriptTag方法中的document.body.appendChild(script)实现script标签被添加到body里,由于我们JS代码是在head标签中,执行到document.body.appendChild(script)时document.body可能还没有初始化完毕,所以通过window.onload方法确保页面加载完毕再添加script标签。

② 实际上,<script>标签的src属性并不被同源策略所约束,所以可以获取任何服务器上脚本并执行,因此,以上实例并不能算是一个真正的JSONP跨域服务。下面是真正的JSONP跨域服务:

http://www.msnova.net/a.html

<script type="text/javascript">
	function result(data) {
		alert("Hello " + data.student[0].name);
	}
	function addScriptTag(src){
		var script = document.createElement('script');
		script.setAttribute("type","text/javascript");
		script.src = src;
		document.body.appendChild(script);
	}
	window.onload = function(){
		addScriptTag("http://blogs.msnova.net/dataProcessor?city=Beijing&callback=result");
	}
</script>

服务器端http://blogs.msnova.net/dataProcessor会将查询结果转换成JSON格式,然后用参数callback在JSON外面再套一层变成JSONP作为响应返回,此处涉及到后台代码,不写出。


(2)jQuery与JSONP

jQuery框架也支持JSONP,可以使用$.getJSON(url,[data],[callback])方法$.ajax()方法

① $.getJSON方法:

<script type="text/javascript">
	$.getJSON("http://blogs.msnova.net/dataProcessor?callback=?",function(data){
		alert("Hello " + data.student[0].name);
	});
</script>

注意:在url的后面必须添加一个callback参数,这样getJSON()方法才知道是用JSONP方式,callback后面的问号是内部自动生成的一个回调函数名。

② $.ajax()方法:

a.  jsonp参数:

使用$.ajax形式可以不在url的后面添加一个callback参数,但此时需要指定jsonp参数。jsonp: “callback”代表的是服务端通过String callback = request.getParameter("callback") 接收客户端回调函数名的参数名,ajax请求中jsonp参数的默认值就是callback,也可以自己随便定义。

$.ajax({
   		url:"http://blogs.msnova.net/dataProcessor",   
   		dataType:"jsonp",
  		jsonp:"callback",
 		success:function(data){
  			alert("Hello " + data.student[0].name);
 		}
});

等价于:

$.ajax({
   		url:"http://blogs.msnova.net/dataProcessor?callback=?",   
   		dataType:"jsonp",
 		success:function(data){
  			alert("Hello " + data.student[0].name);
 		}
});

b.  jsonpCallback参数:

jsonpCallback: “callbackHandler”代表的是服务端调用结束后的本地回调函数名,比如jsonp: “callback”中的客户端回调函数名,jsonpCallback的参数值也可以自己随便定义,也可以不给jsonpCallback参数,其实jQuery会自动生成一个函数和函数名,远程服务调用成功后,既执行了success这个回调函数,也执行自己定义的jsonpCallback指定的回调函数,所以完全可以使用jQuery生成的回调函数,在调用结束后在success回调中做相应的处理即可。

$.ajax({
   	url:"http://blogs.msnova.net/dataProcessor?callback=?",   
   	dataType:"jsonp",
  	jsonpCallback:"result",
 	success:function(data){
  		alert("Hello " + data.student[0].name);
 	}
});

等价于:

$.ajax({
   	url:"http://blogs.msnova.net/dataProcessor",   
   	dataType:"jsonp",
	jsonp:"callback",
  	jsonpCallback:"result",
 	success:function(data){
  		alert("Hello " + data.student[0].name);
 	}
});

此处并没有定义result函数,也运行成功了。这是jQuery的功劳,jQuery在处理jsonp类型的ajax时,会自动生成回调函数并把数据取出来供success属性方法来调用。


本文转载:CSDN博客