項目開發中,某個可獨立、也可集成的子業務模塊需要向外開放相關API接口,先說下項目自己使用了jersery來實現RESTful webservice以名詞形式公佈API。有意思的是在實際的操做中同事卻經過Ajax跨域請求的方式去調用該API,先不說成功與否,這樣的方式本就是「滑稽"的。和他一塊兒探討了此種作法的不合理性,以後選擇jersey client的方式進行遠程調用。只是他在跨域請求中遇到了問題,本身閒暇時間予以解決,這纔是此篇文章的由來。javascript
jQuery對跨域請求有兩種解決方式各自是jQuery的jquery.ajax jsonp格式和jquery.getScript方式,而且這兩種方式都僅僅支持get方法。前端
這裏主要談的是jsonp跨域的實現。java
json格式咱們卻是常常使用,但是jsonp就不那麼常常使用了,因此首先需要對jsonp要有一個瞭解。jquery
在解釋JSONP以前,咱們需要了解下」同源策略「這個概念,這對理解跨域有幫助。基於安全的緣由,瀏覽器是存在同源策略機制的,同源策略阻止從一個源載入的文檔或腳本獲取或設置還有一個源載入額文檔的屬性。有點繞,說的簡單點就是瀏覽器限制腳本僅僅能和同協議、同域名、同port的腳本進行交互。web
JSONP就是爲了解決這一問題的,JSONP是英文JSON with Padding的縮寫,是一個非官方的協議。他贊成服務端生成script tags返回值client,經過javascript callback的形式來實現網站訪問。JSONP是一種script tag的注入,將server返回的response加入到頁面是實現特定功能。ajax
簡而言之,JSONP自己不是複雜的東西,就是經過scirpt標籤對javascript文檔的動態解析繞過了瀏覽器的同源策略。json
接下來,來實際模擬一個跨域請求的解決方式。後端爲Spring MVC架構的,前端則經過Ajax進行跨域訪問。後端
一、首先client需要註冊一個callback(服務端經過該callback(jsonp)可以獲得js函數名(jsonpCallback))。而後以JavaScript語跨域
法的方式,生成一個function瀏覽器
二、接下來,將JSON數據直接以入參的方式,放置到function中,這樣就生成了一段js語法文檔,返回給client。
三、最後client瀏覽器動態的解析script標籤,並運行返回的JavaScript語法文檔片斷,此時數據做爲參數傳入到了預先定義好的
回調函數裏(動態運行回調函數)。
這樣的動態解析js文檔和eval函數是相似的。
接下來就是怎樣實現了,client代碼。
$.ajax({ type: "get", async: false, url: "http://localhost:8080/buy/get", dataType: "jsonp", jsonp: "callbackparam", //服務端用於接收callback調用的function名的參數 jsonpCallback: "success_jsonpCallback", //callback的function名稱,服務端會把名稱和data一塊兒傳遞回來 success: function(json) { alert(json[0].name); } });
註解:jsonp會建立一個查詢字符串參數callback=?
,這個參數會載入請求的URL後面,服務端應當在JSON數據前加上回調函數
名,以便完畢一個JSONP請求。也就是說server端需要對返回的數據作處理,格式爲例如如下形式:
jsonpCallback([{ name:"jhon"}])接下來看server端針對上述代碼的處理:
@RequestMapping("/get") public void get(HttpServletRequest req,HttpServletResponse res) { res.setContentType("text/plain"); String callbackFunName =req.getParameter("callbackparam");//獲得js函數名稱 try { res.getWriter().write(callbackFunName + "([ { name:\"John\"}])"); //返回jsonp數據 } catch (IOException e) { e.printStackTrace(); } }
至此,Ajax跨域請求也已經攻克了,只是仍是有兩點地方需要注意:
一、沒有關於JSONP調用的錯誤處理,動態插入的腳本有效,則運行調用,無效就默默失敗(無不論什麼提示)。
二、JSONP被不信任的服務使用會有必定的安全隱患,不信任的服務提供的腳本多是惡意的。