JSONP原理
JSON和JSONP
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式。對於JSON大家應該是很瞭解了吧,不是很清楚的朋友可以去json.org上了解下,簡單易懂。
JSONP是JSON with Padding的略稱。它是一個非官方的協議,它允許在服務器端集成Scripttags返回至客户端,通過javascriptcallback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。
JSONP就像是JSON+Padding一樣(Padding這裏我們理解為填充),我們先看下面的小例子然後再詳細介紹。
同源策略
在JavaScript中,有一個很重要的安全性限制,被稱為“Same-OriginPolicy”(同源策略)。這一策略對於JavaScript代碼能夠訪問的頁面內容做了很重要的限制,即JavaScript只能訪問與包含它的文檔在同一域下的內容。
根據這個策略,在baidu.com下的頁面中包含的JavaScript代碼,不能訪問在google.com域名下的頁面內容;甚至不同的子域名之間的頁面也不能通過JavaScript代碼互相訪問。對於Ajax的影響在於,通過XMLHttpRequest實現的Ajax請求,不能向不同的域提交請求,例如,在abc.example.com下的頁面,不能向def.example.com提交Ajax請求,等等。然而,當進行一些比較深入的前端編程的時候,不可避免地需要進行跨域操作,這時候“同源策略”就顯得過於苛刻。
然而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 Controller直接返回如下
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的缺點則是:
- 它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。
- 沒有關於 JSONP調用的錯誤處理。如果動態腳本插入有效,就執行調用;如果無效,就靜默失敗。失敗是沒有任何提示的。例如,不能從服務器捕捉到404 錯誤,也不能取消或重新開始請求。不過,等待一段時間還沒有響應的話,就不用理它了。
JQUERY對JSONP的支持
從JQery 1.2以後,就開始支持JSONP的調用。JQuery對前台做了很好的處理如自動生成全局回調函數等,但後台還需要開發人員自己實現.
$.getJSON("http://跨域的dns/xxx.do?callback=?",function(json){
// 業務邏輯執行代碼
});
請求URL
http://xxx.com/rest.do?callba..._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
- 當dataType為JSONP時,JQUERY會為用户生成一個全局函數名稱為jsonpCallback參數的值,這個函數內部調用了success方法JQUERY的實現原理及步驟
- 以GET方式請求目標地址,並在URL中拼接以jsonp參數值為key,以jsonpCallback值為value的參數
- 請求返回回調函數數據
- 觸發調用全局的回調函數,在全局函數回調中調用success方法並將數據傳遞給success方法