• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Joanna Qian
Stay Hungry, Stay Foolish!
博客园    首页    新随笔    联系   管理    订阅  订阅
JSONP的学习(收集整理)

JSONP和JSON之间有什么联系吗?

JSON(JavaScript Object Notation) 是一种轻量级、可读的基于文本的的数据交换格式。,是一种轻量的数据交换开放标准。源于JavsScript编程语言中对简单数据结构和关联数组的展示功能。它是仅含有数据对和简单括号结构的纯文本,因此可通过许多途径进行JSON消息的传递。对于JSON大家应该是很了解了吧,不是很清楚的朋友可以去json.org上了解下。

1. JSONP定义
    JSONP是英文JSON with Padding的缩写,是一个非官方的协议。它允许在服务器端生成script tags返回至客户端,通过javascript callback的形式来实现
跨域访问(这仅仅是JSONP简单的实现形式)--来源百度。 JSONP是一种script tag的注入,将server返回的response添加到页面实现特定功能。

2.JSONP由来

    要解释JSONP的来由,先要说一下浏览器的“同源策略(SOP:Same Origin Policy)”。 简而言之,就是浏览器限制脚本程序只能和同协议、同域名、同端口的脚本进行交互,这包括共享和传递变量等。cookie的传递也是遵从同样策略。这就造成 一些涉及到多个服务器的应用在整合时一些麻烦。跨域访问的问题造成A站点的Ajax代码无法访问B站点的数据。

     如何解决跨域访问呢?那就要借助浏览器 的一个特性:尽管浏览器不允许页面中的脚本程序跨域读取数据,但却允许HTML引用跨域的资源,如图片,CSS和脚本程序。对于脚本程序的引用比较特殊, 它被浏览器解析以后,就和本地的脚本程序别无二致且可立即进行解释并执行。如在B站点的一个js文件,一个简单的提示框:alert(“This is Victor!”);。在A站点引用这个js,这个脚本就会在B站点的应用中执行,显示一个alert信息。由于站外脚本的引用是通过script tag来实现的,而脚本程序又可通过DOM的方式可以对HTML页面的所有标签进行控制(包括动态的创建script标签),这就可以实现通过调用站外程 序对本地资源进行更改了。另外,通过<script> 标记的使用,就可从服务端直接返回可执行的JavaScript函数调用或者JSON数据。

 3. JSONP原理--CallBack
    首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先生成 JSON数据。然后以JavaScript 语法的方式,生成一个function, function名字就是传递上来的参数jsonp.

    然后,将JSON数据直接以入参的方式,放置到function中,这样就生成了一段 js 语法的文档,返回给客户端。
    最后,在客户端浏览器中解析script标签,并执行返回的JavaScript文档,此时数据作为参数,传入到了客户端预先定义好的回调函数里(动态执行回调函数) 。

其实 JSONP是个很简单的一个东西。主要是利用了 <script/>标签对javascript文档的动态解析来实现。(其实也可以用eval函数) 

 JSONP实现代码:

//远程服务器js文件代码:
localHandler({"result":"我是远程js带来的数据"});

//本地服务器下html页面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    var localHandler = function(data){
        alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
    };
    </script>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基 本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对 象各自的本地函数都不相同啊?

这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数(localHandler),然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义吧。

上面的例子是最简单的JSONP的实现模型,不过它还算不上一个真正的JSONP服务。我们来看一下真正的JSONP服务是怎么样的,比如Google的ajax搜索接口:http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=?&callback=? 

  • q=?这个问号是表示你要搜索的内容,最重要的是第二个callback=?这个是正如其名表示回调函数的名称,也就是将你自己在客户端定义的 回调函数的函数名传送给服务端,服务端则会返回以你定义的回调函数名的方法,将获取的json数据传入这个方法完成回调。

本地服务器下html页面代码改为:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script);
    </script>
</head>
<body>
</body>
</html>

服务器端的js

flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});

4. jQuery对JSONP的实现

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" >
 <head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){
        $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
             },
             error: function(){
                 alert('fail');
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
 </html>

是不是有点奇怪?为什么这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处 理jsonp类型的ajax时,自动帮你生成回调函数并 把数据取出来供success属性方法来调用

5.用 Java servlet 实现的 JSONP 服务

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
  throws ServletException, IOException {
    String jsonData = getDataAsJson(req.getParameter("symbol"));
    String output = req.getParameter("callback") + "(" + jsonData + ");";
    resp.setContentType("text/javascript");          
    PrintWriter out = resp.getWriter();
    out.println(output);
    // prints: jsonp1232617941775({"symbol" : "IBM", "price" : "91.42"});
}

6. 现成的 JSONP 服务

知道如何使用 JSONP 之后,可以开始使用一些现成的 JSONP Web 服务来构建应用程序和 mashup。下面为接下来的开发项目做准备。

  • Digg API:来自 Digg 的头条新闻:http://services.digg.com/stories/top?appkey=http%3A%2F%2Fmashup.com&type=javascript&callback=?
  • Geonames API:邮编的位置信息:http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?
  • Flickr API:来自 Flickr 的最新猫图片: http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?
  • Yahoo Local Search API:在邮编为 10504 的地区搜索比萨:http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query=pizza&zip=10504&results=2&output=json&callback=?

说明:

  • ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
  • 但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
  • 所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
  • 还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

JSONP的缺陷

    JSONP 是构建 mashup 的强大技术,但不幸的是,它并不是所有跨域通信需求的万灵药。它有一些缺陷,必须认真考虑它们。

  • 第一,也是最重要的一点,没有关于 JSONP 调用的错误处理。如果动态脚本插入有效,就执行调用;如果无效,就静默失败。失败是没有任何提示的。例如,不能从服务器捕捉到 404 错误,也不能取消或重新开始请求。不过,等待一段时间还没有响应的话,就不用理它了。(未来的 jQuery 版本可能有终止 JSONP 请求的特性)。
  • 第二, JSONP 被不信任的服务使用时会很危险。因为 JSONP 服务返回打包在函数调用中的 JSON 响应,而函数调用是由浏览器执行的,这使宿主 Web 应用程序更容易受到各类攻击。如果打算使用 JSONP 服务,了解它能造成的威胁非常重要。

参考:

  • 说说JSON和JSONP,也许你会豁然开朗
  • JSONP简介
  • 深入浅出JSONP--解决ajax跨域问题
  • 使用 JSONP 实现跨域通信,第 1 部分: 结合 JSONP 和 jQuery 快速构建强大的 mashup
posted on 2014-01-09 01:08  Joanna Qian  阅读(842)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3