JSONP解决跨域方案

一、jsonp原理

本质并不是ajax,只是执行了跨域js,所以该方式只支持get方式

html中,所有带src属性的标签都可以跨域script img iframe

所以,可以通过script加载其他域的一段动态脚本,这段脚本包含了所要的数据信息。

二、实现方式

2.1 自己封装jsonp方法: 

 function jsonp(url,data,callback){
      var script=document.createElement('script');
      document.body.appendChild(script);
      
      data=data||{};
      data.callback='cb'+new Date().getTime();
      window[data.callback]=callback;
      
      url+="?"+$.param(data);
      script.src=url;
      script.onload=function(){
          document.body.removeChild(script);
      }
  }

方法说明:

jsonp(url,data,callback):

url:后台的url方法,无需加[?callback=?]封装方法里头已经做了处理。

data:请求参数

callback:回调函数

调用方式:

jsonp('http://b.test.com:8888/'+path+'/public/monitorJsonp.do',{test:"ok"},function(data){
      alert("自己封装jsonp方式调用:"+data[0].name);
});

2.2 $.getJSON方式

$.getJSON('http://b.test.com:8888/'+path+'/public/monitorJsonp.do?callback=?',{test:"ok"},function(data){        
      alert("getJSON方式调用:"+data[0].name);
});

封装的jsonp和$getJSON有点相似,相关方法参考2.1 jsonp的方法说明。

尤其要注意$getJSON这方法的url后面一定要加[?callback=?],否则getJSON会默认为一个普通的ajax请求,就会报非同源问题的错误。

2.3 ajax指定返回jsonp类型 

ajax方式一

    $.ajax('http://b.test.com:8888/'+path+'/public/monitorJsonp.do?callback=?',{
        data:{test:"ok"},
        dataType:'jsonp'
    }).done(function(data){
        alert("Ajax方式一调用: "+data[0].name);
    });

ajax方式二

      $.ajax({  
            url:"http://b.test.com:8888/"+path+"/public/monitorJsonp.do",  
            dataType:'jsonp',  
            data:'',  
            jsonp:'callback',  
            success:function(data) {  
                alert("Ajax方式调用:  "+data[0].name);
            },  
            error:function(data){
                alert("请求错误,请稍后再试!");
            }
        });  

要制定好dataType为jsonp注意要小写,此外,jsonp要设置为callback。

java代码

    @RequestMapping(value="/monitorJsonp")
    @ResponseBody
    public void monitorJsonp(HttpServletRequest request,HttpServletResponse response){
        try {  
            response.setContentType("text/plain");  
            response.setHeader("Pragma", "No-cache");  
            response.setHeader("Cache-Control", "no-cache");  
            response.setDateHeader("Expires", 0);  
            
            PrintWriter out = response.getWriter();       
            String callback = request.getParameter("callback");    
            out.print(callback+"([ { name:'shawWey',age:'19'},{ name:'joe',age:'20'}] );");    
            out.print(callback);   
            
          } catch (IOException e) {  
             e.printStackTrace();  
          }  
    }

2.4 jsonp jsonpCallback 参数说明

jsonp:制定回调参数名称比如为callback或者其他名字,当然这儿改了相关后台获取回调函数的名称也要进行相应的修改。

jsonpCalllback:回调函数参数的名称

测试:

例如设置如下:

jsonp:"shaw",

jsonpCallback:"jsonpCallback"

请求如下,回调函数的名称以及值都改变了。

三、jsonp优缺点:

优点: 

比XML轻了很多,没有那么多冗余的东西。
JSON也是具有很好的可读性的,但是通常返回的都是压缩过后的。不像XML这样的浏览器可以直接显示,浏览器对于JSON的格式化的显示就需要借助一些插件了。
在JavaScript中处理JSON很简单。
其他语言例如PHP对于JSON的支持也不错。 

缺点:

只支持get方式  
后端代码要调整

JSONP 是构建 mashup 的强大技术,但不幸的是,它并不是所有跨域通信需求的万灵药。它有一些缺陷,在提交开发资源之前必须认真考虑它们。
  第一,也是最重要的一点,没有关于 JSONP 调用的错误处理。如果动态脚本插入有效,就执行调用;如果无效,就静默失败。失败是没有任何提示的。例如,不能从服务器捕捉到 404 错误,也不能取消或重新开始请求。不过,等待一段时间还没有响应的话,就不用理它了。(未来的 jQuery 版本可能有终止 JSONP 请求的特性)。
  JSONP 的另一个主要缺陷是被不信任的服务使用时会很危险。因为 JSONP 服务返回打包在函数调用中的 JSON 响应,而函数调用是由浏览器执行的,这使宿主 Web 应用程序更容易受到各类攻击。如果打算使用 JSONP 服务,了解它能造成的威胁非常重要。

跨域问题解决方案:代码下载

 

posted @ 2017-04-19 15:39  shawWey  阅读(555)  评论(0编辑  收藏  举报