先說說JSONP是怎么產生的1: 其實網上關于JSONP的講解有很多,但卻千篇一律,而且云里霧里,對于很多剛接觸的人來講理解起來有些困難,小可不才,試著用自己的方式來闡釋一下這個問題,看看是否有幫助。
一個眾所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一律不準;不過我們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不僅如此,我們還發現凡是擁有”src”這個屬性的標簽都擁有跨域的能力,比如<script>
、<img>
、<iframe>
);于是可以判斷,當前階段如果想通過純web端(ActiveX控件、服務端代理、屬于未來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件里,供客戶端調用和進一步處理;恰巧我們已經知道有一種叫做JSON的純字符數據格式可以簡潔的描述復雜數據,更妙的是JSON還被js原生支持,所以在客戶端幾乎可以隨心所欲的處理這種格式的數據;這樣子解決方案就呼之欲出了,web客戶端通過與調用腳本一模一樣的方式,來調用跨域服務器上動態生成的js格式文件(一般以JSON為后綴),顯而易見,服務器之所以要動態生成JSON文件,目的就在于把客戶端需要的數據裝入進去??蛻舳嗽趯SON文件調用成功之后,也就獲得了自己所需的數據,剩下的就是按照自己需求進行處理和展現了,這種獲取遠程數據的方式看起來非常像AJAX,但其實并不一樣。為了便于客戶端使用數據,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許用戶傳遞一個callback參數給服務端,然后服務端返回數據時會將這個callback參數作為函數名來包裹住JSON數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了。JSONP的客戶端具體實現(jquery版):
使用jsonp來獲取數據時,使用GET或者POST方法都是可以的,但是dataType必須要填寫jsonp,并且需要填寫jsonp和jsonpCallback兩個屬性,如:
$.ajax({ type: "POST", async: false, url: "http://www.someone.com/a/b", data:{ p: 1609 }, dataType: "jsonp", jsonp: "callback", jsonpCallback:"anyThing", success: function(data){ console.log(data.commonData); alert('票價: ' + data.jsonPData.PRice + ' 元,數量: ' + data.jsonPData.tickets + ' 個。'); }, error: function(){ alert('fail'); }});其中需要注意的是,jsonp屬性在最后發出請求時會變成如下格式
http://www.someone.com/a/b?callback=anyThing&_=1486627742030所以java后端會取到callback的值,在返回時會拼裝成如下格式數據返回,返回一個名為angThing的函數:
angThing({ "commonData": {...}, "jsonPData": { "price": 213.1, "tickets": 41 }})jquery會將方法中的數據剝離并返回到success回調方法中,供頁面使用。
JSONP的服務端實現(struts2): 首先,在action中獲取有客戶端傳來的數據,如data中的參數和callback的值
private String callback;public String find() { CommonData commonData = new CommonData(); JsonPTemp jsonPData = new JsonPTemp(new BigDecimal(213.1), new BigDecimal(41)); setJsonp(new JsonP(commonData, jsonPData)); return SUCCESS;}Struts2配置
<package name="a" namespace="/a" extends="default"><action name="b" class="com.someone.www.action.Action" method="find"> <result name="success" type="json"> <param name="callbackParameter">callback</param> <param name="root">jsonp</param> </result></action></package>注意:result中callbackParameter的值一定要與action中聲明的變量名一致,否則的話請求會報錯。
其實,struts2會把callback的值獲取到,然后聲明稱一個方法供客戶端使用,里面包裹的值是在下面時候填寫進去的
setJsonp(new JsonP(commonData, jsonPData));struts2會把數據先轉化為json,然后放入生成的方法中后,返回。
新聞熱點
疑難解答