前言
今天在学习vuejs的是时候,有关注到跨域请求的问题,这让我想到我之前的一个项目也有遇到过跨域请求的问题,既然再次遇见说明了一个道理:有缘既会再见!
再见了那我么就来了解一下吧。
什么是跨域
这里就要讲到同源策略,那么什么是同源策略?
同源策略,它是由Netscape提出的一个著名的安全策略。
现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。
当一个浏览器的两个tab页中分别打开百度和谷歌的页面
当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的
即检查是否同源,只有和百度同源的脚本才会被执行。
以上是百度百科low来的,知道什么意思就好。
什么是JSONP
JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
写过前端页面的同学会发现,Web页面上调用js文件时不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<\script>、<\img>、<\iframe>)。
于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP。
它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。
(这里需要注意的是:jsonp请求都是get请求,想想img标签,src就可以理解了为毛了)
实现原理
ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。
实现
这里我先上代码
ajax({
url: 'http://xiaolinge.com/jsonp',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'myCallBack',
data: {name:‘leo’,age:30},
success: function(data){
console.log(data)
}
});
jquery 动态生成script标签,并定义好方法。前提是jsonpCallback的方法名与引入的js文件方法名(即函数名)一致。
其实内部实现就是类似下面
<script>
$('#btn').click(function(){
var frame = document.createElement('script');
frame.src = 'http://xiaolinge.com/jsonp?name=leo&age=30&callback=func';
$('body').append(frame);
});
function func(res){
alert(res.message+res.name+'你已经'+res.age+'岁了');
}
</script>
这里可以看到,我们声明了一个func函数,但没有执行,你可以想一下,如果服务端接口到get请求,返回的是func({message:‘hello’}),这样一看就应该明白了吧。
其实ajax就是做了这样的封装了。
接下来我就low一个后台的代码,这里我就直接使用springMVC了:
@RequestMapping(value="/jsonp", method=RequestMethod.GET)
@ResponseBody
public JSONPObject login(HttpServletRequest request,HttpServletResponse response,@RequestParam String callback) throws Exception {
ModelAndView model = new ModelAndView();
List l=new ArrayList();
for(int i=0;i<2;i++){
Otc otc = new Otc();
otc.setName("测试1");
otc.setAge(i+1);
l.add(otc);
}
model.addObject("data", l);
return new JSONPObject(callback, model);
}
总结
OK到此就结束了,后面有机会还会继续深入。有问题的话欢迎评论哦。