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标签去掉了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值