Jquery跨域調用

轉自:http://www.cnblogs.com/5201314/archive/2009/06/23/1509552.html

JQuery1.2後getJSON方法支持跨域讀取json數據,原理是利用一個叫做jsonp的概念。當然,究其本質還是通過script標籤動態加載js,似乎這是實現真正跨域的唯一方法。

getJSON的用法JQuery手冊已經寫得很詳細,參考手冊就可以了,很簡單。需要指出的一點是getJSON利用的jsonp需要客戶端與服務端作出配合。

  1. 客戶端傳遞的URL裏要包含callback變量,以形如callback=?的形式結尾。(jquery會隨機生成一個字符串替換傳遞給服務端)
  2. 服務端獲取客戶端傳遞的callback的值callbackValue,和需要傳遞的json字符串構成 callbackValue.’(’.json.’)'傳回給客戶端(示例爲php字符串連接方式,其他語言類似)

不出意外的話應該已經可以跨域讀取了。

同時輸出json數據時候{之前的是(

Ajax的應用中,由於安全的問題,瀏覽器默認是不支持跨域調用的。傳統解決的方法,包括:(參考http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/)

Local proxy:
Needs infrastructure (can't run a serverless client) and you get double-taxed on bandwidth and latency (remote - proxy - client).
Flash:
Remote host needs to deploy a crossdomain.xml file, Flash is relatively proprietary and opaque to use, requires learning a one-off moving target programming langage.
Script tag:
Difficult to know when the content is available, no standard methodology, can be considered a "security risk".

以上方法都各有缺陷,都不是很好多解決方案。後來出現了一種叫JSON with Padding 的技術,簡稱 JSONP .(原理參考http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/),應 用JSONP可以實現JSON數據的跨域調用。非常的幸運,JQuery1.2以後支持JSONP的應用。下面側重說明在JQuery中,Json的跨域調用。

      應用JSONP實現Json數據跨域調用,需要服務器端與客戶端的合作完成。引用Jquery官方的例子,客戶端掉用如下:

$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
        function(data){
          $.each(data.items, function(i,item){
            $("<img/>").attr("src", item.media.m).appendTo("#images");
            if ( i == 3 ) return false;
          });
        });

 

    注意這裏調用的地址中jsoncallback=?是關鍵的所在!其中,符號會被Query自動替換成其他的回調方法的名稱,具體過程和原理我們這裏不理 會。我們關心的是jsoncallback=?起什麼作用了?原來jsoncallback=?被替換後,會把方法名稱傳給服務器。我們在服務器端要做什 麼工作呢?服務器要接受參數jsoncallback,然後把jsoncallback的值作爲JSON數據方法名稱返回,比如服務器是JSP,我們會這 樣做:

 

      ...

      String jsoncallback=request.getParameter("jsoncallback");

      ...

      out.print(jsoncallback+"({\"account\":\"XX\",\"passed\":\"true\",\"error\":\"null\"})");

 

Jquery取得的數據可能如下:

      JQUET0988788({"account":"XX","passed":"true","error":"null"})

 

總結,用JSONP要做兩件事:

      1/請求地址加參數:jsoncallback=?

      2/服務器段把jsoncallback的值作爲方法名傳回來,如JQUET098788(...)

 

 

jQuery從1.2開始就支持XMLHttp跨域請求了,具體怎麼操作?

jQuery中跨域訪問的核心原理:JS文件注入,因爲因爲script標籤的src屬性是可以跨域的,利用script標籤的src屬性直接返回非本域名下的數據,具體採用的方式稱爲:jsonp。

代碼:
    test.html,例如位於 
www.qq.com
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="
http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>jQuery-跨域請求</title>
    <script type="text/javascript" src="/js/jquery.js"></script>
    </head>
     <script type="text/javascript">
    jQuery(document).ready(function(){
        $.ajax({
            type : "GET",
            url : "
http://www.b.com/server.php&action=getmsg&callback=?",
            dataType : "jsonp",
           jsonp: 'callback',
            success : function(json){
                $('#msg_box').html(json.msg);
                return true;
            }
        });
    });
    </script>
     <body>
    <div id="msg_box"></div>
    </body>
    </html>

    server.php,例如位於
www.baidu.com
    <?php
    $action = $_GET['action'];
    $callback = $_GET[callback ];
    
    if ($action)
    {
        echo "{$callback}({"msg":"this is a jquery jsonp test message!"})";
        exit();
    }
    else
    {
        echo "{$callback}({"msg":"error action!"})";
        exit();
    }
    ?>

 

 

  今天上午,路路同學問了一個JQuery跨域讀取json數據的問題。JQuery用得很少,還真沒實際試過。於是上網找個找,看到了JQ的$.getJSON() 方法。先介紹下概念性的東西,網上找的,簡單看看就行了。

1.JSONP(JSON with Padding-填充json數據也就是常用的json跨域方式):利用script標籤,通過特定的src地址的調用,來執行一個客戶端的js函數,在 服務器端生成相對的數據(json格式)並以參數的形式傳遞給這個客戶端的js函數並執行這個函數,前提是需要服務器端的數據輸出支持。       

2.爲什麼使用JSONP:由於 JSON 只是一種含有簡單括號結構的純文本,因此許多通道都可以交換 JSON 消息。因爲同源策略的限制,我們不能在與外部服務器進行通信的時候使用 XMLHttpRequest。而JSONP是一種可以繞過同源策略的方法,即通過使用 JSON 與 <script> 標記相結合的方法,從服務端直接返回可執行的JavaScript函數調用或者JavaScript對象。       

3.誰在使用JSONP:dojo、JQuery、Youtube GData API 、Google Social Graph API 、Digg API 、GeoNames webservice、豆瓣API、Del.icio.us JSON API等。

------------------------------------------------------------------------------------------------


  和 AJAX 一樣,JSONP 實際上也是早已存在,只是說法相對比較新穎(貌似也出來很久了)。自 1.2 版本起,JQuery加入了對 JSONP 的支持(http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback)。我們可以很容易的利用 $.getJSON() 方法(或者其它基於 $.ajax() 的方法),來跨域加載 JSON 數據。我參考官網,寫了個JQ測試的例子:

a.html

<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<script type="text/javascript">
function do_jsonp() {
    $.getJSON("http://active.zol.com.cn/guofeng/profile2.php?callback=?",
    function(data) {
        $('#result').val('My name is: ' + data.nick);
    });
}
</script>
<a href="javascript :do_jsonp();">Click me</a><br />
<textarea id="result" cols="50" rows="3"></textarea>
</body>
</html>

 

profile2.php

<?php
$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
$json = '';

//php數組
$arr = array(
     'name' => 'lava',
     'nick' => '比目魚',
     'contact' => array(
      'MSN' => 'lavaguo#msn.com',
         'email' => 'guo.feng#zol.com.cn',
         'website' => 'http://www.zol.com.cn',
     )
 );

$arr = gb2312ToUtf8($arr);//中文需要轉UTF-8
$json = json_encode($arr);//轉成json數組
if (!empty($callback)) {
    $json = $callback . '(' . $json . ')';//注意這裏的格式,調試時這裏費了點時間
}
echo $json;

function gb2312ToUtf8(&$input)
{
    if (!is_array($input)) {
        $input = iconv('GB2312', 'UTF-8', $input);
    } else {
        foreach ($input as $k=>$v) {
            gb2312ToUtf8(&$input["$k"]);
        }
    }
    return $input;
}

?>

你可能注意到上面的例子中,url 被寫成了http://active.zol.com.cn/guofeng/profile2.php?callback=?,需要說明的是,這個問號會被 jQuery 自動替換爲回調函數的函數名(如果是一個匿名函數,JQuery 會自動生成一個帶時間戳的函數名)。

總結下JSONP原理:

首先在客戶端註冊一個callback, 然後把callback的名字傳給服務器。

此時,服務器先生成 json 數據。 

然後以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp.

最後將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。

客戶端瀏覽器,解析script標籤,並執行返回的 javascript 文檔,此時數據作爲參數,傳入到了客戶端預先定義好的 callback 函數裏.(動態執行回調函數)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章