zoukankan      html  css  js  c++  java
  • 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{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标签去掉了

  • 相关阅读:
    HTML特殊字符编码对照表(备记)
    【java线程】锁机制
    java判断一个字符串是否为空,isEmpty和isBlank的区别
    对Java中properties类的理解
    使用redis的zset实现高效分页查询(附完整代码)
    ServiceStack.Redis高效封装和简易破解
    3.NetDh框架之缓存操作类和二次开发模式简单设计(附源码和示例代码)
    2.NetDh框架之简单高效的日志操作类(附源码和示例代码)
    1.NetDh框架之数据库操作层--Dapper简单封装,可支持多库实例、多种数据库类型等(附源码和示例代码)
    SQL Server索引原理解析
  • 原文地址:https://www.cnblogs.com/keyi/p/6963843.html
Copyright © 2011-2022 走看看