jsonp的使用方法


 

 

 

參數jsonp 和 jsonpCallback

jsonp指定使用哪個名字將回調函數傳給服務端,也就是在服務端通過 request.getParameter(""); 的那個名字,而jsonpCallback就是request.getParamete("")取得的值,也就是回調函數的名稱。其實這兩個參數都可以不指定,只要我們是通過 success : 來指定回調函數的情況下,就可以省略這兩個參數,jsnop如果不知道,默認是 "callback",jsnpCallback不指定,是jquery自動生成的一個函數名稱,其對應源碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
var  oldCallbacks = [],
     rjsonp = /(=)\?(?=&|$)|\?\?/;
 
// Default jsonp settings
jQuery.ajaxSetup({
     jsonp:  "callback" ,
     jsonpCallback:  function () {
         var  callback = oldCallbacks.pop() || ( jQuery.expando +  "_"  + ( nonce++ ) );
         this [ callback ] =  true ;
         return  callback;
     }
});

  

(1)訪問js

 

8888端口的html4項目中的jsonp.html頁面代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<! doctype  html>
< html >
< head >
     < meta  charset="utf-8">
     < meta  name="keywords" content="jsonp">
     < meta  name="description" content="jsonp">
     < title >jsonp</ title >
</ head >
< body >
 
< script  type="text/javascript" src="js/jquery-1.11.1.js"></ script >
< script  type="text/javascript">
var url = "http://localhost:8080/html5/jsonp_data.js";
// 創建script標簽,設置其屬性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script標簽加入head,此時調用開始
document.getElementsByTagName('head')[0].appendChild(script);
function callbackFun(data)
{
     console.log(data.age);
     console.log(data.name);
}  
</ script >
</ body >
</ html >

 其訪問的8080端口的html5項目中的jsonp_data.js代碼如下:

1
callbackFun({ "age" :100, "name" : "yuanfang" })

 將兩個tomcate啟動,用瀏覽器訪問8888端口的html4項目中的jsonp.html,結果如下:

上面我們看到,我們從8888 端口的頁面通過 script 標簽成功 的訪問到了8080 端口下的jsonp_data.js中的數據。這就是 jsonp 的基本原理,利用script標簽的特性,將數據使用json格式用一個函數包裹起來,然后在進行訪問的頁面中定義一個相同函數名的函數,因為 script 標簽src引用的js腳本到達瀏覽器時會執行,而我們有定義了一個同名的函數,所以json格式的數據,就做完參數傳遞給了我們定義的同名函數了。這樣就完成了跨域數據交換。jsonp的含義是:json with padding,而在json數據外包裹它的那個函數,就是所謂的 padding 啦^--^

 

(2)訪問servlet---比較實用的例子

8080端口的html5項目中定義一個servlet:

復制代碼
復制代碼
package com.tz.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;

@WebServlet("/JsonServlet")
public class JsonServlet extends HttpServlet 
{
    private static final long serialVersionUID = 4335775212856826743L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException 
    {
        String callbackfun = request.getParameter("mycallback");
        System.out.println(callbackfun);    // callbackFun
        response.setContentType("text/json;charset=utf-8");
        
        User user = new User();
        user.setName("yuanfang");
        user.setAge(100);
        Object obj = JSON.toJSON(user);
        
        System.out.println(user);            // com.tz.servlet.User@164ff87
        System.out.println(obj);            // {"age":100,"name":"yuanfang"}
        callbackfun += "(" + obj + ")";    
        System.out.println(callbackfun);    // callbackFun({"age":100,"name":"yuanfang"})
        
        response.getWriter().println(callbackfun);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException 
    {
        this.doPost(request, response);
    }

}
復制代碼
復制代碼

 

 在8888端口的html4項目中的jsonp.html來如下的跨域訪問他:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<! doctype  html>
< html >
< head >
     < meta  charset="utf-8">
     < meta  name="keywords" content="jsonp">
     < meta  name="description" content="jsonp">
     < title >jsonp</ title >
     < style  type="text/css">
         *{margin:0;padding:0;}
         div{width:600px;height:100px;margin:20px auto;}
     </ style >
</ head >
< body >
     < div >
         < a  href="javascript:;">jsonp測試</ a >
     </ div >
     
< script  type="text/javascript" src="js/jquery-1.11.1.js"></ script >
< script  type="text/javascript">
function callbackFun(data)
{
     console.log(111);
     console.log(data.name);
     //data.age = 10000000;
     //alert(0000);
}
$(function(){
     $("a").on("click", function(){     
         $.ajax({
             type:"post",
             url:"http://localhost:8080/html5/JsonServlet",
             dataType:'jsonp',
             jsonp:'mycallback',
             jsonpCallback:'callbackFun',
             success:function(data) {
                 console.log(2222);
                 console.log(data.age);
             }
         });
     })
});
</ script >
</ body >
</ html >

 結果如下:

我們看到,我們成功的跨域取到了servlet中的數據,而且在我們指定的回調函數jsonpCallback:'callbackFun' 和 sucess 指定的回調函數中都進行了執行。而且總是callbackFun先執行,如果我們打開注釋://data.age = 10000000; //alert(0000);

就會發現:在callbackFun中對 data 進行修改之后,success指定的回調函數的結果也會發生變化,而且通過alert(0000),我們確定了如果alert(000)沒有執行完,success指定的函數就不會開始執行,就是說兩個回調函數是先后同步執行的。

注:雖然ajax封裝了jsop跨域請求但是不支持async:false,依然是同步的,因為ajax本質是xmlhttprequest請求,jsonp是js語法。

 

結果如下:

 

從上面的介紹和例子,我們知道了 jsonp 跨域的原理,是利用了script標簽的特性來進行的,但是這和ajax有什么關系呢?顯然script標簽加載js腳本和ajax一點關系都沒有,在沒有ajax技術之前,script標簽就存在了的。只不過是jquery的封裝,使用了ajax來向服務器傳遞 jsonp 和 jsonpCallback 這兩個參數而已。如果我們再服務器端和客戶端,對參數 jsonp 和 jsonpCallback 的值,協調好(也就是一致性),那么就沒有必要使用ajax來傳遞着兩個參數了,就像上面第二個例子那樣,直接構造一個script標簽就行了。不過實際上,我們還是會使用ajax的封裝,因為它在調用完成之后,又將動態添加的script標簽去掉了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM