1、JSONP的诞生过程综述

1) Ajax无法跨域,引起了开发者的思考。

2) 开发者发现, <script>标签的src属性是可以跨域的,是否可以把跨域服务器写成调用本地的函数,回调数据回来?

3) JavaScript刚好支持JSONobject)。

4) 调用跨域服务器上动态生成的js格式文件(不管是什么样的跨域服务器,最终生成的返回值都是一段js代码)

5) 这种获取远程数据的方式看起来非常像Ajax,但其实并不一样,逐渐形成了一种非正式传输协议,称作JSONP

6) 传递一个callback参数给跨域服务器,然后跨域服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据进而返回。


2、JSONP的诞生过程细述

1) 哪怕跨域js文件中的代码,web页面也是可以无条件执行的。 

远程服务器www.server.com根目录下的server.js文件: 

alert(“我是跨域调用得到的响应”);

本地服务器www.client.com根目录下的client.html文件:

<!DOCTYPE html>
<html>
	<head>
    	<title></title>
    	<script src="http://www.server.com/server.js"></script>
	</head>
	<body>
	</body>
</html>

跨域调用显然可以成功。

问题:跨域远程获取数据如何实现?

 

2) 在client.html页面定义一个函数,然后在server.js中传入数据进行调用。

远程服务器www.server.com根目录下的server.js文件: 

serverResponse({"result":"我是跨域调用得到的响应"});

本地服务器www.client.com根目录下的client.html文件:

<!DOCTYPE html>
<html >
	<head>
    	<title></title>
    	<script>
    		var serverResponse = function(data){
        		alert(“跨域调用得到的响应是:” + data.result);
    		};
    	</script>
    	<script src="http://www.server.com/server.js"></script>
	</head>
	<body>
	</body>
</html>

跨域远程获取数据的目的实现。

问题:JSONP的服务器往往要面对很多客户端,而这些客户端各自的本地函数都不相同,如何让服务器知道它应该调用的本地函数是什么?

 

3) 服务器提供的JS脚本动态生成,客户端传递一个参数告诉服务器要查询的信息,服务器根据客户端的需求来动态生成JS脚本。

远程服务器www.server.com根目录下的getResult.jsp文件动态生成的JS脚本:

serverResponse({
	"name":"Amy",
	"age":23,
	"school":"BUPT"
});

本地服务器www.client.com根目录下的client.html文件:

<!DOCTYPE html>
<html>
	<head>
    	<title></title>
    	<script>
    		var serverResponse = function(data){
        		alert("跨域调用得到的响应是:" + data.result);
    		};
    		var url = "http://www.server.com/getResult.jsp?name=Amy&callback=serverResponse";
			var script = document.createElement('script');
			script.setAttribute('src', url);
			document.getElementsByTagName('head')[0].appendChild(script);
    	</script>
	</head>
	<body>
	</body>
</html>

问题:如何实现多次和重复调用?jQuery如何实现JSONP调用? 


3、JSONP的基本原理

JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。其实,JSONP跨域方式与Ajax XmlHttpRequest协议无关。


4、JSONP的执行过程:

1) 客户端注册一个callback (如:'jsoncallback'), 然后把callback的值(如'jsonpValue')传给服务器;

2) 服务端得到callback的数值后,要用jsonpValue(......)把将要输出的JSON内容包括起来,此时,服务器生成JSON数据才能被客户端正确接收。

3) 以JavaScript语法的方式,生成一个function,function 名字是传递上来的参数 'jsoncallback'的值'jsonpValue'.

4) 最后将JSON数据直接以参数的方式,放置到function中,生成了一段js格式文件,返回给客户端。

5) 客户端浏览器,解析script标签,并执行返回的js格式文件,此时js格式文件的数据作为参数,传入到了客户端预先定义好的callback函数(如$.ajax()方法封装的success: function(data)里。

 

5、jQuery用Ajax封装JSONP

远程服务器www.server.com根目录下的getResult.jsp文件动态生成的JS脚本:

serverResponse({
	"name":"Amy",
	"age":23,
	"school":"BUPT"
});

本地服务器www.client.com根目录下的client.html文件:

<!DOCTYPE html>
<html>
	<head>
		<title></title>
  		<script src=jquery-1.8.2.min.js"></script>
  		<script>
     		$(document).ready(function(){
        		$.ajax({
            		type: "get",
              		async: false,
             		url: "http://www.server.com/getResult.jsp?name=Amy",
             		dataType: "jsonp",
             		jsonp: "callback",
             		jsonpCallback:"serverResponse",             
					success: function(data){
                		alert('年龄: ' + data.age + ',学校: ' + data.school);
             		},
             		error: function(){
                 		alert(“跨域调用失败”);
             		}
         		});
     		});
		</script>
   	</head>
	<body>
  	</body>
</html>


6、Ajax和JSONP

Ajax和JSONP在调用方式上看起来很像,目的也都是请求一个url,然后把服务器返回的数据进行处理,因此jQuery把JSONP作为Ajax的一种形式进行了封装。 

Ajax和JSONP本质上是不同的:Ajax的核心是通过XmlHttpRequest获取非本页内容,而JSONP的核心则是动态添加<script>标签来调用服务器提供的JS脚本。 

Ajax和JSONP的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。 

 

7、JSONP的优缺点

(1)优点

① 不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略;

② 兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持。

③ JSONP在请求完毕后可以通过调用callback的方式回传结果,将回调方法的权限给了调用方,相当于将controller层和view层终于分开了。JSONP服务只提供纯服务的数据,至于提供服务以后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,只需要有不同的渲染逻辑就可以了,逻辑都可以使用同一个JSONP服务。

2)缺点

① 只支持GET请求而不支持POST等其它类型的HTTP请求;

② 只支持跨域HTTP请求,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

③ JSONP在调用失败时不会返回各种HTTP状态码。

④ 缺乏安全性。万一假如提供JSONP的服务存在页面注入漏洞,即它返回的JavaScript的内容被人控制的。那么所有调用这个JSONP的网站都会存在漏洞,于是无法把危险控制在一个域名下,所以在使用JSONP的时候必须要保证使用的JSONP服务必须是安全可信的。


本文转载:CSDN博客