都知道ajax请求受同源策略限制而不能跨域访问数据,那么我们要实现跨域访问数据应该怎么办呢?通常有两种解决方案:
第一种,是比较古老比较简单的方法。同源策略限制是针对客户端浏览器而言,对服务器端则没有此限制,所以我们才能够通过爬虫类脚本在互联网上抓取数据。因此我们可以在服务器端通过HttpClient方式来完成“跨域访问”操作获取外部站点数据,然后在客户端浏览器中通过ajax访问本服务器端“跨域访问”对应的url,这样就能实现浏览器的“跨域访问”了。这种方式基于“转发”而实现,限制较少,但是开发工作量较大,不是我们这次主要讨论的方式。
第二种,jsonp,也是我们本次讨论重点。
jsonp原理:在客户端浏览器中,虽然ajax受到同源策略限制,但是<script>标签却可以跨域加载脚本,据此,我们可以加载一段位于外部站点的JS脚本代码,通过这段代码来执行在页面中我们需要执行的JS函数。
jsonp定义:利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP。
从原理和定义可以看出,jsonp的实质就是通过<script>标签发起请求,所以jsonp只支持get方式的访问,不支持post方式的访问。
那么对于jQuery.ajax({dataType:"jsonp", type:"post"})又是怎么回事呢?这里的jQuery.ajax({dataType:"jsonp"})容易给人造成一个误区,其实当dataType="jsonp"时,jQuery通过向页面添加<script>标签来发起请求,此时已经不是使用ajax协议了,而type="post"配置也没有任何用处,甚至beforeSend方法都会失效。
写一个简单的demo,在服务器端:
@ResponseBody @RequestMapping("jsonp/test") public String jsonp(String jsonpCallback) { String data = "{id:1,name:'Sunw',portal:'www.sunw.com'}";//这里data可能是查询数据库获得的数据,如果是对象,可以转为son字符串 return jsonpCallback + "(" + data + ")";//将数据传入回调函数中,拼成js代码字符串,jsonp调用完成后在页面会自动执行这个字符串代码 }在另一个站点的页面中,我们利用jsonp访问这个路径:
$.ajax({ url:"http://another.com/jsonp/text",//这是另一个站点的地址 dataType:"jsonp", jsonp:"jsonpCallback",//这个就是参数名字,默认为callback //jsonpCallback:"fun_name",//这个是指定回调函数名字,不指定的话jquery会自动生成一个“jsonp一串数字”格式的名字 success: function(data) {//不指定回调函数名时,success即为回调函数 //data就是外部站点获取到的数据 } })
ps:如果指定了jsonpCallback,则会先调用jsonpCallback函数,然后再调用success函数。jsonp不能用于文件上传
经过以上请求,我们打开火狐firebug就可以看见,控制台没有打印ajax请求的地址,而在网络面板中可以发现一个外部站点的get请求,这说明jsonp不是ajax协议的请求。
评论
你肿么看?