使用jquery的getjson()遇到的跨域訪問問題

環境描述

  • 服務器:使用jersey提供RESTful接口
  • 客戶端:使用jquery的getJson()方法異步獲取數據
  • 希望實現的功能:服務器端以json格式提供RESTful的數據訪問,客戶端通過ajax異步加載的方式讀取數據。

出問題代碼

(其實下面代碼也不包含錯誤,只是在執行的時候會出問題)

客戶端原始代碼:

document.getElementById("mydiv").innerHTML = "data";
$(function(){
     $.getJSON("******", function (data) {
         alert("go");
         document.getElementById("mydiv").innerHTML = "hahahah";
     });
});

服務器端原始代碼:

@GET
@Path("/test")
@Produces("application/json;charset=utf8")
public String go(){
    return "({\"num\":\"3\"}";
}

結果運行的時候就出問題了,客戶端的回調函數死活不執行。用Firefox的Httpfox調試下,發現在獲取json數據的時候就遇到問題,報錯application/json (NS_ERROR_DOM_BAD_URI)
網上找了下,說是jquery跨域訪問的安全問題,就是說:

JavaScript出於安全方面的考慮,不允許跨域調用其他頁面的對象。但在安全限制的同時也給注入iframe或是ajax應用上帶來了不少麻煩。首先什麼是跨域,簡單地理解就是因爲JavaScript同源策略的限制,a.com 域名下的js無法操作b.com或是c.a.com域名下的對象。

上邊的代碼中,客戶端和服務端確實在不同的服務器,使用不同的IP地址和端口號,因此出現了問題。

解決辦法就是JSONP,全稱是 JSON with Padding ,是基於 JSON 格式的爲解決跨域請求資源而產生的解決方案。其基本原理是利用了 HTML 裏 元素標籤可以跨域訪問,因此將數據封裝成爲js回調函數的格式進行傳輸訪問。

舉個例子,上述的數據{"num":"3"},這時不能跨域訪問的,那麼救把它包裝爲js,callback('{"num":"3"}'),將數據包裝爲回調函數的參數,就可以跨域訪問了。這就需要解決一個問題,提供數據訪問的服務器必須進行數據封裝的操作,如果響應的時候還是把原來的json格式數據輸出,那麼客戶端是拿不到需要的數據的。

如果說服務器沒有對數據進行封裝,那麼出現的問題就是回調函數死活不執行。即使用Httpfox進行調試,也會發現雖然正確訪問了數據鏈接,服務器也返回了數據,但回調函數就是執行不了。就是因爲這個問題困了我整整兩天……

解決方案

其實jQuery已經封裝了JSONP的使用

$.getJSON( "****?jsoncallback=?", function( data ){
    // 處理跨域請求得到的數據
});

jquery會把jsoncallback後邊的?替換爲一個字符串作爲數據訪問的回調函數的函數名,在服務器端需要讀取該參數,然後使用它對數據進行封裝,也就是改成f(data)的樣式,加上函數名和括號就行了。

服務器端代碼爲:

    @GET
    @Path("/test")
    @Produces("application/json;charset=utf8")
    public String go(@QueryParam("jsoncallback") String jsoncallback){
        System.out.println(jsoncallback);
        String info = jsoncallback+"({\"num\":\"3\"})";
        return info;
    }

ok,再訪問就沒有問題了!

PS:最後吐槽一下網絡上的各種解決方案,都是隻給一個jsoncallback參數,服務器需要怎麼改一點都不說,結果整整兩天一直困在回調函數不執行的苦惱中……

感謝基於JQuery、Jsonp與Jersey的跨域訪問這篇文章替我找到了回家的路!

發佈了110 篇原創文章 · 獲贊 19 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章