1、一個眾所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一律不準;
2、不過我們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不僅如此,我們還發現凡是擁有"src"這個屬性的標簽都擁有跨域的能力,比如<script>、<img>、<iframe>);
3、于是可以判斷,當前階段如果想通過純web端(ActiveX控件、服務端代理、屬于未來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件里,供客戶端調用和進一步處理;
4、恰巧我們已經知道有一種叫做JSON的純字符數據格式可以簡潔的描述復雜數據,更妙的是JSON還被js原生支持,所以在客戶端幾乎可以隨心所欲的處理這種格式的數據;
5、這樣子解決方案就呼之欲出了,web客戶端通過與調用腳本一模一樣的方式,來調用跨域服務器上動態生成的js格式文件(一般以JSON為后綴),顯而易見,服務器之所以要動態生成JSON文件,目的就在于把客戶端需要的數據裝入進去。
6、客戶端在對JSON文件調用成功之后,也就獲得了自己所需的數據,剩下的就是按照自己需求進行處理和展現了,這種獲取遠程數據的方式看起來非常像AJAX,但其實并不一樣。
7、為了便于客戶端使用數據,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許用戶傳遞一個callback參數給服務端,然后服務端返回數據時會將這個callback參數作為函數名來包裹住JSON數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了。
以上就是jsonp方法的思路,不得不佩服創造者是怎么個想出這種方法去跨域的。
Jsonp原理: 首先在客戶端注冊一個callback, 然后把callback的名字傳給服務器。此時,服務器先生成 json 數據。然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp.最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。客戶端瀏覽器,解析script標簽,并執行返回的 Javascript 文檔,此時數據作為參數,傳入到了客戶端預先定義好的 callback 函數里.(動態執行回調函數)
而目前實現jsonp跨域方法最簡便是使用jq封裝的
02 | jQuery(document).ready( function (){ |
06 | url : "http://api.taobao.com/apitools/ajax_PRops.do" , //跨域請求的URL |
09 | jsonp: "jsoncallback" , |
11 | jsonpCallback: "success_jsonpCallback" , |
13 | success : function (json){ |
服務器端:
01 | public void jsonpTest() throws IOException{ |
02 | HttpServletRequest request = ServletActionContext.getRequest(); |
03 | HttpServletResponse response = ServletActionContext.getResponse(); |
06 | String callbackName = (String)request.getAttribute( "jsoncallback" ); |
10 | String jsonStr = "{/"name/":/"張三/",/"age/":28}" ; |
12 | String renderStr = callbackName+ "(" +jsonStr+ ")" ; |
13 | response.setContentType( "text/plain;charset=UTF-8" ); |
14 | response.getWriter().write(renderStr); |
原生方法的話有:<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <script type="text/javascript"> function jsonpCallback(result) { //alert(result); for(var i in result) { alert(i+":"+result[i]);//循環輸出a:1,b:2,etc. } } var JSONP=document.createElement("script"); JSONP.type="text/javascript"; JSONP.src="http://crossdomain.com/services.php?callback=jsonpCallback"; document.getElementsByTagName("head")[0].appendChild(JSONP); </script> PHP:<?php //服務端返回JSON數據 $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); $result=json_encode($arr); //echo $_GET['callback'].'("Hello,World!")'; //echo $_GET['callback']."($result)"; //動態執行回調函數 $callback=$_GET['callback']; echo $callback."($result)";
02 | jQuery(document).ready( function (){ |
06 | url : "http://api.taobao.com/apitools/ajax_props.do" , //跨域請求的URL |
11 | jsonpCallback: "success_jsonpCallback" , |
13 | success : function (json){ |