1.起因

js脚本做ajax异步调用的时候,直接请求普通文件存在跨域无权限访问的问题,不管你是静态页面、动态网页、web服务,只要是跨域请求,都无法成功;

如果上句话没明白,我们直接看例子。有两个一模一样的项目,一个webApp01,一个webApp02,分别在两个tomcat里启动,一个端口是8080,一个端口是9080。即两个访问地址是

http://localhost:8080/webApp01/
http://localhost:9080/webApp02/

项目结构也很简单。

webApp01中的index.jsp的代码如下:

 <html>
<script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
<body>
<script type="text/javascript">
$(function (){
$("#getOtherDomainThings").click(function () { $.get("http://localhost:8080/webApp01/jquery-1.11.1.js", function (data) { alert(data);
})
})
})
</script>
<h2>Hello World!</h2>
<input type="button" value="submit" id="getOtherDomainThings"/>
</body>
</html>

当我们访问http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本成功获取到了,如下图

但当我们改一下代码,要异步获取的文件不在同一个域下会发生什么?index.jsp代码改成如下所示

 <html>
<script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
<body>
<script type="text/javascript">
$(function (){
$("#getOtherDomainThings").click(function () {
$.get("http://localhost:9080/webApp02/jquery-1.11.1.js", function (data) { alert(data);
})
})
})
</script>
<h2>Hello World!</h2>
<input type="button" value="subbmit" id="getOtherDomainThings"/>
</body>
</html>

我们刷新一下http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本获取失败,如下图

看出来了吧,这就是js脚本做ajax异步调用的时候,直接请求普通文件存在跨域无权限访问的问题。请求压根就没有发出去。

2.解决方式

最简单的方式当然是让异步请求的数据在同一个域下了。不过伟大的攻城师找到了其他方式--jsonp。

jsonp的原理很简单,虽然ajax无法跨域请求,但是所有有src标签的元素都能跨域请求,比 img、iframe、script等。

2.1.JSONP和JSON关系

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。这个地方(json.org)可以学习json。

JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

2.2.实现-无格式json

我们继续改造我们的index.jsp的代码

 <html>
<script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
<body>
<script type="text/javascript">
$(function (){
$("#getOtherDomainThings").click(function () {
$.getJSON("http://localhost:9080/webApp02/jquery-1.11.1.js?callback=?", function (data) { alert(data);
})
})
})
</script>
<h2>Hello World!</h2>
<input type="button" value="subbmit" id="getOtherDomainThings"/>
</body>
</html>

我们刷新http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本成功获取到了,如下图

等等,好像有些不对劲,alert提示窗口没弹出来,而且请求的文件地址全称是http://localhost:9080/webApp02/jquery-1.11.1.js?callback=jQuery1111049328906112350523_1410439234844&_=1410439234845 。

我们在一个新浏览器窗口打开这个链接是没有问题的(当然也不会有什么问题,这已经不涉及到跨域的问题了)。

原来这种跨域请求只能返回json格式的数据,假设我们把这个webApp2上的jquery-1.11.1.js文件内容改成这个样子

 {"name":"qyf404","age":123}

我们再次刷新浏览器访http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本成功获取到了,如下图

结果和之前的没有区别,怎么回事?查了下资料,原来jsonp返回的json文本是有格式要求的。

2.3.实现-有格式json

我们在webApp02项目中创建一个test.jsp,内容如下

 <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String callback = request.getParameter("callback");
out.print(callback+"({ name:'qyf404',age:'27'});");
%>

我们把webApp01的index.jsp的代码改造一下,如下

 <html>
<script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
<body>
<script type="text/javascript">
$(function (){
$("#getOtherDomainThings").click(function () {
$.getJSON("http://localhost:9080/webApp02/test.jsp?callback=?", function (data) { alert("name=" + data.name + ",age=" + data.age);
});
});
})
</script>
<h2>Hello World!</h2>
<input type="button" value="subbmit" id="getOtherDomainThings"/>
</body>
</html>

我们再次刷新浏览器访http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本成功获取到了,而且json的内容也传过来了,如下图

大功告成。等等,还有一个问题?异步请求多数会带参数,有参数怎么处理?

2.4实现-有参数有格式json

让我们继续改造webApp01的index.jsp,追加请求参数,代码如下

 <html>
<script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
<body>
<script type="text/javascript">
$(function (){
$("#getOtherDomainThings").click(function () {
$.getJSON("http://localhost:9080/webApp02/test.jsp?user=qyf404&callback=?", function (data) {
alert("name=" + data.name + ",age=" + data.age);
});
});
})
</script>
<h2>Hello World!</h2>
<input type="button" value="subbmit" id="getOtherDomainThings"/>
</body>
</html>

继续改造webApp02的test.jsp页面,代码如下

 <%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<% String name = request.getParameter("user");
String callback = request.getParameter("callback");
out.print(callback+"({ name:'"+name+"',age:'27'});"); %>

