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

jsonp的使用方法的更多相关文章

  1. 手把手教你实现一个通用的jsonp跨域方法

    什么是jsonp JSONP(JSON with Padding)是JSON的一种"使用模式",可用于解决主流浏览器的跨域数据访问的问题.由于同源策略,一般来说位于 server1 ...

  2. jsonp使用post方法

    来源https://www.jb51.net/article/68980.htm

  3. jsonp 跨域Uncaught SyntaxError: Unexpected token :解决方法

    [jQuery]Ajax实现跨域访问JSON Ajax跨域访问JSON 环境:.net4.0+jQuery+JSON.net 因为在跨域实现,所以这里新建网站,这个网站只需要Ashx文件 public ...

  4. JSONP是如何工作的

    我对这个问题的探究来源于一个需求: 当访问某个页面的时候,需要向另外一个网站报告一下这次访问的信息. 其实发一个跨域的请求就能大致实现这个需求.我们发跨域的例子其实很常见,例如请求一个第三方的图片.引 ...

  5. Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)

    由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...

  6. Ajax跨域:Jsonp原理解析

    推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...

  7. 我的jsonp跨域问题

    关于jsonp跨域问题,在这个方面也是了解一点点,先记录下来,主要作为以后查看,之前下载并安装过wampserver,了解到了jsonp和json的区别,现在谈谈跨域这个问题: 首先什么是跨域,简单地 ...

  8. jQuery工具方法

    目录 常用工具方法 判断数据类型的方法 Ajax操作 $.ajax 简便写法 Ajax事件 返回值 JSONP 文件上传 参考链接 jQuery函数库提供了一个jQuery对象(简写为$),这个对象本 ...

  9. JSONP跨域的原理解析( 一种脚本注入行为)

    JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制, 被称为“some-Origin Policy”(同源策略).这一策略对于Jav ...

随机推荐

  1. 更精炼更专注的RTMPClient客户端EasyRTMPClient,满足直播、转发、分析等各种需求

    现状 EasyRTMPClient,熟悉的朋友就会联想到EasyRTSPClient项目(https://github.com/EasyDSS/EasyRTSPClient),EasyRTSPClie ...

  2. Mybatis之Mapper动态代理

    一.什么是Mapper的动态代理 采用Mapper动态代理方法只需要编写相应的Mapper接口(相当于Dao接口),那么Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同Dao接 ...

  3. XShell 连接 vm虚拟机中的redhat Linux系统

    选择的是nat链接,因为nat链接是没有网络的情况下,也是可以链接操作的,当然bridge也可以,那我就从第一步开始; 因为有的人可能改过电脑上的虚拟适配器的ip地址,导致和虚拟机默认的不一样了.如果 ...

  4. iOS视频直播用到的协议

    一 .流媒体 1 - 伪流媒体 1.1 扫盲:边下载边播放1.2 伪流媒体:视频不是实时播放的,先把视频放在数据库,再供客户端访问,比如:优酷,爱奇艺等 1.3 特点: 边下边存,文件会保存.遵守了 ...

  5. php总结3——基本函数、流程控制中的循环

    3.1 php基本函数(数学.日期.字符串) 数学函数:max         mixed max(number $arg1,number $arg2,……)  求一组数据中的最大值        m ...

  6. BTC、BCH和BSV三者到底有什么区别?

    比特币发展到今天已经有10个年头了,在这十年的发展中,比特币一共经历了两次重要的分裂,现在变成了三种货币,第一种是目前继承了比特币绝大多数遗产的BTC:第二种是BCH:第三种是BSV.那这三种货币到底 ...

  7. ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails

    mysql 删除表时提示有外键 mysql> drop tables auth_group;ERROR 1217 (23000): Cannot delete or update a paren ...

  8. API的理解和使用——字符串的命令

    字符串的命令复习表 命令 作用 set   setex   setnx   get   mset   mget   incr   decs   incrby   decrby   incrbyfloa ...

  9. Flask中的CBV和上下文初步解读

    一 . flask中的CBV 相对于Django中的CBV,让我们来看看flask中的CBV是如何实现的 ? from flask import Flask, render_template, url ...

  10. Java中的内存泄漏

    [转]介绍Java中的内存泄漏 1. 什么是内存泄漏? 内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 要想理解这个定义,我们需要先了解一下对象在内存中的 ...