說到這個問題,不得不說一下“同源策略(Same-Origin Policy)”,它是由Netscape提出的一個著名的安全策略。現在所有支持JavaScript 的瀏覽器都會使用這個策略。所謂同源,就是必須協議、域名、端口都一致的,才叫做同源。例如:http://www.12306.cn和https://www.12306.cn,由於協議不一致,就不是同源。http://127.0.0.1:8080/test1和http://localhost:8080/test1 也不屬於同源,因爲域名不一致。端口不同當然也不叫同源了。
如果非同源,那麼在請求數據時,瀏覽器會在控制檯中報一個異常,提示拒絕訪問。這是一個令web開發人員非常手疼的問題。比如,我現在打開百度網頁,然後在控制檯中請求CSDN的網頁,那麼就會報如圖所示的異常:
在上圖中,大家可能會看到這個詞兒——“Access-Control-Allow-Origin”,它是W3C標準中爲了解決同源策略引起的跨域問題而提出的一種技術——“跨域資源共享(CORS,Cross-Origin Resource Sharing)”。只要你在服務端設定這個Access-Control-Allow-Origin的header就可以允許跨域訪問了。有興趣的話,自己查一下,很簡單。不過它有安全隱患,主要是因爲支持通配符*。每個網站都可以隨意請求,那就太不安全了。如:
- response.setHeader("Access-Control-Allow-Origin", "*");
Query中$.ajax的get方法,是支持跨域訪問的,不過dataType要設定爲“jsonp”。Jsonp(JSON with Padding)是 json 的一種“使用模式”,可以讓網頁從別的網域獲取資料。jsonp是採用的js的回調機制來實現的。使用方式也很簡單,代碼如下:
- $.ajax({
- url: 'http://localhost:8080/test2/searchJSONResult.action',
- type: "GET",
- dataType: 'jsonp',
- data: {name:”ZhangHuihua”}, timeout: 5000,
- success: function (json) {
- //客戶端jquery預先定義好的callback函數,成功獲取跨域服務器上的json數據後,會動態執行這個callback函數
- alert(json);
- },
- error: function (){
- alert("請求失敗!");
- }
- });
- //簡單方式如下:
- $.getJSON("http://localhost:8080/test2/searchJSONResult.action?name1=ZhangHuihua&callback=?",
- function(json){ // 執行代碼
- });
在服務器端,重新拼接json數據:
- /** 獲取請求的各個參數(用戶名等) **/
- Map map = request.getParameterMap();
- /** 獲取jsonp的回調函數名 **/
- String callback = request.getParameter("callback");
- /** 調用業務邏輯,並將結果轉化爲json格式 **/
- String msg = convert2Json(services.login(map))
- /** 重新拼接格式,並輸出 **/
- out.println(callback + "('" + msg + "')");
這樣就可以在瀏覽器獲取到異源服務端返回的json數據了。這裏返回的跟json格式不一樣,它的格式是回調函數名+(json數組)。其中小括號不可以省略。否則請求是發送成功了,但是卻獲取不到數據,因爲返回的數據格式出錯了。效果圖如下: