Cette fois, je vais vous montrer comment Jsonp peut résoudre le cross-domain ajax. Quelles sont les précautions pour que Jsonp résolve le cross-domain ajax. Ce qui suit est un cas pratique, jetons un coup d'œil.
1. Introduction
Il y a eu beaucoup de problèmes inter-domaines récemment, et il m'est arrivé de voir celui-ci, alors je l'ai résumé. , à propos de JSONP Il y a en effet beaucoup de choses sur Baidu, et beaucoup de gens en copient d'autres. Si cela continue, je ne peux en fait trouver que quelques informations. La clé est que je ne comprends toujours pas. problème de capacité. Après de nombreuses tentatives, je l'ai résumé. Au bout d'un moment, j'ai finalement compris. Une chose à noter est que Jsonp est utilisé ici pour résoudre le problème inter-domaines d'ajax. L'implémentation spécifique n'est pas réellement ajax.
1. Politique de même origine
Les navigateurs ont un concept très important : la politique de même origine. La soi-disant même origine signifie que le nom de domaine, le protocole et le port sont identiques. Les scripts côté client (JavaScript, ActionScript) provenant de différentes sources ne peuvent pas lire ou écrire les ressources des uns et des autres sans autorisation explicite.
2. JSONP
JSONP (JSON with Padding) est un "mode d'utilisation" de JSON qui peut être utilisé pour résoudre le problème de l'accès aux données entre domaines en navigateurs grand public. En raison de la politique de même origine, de manière générale, les pages Web situées sur server1.example.com ne peuvent pas communiquer avec des serveurs autres que server1.example.com, à l'exception de l'élément de script HTML. Grâce à cette politique ouverte de l'élément <script>, les pages Web peuvent obtenir des données JSON générées dynamiquement à partir d'autres sources, et ce modèle d'utilisation est appelé JSONP. Les données capturées avec JSONP ne sont pas du JSON, mais du JavaScript arbitraire, qui est exécuté avec un interpréteur JavaScript au lieu d'être analysé avec un analyseur JSON. </script>
2. Pratique
1. Simulez des requêtes inter-domaines
Faites-en deux. machine Il existe un tomcat et les ports sont respectivement 8080 et 8888, ce qui remplit la condition de non-même origine. Si vous envoyez ajax depuis un port pour obtenir des données d'un autre port, un problème de requête inter-domaine sera certainement signalé.
Il y a deux projets ici, à savoir jsonp (8080) et autre (8888). L'index.jsp dans le projet jsonp est le suivant :
nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <title>Insert title here</title> <script></script> <script> function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp', type:'post', dataType:'text', success:function(data){ console.log(data); } }); } </script> <input>
Le index.jsp dans l'autre projet (8888) est le suivant : // Parce que jsp est en fait un servlet, jsp est utilisé ici à la place du servlet pour la démonstration.
nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <title>Insert title here</title> <script></script> other domain
En fait, ce que vous voyez ci-dessus n'est rien de plus que de cliquer sur le bouton ajax de la page jsonp pour obtenir les données dans d'autres pages.
Les résultats sont les suivants : la console Chrome
XMLHttpRequest ne peut pas charger http://localhost:8888/other/index.jsp Non 'Access-. L'en-tête Control- Allow-Origin' est présent sur la ressource demandée. L'origine 'http://localhost:8080' n'est donc pas autorisée à accéder.
Les conseils ci-dessus font référence à des problèmes inter-domaines. à partir des ressources du domaine 8080.
2. Utilisez la balise script pour accéder aux fichiers js dans d'autres domaines
Étant donné que le src de la balise <script> Le plus courant est l'application des services CDN. Par exemple, dans mon projet, si je veux utiliser jQuery, mais qu'il n'existe pas de fichier js, le téléchargement prendra beaucoup de temps et je ne sais pas si. la version est correcte, alors je peux rechercher jquery cdn sur Baidu, je peux en trouver un au hasard, comme le CDN de bootstrap : http://www.bootcdn.cn/jquery/. Il existe de nombreuses versions parmi lesquelles choisir. ajoutez-le au projet. Le plus gros inconvénient est que si vous n'avez pas de connexion Internet, importez-le simplement. </script>
2.1 Créez le fichier js/other.js dans le chemin racine de other Le contenu de est le suivant :
alert("this is other(8888) js");
2.2 En jsonp. /index.jsp, ajoutez une balise de script, importez les js des autres
<script></script>
dans http://localhost:8080/jsonp/index.jsp, une alerte apparaîtra immédiatement, indiquant que le fichier importé js est automatiquement exécuté et la requête inter-domaine js est réussie.
2.3 De même, la référence directe exécutera immédiatement alert, puis écrira la fonction dans other.js, la même chose que jsonp/index.jsp. également être appelé dans , mais je ne démontrerai pas ce point. Cela se fait principalement dans le développement de projets, et la page est séparée de js/css.
2.4 另外说明一点,如果在other.js中有函数通过ajax调用8080中的东西,然后引入之后,调用这个函数,也是可以的,但是如果other.js中函数ajax调用8888的东西,引入之后,调用这个函数,同样是跨域的。
3、script实现跨域请求
3.1 简单模拟服务器返回数据
将jsonp/index.jsp改成如下:这里注意引入的other.js的位置,是在函数getResult之后的,如果在它之前的话,会提示函数不存在。js加载顺序是从上开始,在之前调用没创建的,不能成功。注意这里是指引入的js文件,如果是同一个js文件或者当前页面的js中,先执行调用,然后再写函数也是没有问题的,但是如果先执行调用引入js文件中的函数,然后再引入js文件,就会提示函数不存在。
<script></script> <script> function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/index.jsp', type:'post', dataType:'text', success:function(data){ console.log(data); } }); } function getResult(data){ alert(data.result); } </script> <script></script>
然后other.js
getResult({"result":"this is other domain's data"});
也就是在jsonp/index.jsp页面写好函数,然后引入其他域的js传入参数去调用这个函数,这里的参数你可以先看做是其他域服务器的接口返回的数据。
刷新页面,效果当然是
弹出alert框,this is other domain's data
3.2 模拟接口访问
看到这里,你会不会还是想不懂,上面js弄啥的,传个死的数据,有什么实际意义吗?,其实script的src不仅可以接js的地址,还可以接servlet的地址,也就是http接口地址,所以接下来,懒得写servlet,这里还是写jsp当做接口,在other项目中新建other.jsp页面,内容如下:
内容很简单,也就是接受一个params的参数,然后返回数据给调用者。
我们在jsonp/index.jsp中加上
<script></script>
看到这个地址,你是不是很熟悉,不熟悉的证明你用servlet用蠢了,jsp也是servlet,流程就是页面一加载的时候,script标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。
Uncaught SyntaxError: Unexpected identifier
报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。
还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错
<script> ajax cross success,the server receive params : jsonp_param </script>
那么js不能解析,我们换一种思路,要是我们输出的是JSON字符串或者调用当前页面函数的字符串了,类似于3.1中返回的getResult({“result”:”this is other domain's data”});
所以改造一下,把other.jsp中的内容改成
别忘了,之前jsonp/index.jsp中我们定义了,那么加入引用之后,依然记得getResult函数与引入函数的先后顺序问题。
<script> function getResult(data){ alert(data.result); } </script> <script></script>
刷新页面,发现大工告成。
至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是getResult(xxx),其中这里的xxx可以当做是经过接口的很多处理,然后塞进去的值,但是这个getResult这个函数名,调用方与其他域服务器这一方怎么约定这个名字是一致的了,况且很多公司自己做服务的,别的公司的开发人员去调用,难道每个人都去那么公司去约定调用函数的名字?怎么可能,所以有人就想出来了一种解决方案,当然不是我~~,其实也很简单啦,也就是把回调的函数名字也一起传过去不就行了,所以代码如下:
<script></script>
other.jsp
代码很简单,也就是传递一个回调函数的参数名,然后经过该接口一系列操作,将返回数据,塞到回调函数里面,调用端的函数就得到了该接口的数据,也就是类似于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") }</script>
4、Jquery的JSONP
至此跨域请求的原理已经讲清楚了,但是仍然还有一个问题,总觉得这样用有点怪是不是,如果用jquery的话,调用就很简单了,其实jquery底层实现也是拼了一个script,然后指定src这种方式,跟上面讲的一样,只是jquery封装了一下,显得更加优雅,跟ajax调用方式差不多,所以容易记,代码如下:
<script> function getResult(data){ alert("through jsonp,receive data from other domain : "+data.result); } function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据 success: function(data){ }, error: function(){ alert('fail'); } }); } </script> <input>
这里的jsonCallback,回调函数设置为getResult,那么返回后会先调用getResult函数中的代码,再调用success函数中的代码,一般情况下,不用定义getResult函数,同样jsonCallback不需要设置,那么就只执行success中的代码,也就跟平时的ajax一样用啦。
所以实际工作用法如下:
function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) success: function(data){ alert("through jsonp,receive data from other domain : "+data.result); }, error: function(){ alert('fail'); } }); }
这里没有指定jsonpCallback,实际上jquery底层拼装了一个函数名,当然生成函数规则就没研究了。
补充:
1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。</script>
3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!