我们再次刷新浏览器访http://localhost:8080/webApp01/并单击submit按钮后,看到jquery的脚本成功获取到了,而且json的内容也传过来了,如下图

没问题,好用的不得了。

最后让我们看看test.jsp到底返回了一个什么神奇的东东

jQuery111102533256879542023_1410490196678({ name:'qyf404',age:'27'});

原来test.jsp是返回了一个可以在本地执行的js脚本。不过这个方法名jQuery111102533256879542023_1410490196678是jQuwey自动生成的。

示例代码下载

学习 jsonp的更多相关文章

  1. 学习JSONP

    最近自己研究 跨域调用js,然后 发现 有jsonp 这种技术,在Jquery中可以使用,于是 研究下原理 发现: 其实 就是 利用<script>的跨域访问的能力. 调用 服务端 返回的 ...

  2. Django学习---jsonp跨域请求

    jsonp跨域请求 我们通过ajax进行跨域请求的时候,请求发送过去,但是在接受返回数据的时候浏览器会进行拦截. 这是由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源 ...

  3. Python学习---JSONP学习180130

    同源策略机制      同源:协议://IP:端口[协议,域名,端口相同]      跨域:知道对方接口,同时对方返回的数据也必须是Jsonp格式的 问题描述:Ajax跨域请求数据的时候,实际浏览器已 ...

  4. Python 系统学习梳理_【All】

    Python学习 1. Python学习---Python安装与基础1205 2. Python学习---PyCharm的使用学习 3. Python学习---Python数据类型1206 4. Py ...

  5. Json格式转化为string格式

    今天在学习Jsonp的时候,想通过服务端返回一段json数据,因为使用的服务端是NodeJs,那么就需要在js文件中实现返回json.(这里不懂的同学,可以先了解一下NodeJs的基础概念,在这里,我 ...

  6. 细说Ajax跨域

    一.什么是跨域 跨域问题来自于浏览器同源策略的限制,包括DOM同源限制和Ajax同源限制,本文探讨的是Ajax跨域.Ajax跨域指的是一个页面的Ajax只能请求和当前页面同源的数据,如果发现请求到的数 ...

  7. 由浅入深学习ajax跨域(JSONP)问题

    什么是跨域?说直白点就是获取别人网站上的内容.但这么说貌似又有点混淆,因为通常我们用ajax+php就可以获取别人网站的内容,来看下面这个例子. 来看看跨域的例子,jquery+ajax是不能跨域请求 ...

  8. 从 AJAX 到 JSONP的基础学习

    目录索引: 一.AJAX的概念二.POST && GET三.原生实现AJAX简单示例 3.1 实现代码 3.2 重点说明四.框架隐藏域 4.1 基本概念 4.2 后台写入脚本 4.3 ...

  9. 关于sencha touch 的JSONP跨域请求的学习研究

    此篇文章是对自己在研究学习sencha touch的过程中的点滴记录,主要是JSONP的跨域请求这方面,对于何为是跨域概念还有不熟悉的,可以自己问下度娘. 先上张图: 我要完成的功能就是表格下拉刷新, ...

随机推荐

  1. 【转】NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

    一.NoSQL的风生水起 1.1 后Web2.0时代的发展要求 随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经 ...

  2. ASP.NET中Request.RawUrl、Request.Url的区别

    如果访问的地址是: http://hovertree.com/guestbook/addmessage.aspx?key=hovertree%3C&n=myslider#zonemenu 那么 ...

  3. cros解决跨域

  4. script引入js文件问题

  5. Android Volley框架的使用(1)

    在Android开发中,经常要通过HTTP请求访问网络.为了使通过HTTP请求访问网络的过程更加简单,2013年提出了新的HTTP通信框架--Volley.Volley使用起来非常简单,适用于网络访问 ...

  6. ThinkCMF-首页Nav部分菜单配置详解

    Nav菜单代码放在了 /themes/simplebootx/Public/nav.html 具体代码: <?php $effected_id="main-menu"; $f ...

  7. 对chain.doFilter(request,response)的理解

    他的作用是将请求转发给过滤器链上下一个对象.这里的“下”指的是哪里 ? 指的是下一个filter,如果没有filter那就是你请求的资源. 一般filter都是一个链,web.xml 里面配置了几个就 ...

  8. AWS CloudFront CDN直接全站加速折腾记The request could not be satisfied. Bad request

    ERROR The request could not be satisfied. Bad request. Generated by cloudfront (CloudFront) Request ...

  9. 基于RulesEngine的业务规则实现

    规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.接受数据输入,解释业务规则,并根据业务规则做出业务决策.比较常见 ...

  10. 20款免费响应式的 HTML5 网站模板下载

    今天这篇文章给大家带来的是20款免费响应式的 HTML5 网站模板,大家可以借助这些优秀的网站模板创建自己的优秀网站.响应式(Responsive Design)设计的目标是要让产品界面能够响应用户的 ...