Jsonp解决ajax跨域问题
<pre name="code" class="javascript">alert("this is other(8888) js");
<pre name="code" class="java"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp',type:'post',dataType:'text',success:function(data){ console.log(data); } }); } </script> </head> <body> <input type="button" value="jsonp" onclick="jsonp_fun()"/> </body> </html> other(8888)项目中index.jsp如下:// 因为jsp实际就是servlet,这里就用jsp代替servlet演示。
<pre name="code" class="java"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> <script type="text/javascript" src="js/jquery.min.js"></script> </head> <body> other domain </body> </html> 其实中上面看无非就是jsonp页面中点击按钮ajax去获取other页面中的数据。 结果如下:chrome控制台
XMLHttpRequest cannot load http://localhost:8888/other/index.jsp. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed 以上提示就是指跨域问题,不能从8080这个域去访问8888域的资源。 2、利用script标签去访问other域的js文件
alert("this is other(8888) js");
<script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script> 进入http://localhost:8080/jsonp/index.jsp,会立马弹出alert,表示引入的js文件自动执行了,跨域请求js成功。
3、script实现跨域请求
将jsonp/index.jsp改成如下:这里注意引入的other.js的位置,是在函数getResult之后的,如果在它之前的话,会提示函数不存在。js加载顺序是从上开始,在之前调用没创建的,不能成功。注意这里是指引入的js文件,如果是同一个js文件或者当前页面的js中,先执行调用,然后再写函数也是没有问题的,但是如果先执行调用引入js文件中的函数,然后再引入js文件,就会提示函数不存在。 <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp',success:function(data){ console.log(data); } }); } function getResult(data){ alert(data.result); } </script> <script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script> 然后other.js
getResult({"result":"this is other domain's data"}); 也就是在jsonp/index.jsp页面写好函数,然后引入其他域的js传入参数去调用这个函数,这里的参数你可以先看做是其他域服务器的接口返回的数据。 刷新页面,效果当然是 弹出alert框,this is other domain's data
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); out.println("ajax cross success,the server receive params :"+params); %> 内容很简单,也就是接受一个params的参数,然后返回数据给调用者。 我们在jsonp/index.jsp中加上 <script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script> 看到这个地址,你是不是很熟悉,不熟悉的证明你用servlet用蠢了,jsp也是servlet,流程就是页面一加载的时候,script标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。
报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。
还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错 <script type="text/javascript"> ajax cross success,the server receive params : jsonp_param </script> 那么js不能解析,我们换一种思路,要是我们输出的是JSON字符串或者调用当前页面函数的字符串了,类似于3.1中返回的 所以改造一下,把other.jsp中的内容改成 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); //out.println("ajax cross success,the server receive params :"+params); out.println("getResult({'result':'"+params+"'})"); %>别忘了,之前jsonp/index.jsp中我们定义了,那么加入引用之后,依然记得getResult函数与引入函数的先后顺序问题。
<script type="text/javascript"> function getResult(data){ alert(data.result); } </script> <script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script> 刷新页面,发现大工告成。 至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是getResult(xxx),其中这里的xxx可以当做是经过接口的很多处理,然后塞进去的值,但是这个getResult这个函数名,调用方与其他域服务器这一方怎么约定这个名字是一致的了,况且很多公司自己做服务的,别的公司的开发人员去调用,难道每个人都去那么公司去约定调用函数的名字?怎么可能,所以有人就想出来了一种解决方案,当然不是我~~,其实也很简单啦,也就是把回调的函数名字也一起传过去不就行了,所以代码如下: <script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult"></script>other.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 经过该接口一系列操作,然后得到data,将data返回给调用者 String data = "{'result':'"+params+"'}"; out.println(callback + "("+data+")"); %>代码很简单,也就是传递一个回调函数的参数名,然后经过该接口一系列操作,将返回数据,塞到回调函数里面,调用端的函数就得到了该接口的数据,也就是类似于ajax中succsss:function(data),然后处理data一样,这里的success回调函数,相当于上面的getResult函数。当然你也可以写的优雅一点,比如: function CreateScript(src) { $("<script><//script>").attr("src",src).appendTo("body") } function jsonp_fun(){ CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult") } 4、Jquery的JSONP至此跨域请求的原理已经讲清楚了,但是仍然还有一个问题,总觉得这样用有点怪是不是,如果用jquery的话,调用就很简单了,其实jquery底层实现也是拼了一个script,然后指定src这种方式,跟上面讲的一样,只是jquery封装了一下,显得更加优雅,跟ajax调用方式差不多,所以容易记,代码如下: <script type="text/javascript"> function getResult(data){ alert("through jsonp,receive data from other domain : "+data.result); } function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp',data:{'params':'fromjsonp'},dataType: "jsonp",jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据 success: function(data){ },error: function(){ alert('fail'); } }); } </script> <body> <input type="button" value="jsonp" onclick="jsonp_fun()"/> </body>
所以实际工作用法如下: function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp',//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) success: function(data){ alert("through jsonp,receive data from other domain : "+data.result); },error: function(){ alert('fail'); } }); } <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 经过该接口一系列操作,然后得到data,将data返回给调用者 String data = "{"result":""+params+""}"; out.println(callback + "("+data+")"); %> 这里没有指定jsonpCallback,实际上jquery底层拼装了一个函数名,当然生成函数规则就没研究了。 补充:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |