博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jsonp的原理
阅读量:7111 次
发布时间:2019-06-28

本文共 4527 字,大约阅读时间需要 15 分钟。

假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击

一:跨域问题。

 

 

二,跨域产生的原因

Js是不能跨域请求。出于安全考虑,js设计时不可以跨域。

什么是跨域:

1、域名不同时。

2、域名相同,端口不同。 

只有域名相同、端口相同时,才可以访问。

可以使用jsonp解决跨域问题。

三,跨域失败的案例

3.1,同源策略

首先基于安全的原因,浏览器是存在这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。

3.2,随便建两个网页

一个端口是2698,一个2701,按照定义它们是不同源的。

3.3,用jQuery发起不同源的请求

在2698端口的网页上添加一个按钮,Click事件随便发起两个向端口为2701域的请求。

$("#getOtherDomainThings").click(function () {    $.get("http://localhost:2701/Scripts/jquery-1.4.4.min.js", function (data) {        console.log(data)    })    $.get("http://localhost:2701/home/index", function (data) {        console.log(data)    })})

根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。(not allowed by Access-Control-Allow-Origin)

 

OK,原来jsonp是要解决这个问题的。

 

 换句话就是说在一个src中或者一个url中直接去请求了另一个项目的json数据。

例如在端口是8080的项目中的页面的url中直接去请求了一个http://localhost:8081/category.json这个语句,而这个category.json就在8081的webapp的目录下,就会产生跨域请求的提示。

 

 

 四,跨域的解决方法

4.1,启发

我们有时候在项目中经常能看到这样的代码

1     

 

这样即使不在同一个项目中,也可以请求成功。就是利用了这个漏洞,或者说是技术吧,来实现的宽裕的请求。

4.2,方法(案例一)

4.2.1,利用script获取不同源的json

既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的scr属性,把这个script插入到dom里,让浏览器去获取。实践:

function CreateScript(src) {    $("

添加一个按钮事件来测试一下:

$("#getOtherDomainJson").click(function () {    $.get('http://localhost:2701/home/somejson', function (data) {        console.log(data)    })})

首先,第一个浏览器,http://localhost:2701/home/somejson这个Url的确是存在一个json的,而且在 2698网页上用script标签来请求这个2701这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即 把响应当js去执行,很明显{"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}不是合法的js语句。

 

 

4.2.2,利用script获取异域的jsonp

显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:

如果存在jsonpcallback这个方法,那么jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})就是合法的js语句。

在这里需要注意的就是在原来的json格式的数据{"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}要封装成jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})这样一个脚本,这样才会被回调的时候解析到,否则解析也是失败的。

由于服务器不知道客户端的回调是什么,不可能hard code成jsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryString的key要遵从服务端的约定,上面的是”callback“。

添加回调函数:

function jsonpcallback(json) {    console.log(json)}

把前面的方法稍微改改参数:

$("#getJsonpByHand").click(function () {    CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")})

200OK,服务器返回jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的 东方"}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。

 

4.2.3,利用jQuery获取jsonp

 

上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp:

$("#getJsonpByJquery").click(function () {    $.ajax({        url: 'http://localhost:2701/home/somejsonp',        dataType: "jsonp",        jsonp: "callback",        success: function (data) {            console.log(data)        }    })})

得到的结果跟上面类似。

4.2.4,总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。

jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})

4.3,案例二

 4.3.1,简单应用

 程序A中sample的部分代码:

1 7 
程序B中test.js的代码: 1 //调用callback函数,并以json数据形式作为阐述传递,完成回调 2 callback({message:"success"}); 

 这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调

  将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义吧。

  一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了

4.3.2,简单应用的升级以一

 程序A中sample的部分代码:

1 

  程序B的test.js代码不变,我们再执行下程序,是不是和原来的一样呢。如果我们再想调用一个远程服务的话,只要添加addScriptTag方法,传入远程服务的src值就可以了。这里说明下为什么要将addScriptTag方法放入到window.onload的方法里,原因是addScriptTag方法中有句document.body.appendChild(script);,这个script标签是被添加到body里的,由于我们写的javascript代码是在head标签中,document.body还没有初始化完毕呢,所以我们要通过window.onload方法先初始化页面,这样才不会出错。

这样这个

http://localhost:20002/test.js路径就可以动态的变化了。

 

 

 

 4.3.3,简单应用的升级二

  上面的例子是最简单的JSONP的实现模型,不过它还算不上一个真正的JSONP服务。我们来看一下真正的JSONP服务是怎么样的,比如Google的ajax搜索接口: 

  q=?这个问号是表示你要搜索的内容,最重要的是第二个callback=?这个是正如其名表示回调函数的名称,也就是将你自己在客户端定义的回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调。有点罗嗦了,还是看看实现代码吧:

1 

 

 这个result方法是自己定义的,可能服务器上有千千万万个类似于result 的回调函数,但是我现在要的就是result而不是其它的方法,所以在这里自己定义回调方法。而不是写死的。可能下一次我就改成result1,result2,result3,等了只要自己把回调方法的名称改一下就行了。

 

4.4.4,jquery对jsonp的支持

  jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(详细可以参考)。那我们就来修改下程序A的代码,改用jQuery的getJSON方法来实现(下面的例子没用用到向服务传参,所以只写了getJSON(url,[callback])):

 

  结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。这个函数名大家可以debug一下看看,比如jQuery17207481773362960666_1332575486681。

  当然,加入说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现(参数较多,详细可以参考)。先来看看如何实现吧:

 

  没错,jsonpCallback就是可以指定我们自己的回调方法名person,远程服务接受callback参数的值就不再是自动生成的回调名,而是person。dataType是指定按照JSOPN方式访问远程服务。

 

转载地址:http://exghl.baihongyu.com/

你可能感兴趣的文章
HTML: 仿写一个财经类静态的网页
查看>>
POJ 3979 分数减法【数学问题的探讨】
查看>>
HashSet
查看>>
C#读写config配置文件
查看>>
JavaScript:文本域事件处理
查看>>
关于dctser进程
查看>>
Sqoop架构(四)
查看>>
【转】Xcode托管代码到oschina中的教程
查看>>
QTP的那些事 -– Visual Relation Identifier Feature: How to use in the real world
查看>>
一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-演示ORM中的查询
查看>>
win7远程登录
查看>>
5.6. DHCP
查看>>
RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->Web版本模块管理界面新增模块排序功能...
查看>>
ajax与算法,sql的group处理
查看>>
《C#高级编程》笔记系列--点滴记录(持续更新中……)
查看>>
采用泳道图工具跟踪项目进度或者问题解决进度
查看>>
sql server 2008学习1–系统数据库
查看>>
找零钱的两种方法
查看>>
DM642图像处理程序的主要结构
查看>>
从微软的DBML文件中我们能学到什么(它告诉了我们什么是微软的重中之重)~三 分部类是否破坏了单一职责...
查看>>