JSONP原理javascript
JSON和JSONPhtml
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式。對於JSON你們應該是很瞭解了吧,不是很清楚的朋友能夠去json.org上了解下,簡單易懂。前端
JSONP是JSON with Padding的略稱。它是一個非官方的協議,它容許在服務器端集成Scripttags返回至客戶端,經過javascriptcallback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。java
JSONP就像是JSON+Padding同樣(Padding這裏咱們理解爲填充),咱們先看下面的小例子而後再詳細介紹。ajax
同源策略數據庫
在JavaScript中,有一個很重要的安全性限制,被稱爲「Same-OriginPolicy」(同源策略)。這一策略對於JavaScript代碼可以訪問的頁面內容作了很重要的限制,即JavaScript只能訪問與包含它的文檔在同一域下的內容。編程
根據這個策略,在baidu.com下的頁面中包含的JavaScript代碼,不能訪問在google.com域名下的頁面內容;甚至不一樣的子域名之間的頁面也不能經過JavaScript代碼互相訪問。對於Ajax的影響在於,經過XMLHttpRequest實現的Ajax請求,不能向不一樣的域提交請求,例如,在abc.example.com下的頁面,不能向def.example.com提交Ajax請求,等等。然而,當進行一些比較深刻的前端編程的時候,不可避免地須要進行跨域操做,這時候「同源策略」就顯得過於苛刻。json
然而html中有一些元素是不存在跨域問題的如:script,iframe等元素,利用這些元素,就能很好的解決這個問題.跨域
JSONP的實現方式瀏覽器
利用在頁面中建立<script>節點的方法向不一樣域提交HTTP請求,這項技術就能夠解決跨域提交Ajax請求的問題。
先看一個簡單例子
example1.com有這樣一個方法
<script type="text/javascript"> //回調函數 function callback(data) { //顯示客戶信息在A頁面上; } </script> //經過加載example2的JS文件來達到函數調用和數據傳遞 <script type="text/javascript" src="http://example2.com/test.js"></script>
example2.com的test.js內容以下
//回調函數 callback({name:"張三"});
以上這種方法只是一個簡單實現緣由的例子,現實中咱們的數據和回調也不會都寫死在JS中的,因此咱們要想辦法將這些靜態的東西動態生成就能夠了.只要將example1.com srcipt 地址改成一個能動態生成JS調用方法的服務地址便可.如:
<script type="text/javascript" src="http://example2.com/test.do"></script>
test.do直接返回以下
callback(數據庫客戶信息的JSON對象);
例子以下:固然對<script type="text/javascript"src="http://example2.com/test.do">的調用,你也能夠動態來建立script標籤完成,這樣就更靈活一些.
倘若要實現一個需求,某個網站a.com上顯示的客戶信息來自於其它網站b.com,顯然經過AJAX請求去取數據是不能作到的,由於存在同源策略.
A網站的前臺實現:
<script type="text/javascript"> //回調函數 function displayCustomer(data) { alert(data); //將客戶信息顯示在A.com的頁面上... } window.onload = function(){ //添加<script>標籤的方法 function createScript(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } } </script> createScript("http://B.com/search.do?&callback=displayCustomer");
B網站的後臺實現:
@Controller public classJsonpRest { @RequestMapping(value = "/test.do",method = RequestMethod.GET) public @ResponseBody Stringlist(HttpServletRequest request) { returnrequest.getParameter("callback")+"({name:'張三',age:18})"; } }
JSONP的優勢是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中均可以運行,不須要XMLHttpRequest或ActiveX的支持;而且在請求完畢後能夠經過調用callback的方式回傳結果。
JSONP的缺點則是:
1. 它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JavaScript調用的問題。
2. 沒有關於 JSONP調用的錯誤處理。若是動態腳本插入有效,就執行調用;若是無效,就靜默失敗。失敗是沒有任何提示的。例如,不能從服務器捕捉到404 錯誤,也不能取消或從新開始請求。不過,等待一段時間尚未響應的話,就不用理它了。
JQUERY對JSONP的支持
從JQery 1.2之後,就開始支持JSONP的調用。JQuery對前臺作了很好的處理如自動生成全局回調函數等,但後臺還須要開發人員本身實現.
$.getJSON("http://跨域的dns/xxx.do?callback=?",function(json){ // 業務邏輯執行代碼 });
請求URL
http://xxx.com/rest.do?callback=jQuery17207481773362960666_1332575486681&_=1393510789026
$.ajax({ url:"http://xxx.com/rest.do", dataType:"jsonp", //必須指定 jsonp : "c", //若不指定則默認爲callback jsonpCallback:"test",//若不指定則Jquery本身生成隨機的名稱 success:function(data){ //業務邏輯執行代碼 } });
請求URL http://xxx.com/rest.do?c=test&_=1393510789026
1. 當dataType爲JSONP時,JQUERY會爲用戶生成一個全局函數名稱爲jsonpCallback參數的值,這個函數內部調用了success方法JQUERY的實現原理及步驟
2. 以GET方式請求目標地址,並在URL中拼接以jsonp參數值爲key,以jsonpCallback值爲value的參數
3.請求返回回調函數數據
4.觸發調用全局的回調函數,在全局函數回調中調用success方法並將數據傳遞給success方法