zoukankan      html  css  js  c++  java
  • 学习 jsonp

    jsonp原理图

    1.起因

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

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

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

    项目结构也很简单。

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

     1 <html>
     2 <script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
     3 <body>
     4 <script type="text/javascript">
     5 $(function (){
     6     $("#getOtherDomainThings").click(function () {
     7         
     8         $.get("http://localhost:8080/webApp01/jquery-1.11.1.js", function (data) {
     9             
    10             alert(data);
    11         })
    12     })
    13 })
    14 </script>
    15 <h2>Hello World!</h2>
    16 <input type="button" value="submit" id="getOtherDomainThings"/>
    17 </body>
    18 </html>

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

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

     1 <html>
     2 <script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
     3 <body>
     4 <script type="text/javascript">
     5 $(function (){
     6     $("#getOtherDomainThings").click(function () {
     7         $.get("http://localhost:9080/webApp02/jquery-1.11.1.js", function (data) {
     8             
     9             alert(data);
    10         })
    11     })
    12 })
    13 </script>
    14 <h2>Hello World!</h2>
    15 <input type="button" value="subbmit" id="getOtherDomainThings"/>
    16 </body>
    17 </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的代码

     1 <html>
     2 <script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
     3 <body>
     4 <script type="text/javascript">
     5 $(function (){
     6     $("#getOtherDomainThings").click(function () {
     7         $.getJSON("http://localhost:9080/webApp02/jquery-1.11.1.js?callback=?", function (data) {
     8             
     9             alert(data);
    10         })
    11     })
    12 })
    13 </script>
    14 <h2>Hello World!</h2>
    15 <input type="button" value="subbmit" id="getOtherDomainThings"/>
    16 </body>
    17 </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文件内容改成这个样子

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

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

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

    2.3.实现-有格式json

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

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

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

     1 <html>
     2 <script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
     3 <body>
     4 <script type="text/javascript">
     5 $(function (){
     6     $("#getOtherDomainThings").click(function () {
     7         $.getJSON("http://localhost:9080/webApp02/test.jsp?callback=?", function (data) {
     8             
     9             alert("name=" + data.name + ",age=" + data.age);
    10         });
    11     });
    12 })
    13 </script>
    14 <h2>Hello World!</h2>
    15 <input type="button" value="subbmit" id="getOtherDomainThings"/>
    16 </body>
    17 </html>

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

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

    2.4实现-有参数有格式json

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

     1 <html>
     2 <script type="text/javascript" src="http://localhost:8080/webApp01/jquery-1.11.1.js"></script>
     3 <body>
     4 <script type="text/javascript">
     5 $(function (){
     6     $("#getOtherDomainThings").click(function () {
     7         $.getJSON("http://localhost:9080/webApp02/test.jsp?user=qyf404&callback=?", function (data) {
     8             alert("name=" + data.name + ",age=" + data.age);
     9         });
    10     });
    11 })
    12 </script>
    13 <h2>Hello World!</h2>
    14 <input type="button" value="subbmit" id="getOtherDomainThings"/>
    15 </body>
    16 </html>

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

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

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

    没问题,好用的不得了。

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

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

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

    示例代码下载

    作者:辵鵵
    欢迎转载,但未经作者同意请保留此段声明,并在文章页面明显位置给出原文链接。
  • 相关阅读:
    [转]Hamcrest使用方法实例
    Maven配置浅析
    Guava API
    awk排序作业
    [转]awk使用手册
    Vue源码探究-全局API
    vue 组件间传值
    在2018年如何优雅的开发一个typescript语言的npm包?
    PHP四种序列化方案
    从 0 到 1 再到 100, 搭建、编写、构建一个前端项目
  • 原文地址:https://www.cnblogs.com/qyf404/p/3868611.html
Copyright © 2011-2022 走看看