henk的gravatar头像
henk 2017-01-19 12:30:16
ajax跨域请求JSONP技术学习总结

原文链接:http://blog.csdn.net/linhenk/article/details/54603659

这是我写的第一篇博客,与其说它为博客,这更像是我平时学习的一些小笔记,可能有些知识点会被遗漏,会有不足,请各位看官多多包涵,也请指出我的不足,共同学习,谢谢!

1.问题提出

在实习的时候,在前台系统中使用AJAX请求后台系统数据(这两个系统不在同一个网域内,你可以简单的理解为:在www.b.com的前台页面中,请求www.a.com的后台数据),这看起来好像没什么问题的操作,就出现了问题。请看下图: 
这里写图片描述
访问www.b.com中的index.html页面 
这里写图片描述
报错了: 
XMLHttpRequest cannot load http://www.a.com/foo. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://www.b.com’ is therefore not allowed access. 
以上的报错是因为我们使用AJAX进行跨域请求而导致的,浏览器对AJAX请求进行了限制,不允许进行跨域请求。 
怎么可以解决跨域问题呢?**使用JSONP**

2.什么是跨域请求

在解决问题之前我们先了解了解怎样的操作才算是跨域请求。

请求端 被请求端 是否跨域
www.b.com www.a.com 是(这就是上面图示中出现的跨域情况)
www.a.com www.a.com:81 是(请求的端口不一样)
b.a.com a.a.com 是(二级域名不一样)
a.a.com a.a.com/foo 不是

以上可以看出,只要是域名不一样或者端口号不一样,就会出现跨域的情况。

3.做个小实验

先来看看下面这一段代码: 
3.1、在AServer(www.a.com)该工程中写入这么一段js代码: 
这里写图片描述

3.2、修改BServer(www.b.com)中index.html中的代码: 
这里写图片描述

3.3、在浏览器中打开BServer(www.b.com)中的index.html页面,效果如下所示: 
这里写图片描述
我们可以看到,AServer(www.a.com)中的demo.js代码已经被执行了,再看demo.js的请求状态码也是200,这再次说明,www.a.com中的demo.js已经被成功请求。 
从上面的小实验中可以看出,script标签中的src属性,是可以支持跨域请求的。(其实不仅仅是scrpit中的src支持跨域,img,vedio,iframe等标签中的src属性都是支持跨域的) 
在这里你是否想到了些什么,我们一起往下看。 
**

4.利用script标签中的src属性解决跨域请求

4.1、修改一下BServer(www.b.com)中的html的代码,使用src属性请求后台数据,如下所示: 
这里写图片描述

4.2代码改好了,我们再次访问一下BServer(www.b.com)中的index.html: 
这里写图片描述
噔噔噔噔,请关注一下我标红的地方: 
1、浏览器报错。 
2、www.a.com中的foo中的后台数据请求成功了。

4.2.1、刚刚的浏览器报错,我们看看是什么错: 
这里写图片描述
错误: 
Uncaught SyntaxError: Unexpected token : 
这错误是js语法错误,为什么会有js语法错误。我们在使用script标签中的src属性对资源进行加载,被请求的资源会被当作js脚本进行解析处理,而www.a.com中的foo返回的是一串json数据({“name” : “www.a.com”}),所以会导致解析出错。

4.2.2、www.a.com中的foo中的后台数据是不是真的请求成功了,请看下图: 
这里写图片描述
这里写图片描述
以上两图中我们可以明确的得出,www.a.com中的foo中的后台数据的确是请求成功了。

4.3、重新修改AServer(www.a.com)中的foo的方法,,使其返回的是一段js脚本(因为刚刚4.2中浏览器报了js解析的错误,所以现在使后端返回js脚本,消除该错误): 
这里写图片描述

4.4、代码改好了,我们再次访问一下BServer(www.b.com)中的index.html: 
这里写图片描述
页面再次报错: 
Uncaught ReferenceError: foo is not defined at foo:1 
错误显示,foo这个方法没有被定义

4.5、在BServer(www.b.com)中的index.html中添加foo的方法(因为4.4中报错显示,foo方法没有定义,所以我们在页面中定义该方法): 
这里写图片描述

4.6、代码改好了,我们再次访问一下www.b.com中的index.html,一起见证奇迹的时刻到了: 
这里写图片描述

4.7小结 
1、script标签的src可以进行跨域请求、加载资源 
2、对要加载的资源进行包装,使其可以被当中js脚本进行解析。 
3、定义一个回调函数,获取传入的数据 
以上就是JSONP的工作原理。

5.化繁为简

5.1疑问 
1、用第4小结中的方法,进行跨域请求,是不是太麻烦了? 
对,是比较麻烦。 
2、有没有比较简单的方法呢? 
有,那就是通过JQuery使用JSONP。 
3、JQuery使用jsonp会不会很难? 
那下面就看看难不难吧。

5.2、通过JQuery使用JSONP 
5.2.1、修改BServer(www.b.com)中的index.html的代码: 
这里写图片描述 
简单的修改两处即可: 
1、dataType修改为jsonp 
2、jsonpCallback设置回调函数的名字,因为AServer(www.a.com)中返回的回调方法名是foo,所以该处填写的回调方法名也是foo

5.2.2、重新在浏览器打开BServer(www.b.com)中的index.html的页面: 
这里写图片描述
好了,成功了,JQuery中使用JSONP就是这么简单。

5.3、修改版 
5.3.1、对后台代码稍作修改: 
这里写图片描述

5.3.2、前台代码也稍作修改: 
这里写图片描述

5.3.3、重新在浏览器打开BServer(www.b.com)中的index.html的页面: 
这里写图片描述

5.3.4、看了5.3小节的代码修改后,你会不会有疑问? 
我想,你应该会问,为什么@RequestParam(“callback”)这段代码获取到的就是回调函数的名字,为什么是@RequestParam(“callback”)而不是@RequestParam(“xxx”)呢??? 
那么这里还需要介绍JQuery使用JSONP的一个参数那就是jsonp参数。what?Jsonp?感觉越说越懵逼,直接上图吧,看图应该可以说清楚点 
这里写图片描述
看看浏览器的请求: 
这里写图片描述

6.总结

以上就是我学习JSONP的一些个人总结,这个更像我的一些小笔记。第一次写博客,可能很多地方表达得不是很清楚,感觉写得有点乱,请各位看官多多包涵,哪里写得不对,或者需要修改,请指正指正,谢谢。

版权声明:本文为博主原创文章,未经博主允许不得转载。


打赏
最近浏览
891353192  LV1 2018年10月8日
zdm128136  LV8 2017年11月24日
taojava  LV3 2017年11月10日
jiaowoyuege  LV11 2017年10月15日
203778513  LV9 2017年9月13日
Luis虎子  LV16 2017年9月8日
马小跳  LV12 2017年8月30日
小夜埙  LV5 2017年7月4日
wangyifan1100  LV6 2017年6月30日
whb5566  LV10 2017年6月20日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友