Dieses Mal zeige ich Ihnen, wie Jsonp Ajax-domänenübergreifend lösen kann. Was sind die Vorsichtsmaßnahmen für Jsonp, um Ajax-domänenübergreifend zu lösen?
1. Einleitung
In letzter Zeit gibt es viele domänenübergreifende Probleme, und ich habe dieses zufällig gesehen, also habe ich es zusammengefasst , über JSONP Es gibt tatsächlich viele Dinge auf Baidu, und viele Leute kopieren andere. Wenn das so weitergeht, kann ich tatsächlich nur ein paar Informationen finden. Der Schlüssel ist, dass ich es immer noch nicht verstehen kann Nach vielen Versuchen habe ich es zusammengefasst. Nach einer Weile habe ich es endlich herausgefunden. Zu beachten ist, dass Jsonp hier verwendet wird, um das domänenübergreifende Problem von Ajax zu lösen. Die spezifische Implementierung ist nicht wirklich Ajax.
1. Same-Origin-Richtlinie
Browser haben ein sehr wichtiges Konzept – Same-Origin-Richtlinie. Der sogenannte Same Origin bedeutet, dass Domainname, Protokoll und Port gleich sind. Clientseitige Skripte (JavaScript, ActionScript) aus unterschiedlichen Quellen können ohne ausdrückliche Genehmigung nicht gegenseitig die Ressourcen lesen oder schreiben.
2. JSONP
JSONP (JSON mit Padding) ist ein „Nutzungsmodus“ von JSON, der zur Lösung des Problems des domänenübergreifenden Datenzugriffs verwendet werden kann Mainstream-Browser. Aufgrund der Same-Origin-Richtlinie können Webseiten, die sich auf server1.example.com befinden, im Allgemeinen nicht mit anderen Servern als server1.example.com kommunizieren, mit Ausnahme des HTML-Skriptelements. Mithilfe dieser offenen Richtlinie des <script>-Elements können Webseiten dynamisch aus anderen Quellen generierte JSON-Daten abrufen. Dieses Verwendungsmuster wird als JSONP bezeichnet. Bei den mit JSONP erfassten Daten handelt es sich nicht um JSON, sondern um beliebiges JavaScript, das mit einem JavaScript-Interpreter ausgeführt wird, anstatt mit einem JSON-Parser analysiert zu werden. </script>
2. Üben
1. Simulieren Sie domänenübergreifende Anfragen
Machen Sie zwei davon Maschine Es gibt einen Tomcat und die Ports sind 8080 bzw. 8888, was die Bedingung eines nicht gleichen Ursprungs erfüllt. Wenn Sie Ajax von einem Port senden, um Daten von einem anderen Port zu erhalten, wird definitiv ein domänenübergreifendes Anforderungsproblem gemeldet.
Hier gibt es zwei Projekte, nämlich jsonp (8080), other (8888). Die index.jsp im jsonp-Projekt lautet wie folgt:
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>
other (8888) Die index.jsp im Projekt lautet wie folgt: // Da JSP tatsächlich ein Servlet ist, wird zur Demonstration hier JSP anstelle von Servlet verwendet.
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
Tatsächlich ist das, was Sie oben sehen, nichts anderes als das Klicken auf die Ajax-Schaltfläche auf der JSONP-Seite, um die Daten auf anderen Seiten abzurufen.
Die Ergebnisse sind wie folgt: Chrome-Konsole
XMLHttpRequest kann http://localhost:8888/other/index.jsp nicht laden. Der Header „Control-Allow-Origin“ ist auf der angeforderten Ressource „http://localhost:8080“ vorhanden. Der Zugriff ist daher nicht gestattet.
Die oben genannten Tipps beziehen sich auf domänenübergreifende Probleme. Sie können nicht auf 8888 zugreifen aus den 8080-Domänenressourcen.
2. Verwenden Sie das script-Tag, um auf js-Dateien in anderen Domänen zuzugreifen
Da der src des <script>-Tags domänenübergreifende Anforderungen unterstützt. Am gebräuchlichsten ist die Anwendung von CDN-Diensten. Wenn ich in meinem Projekt beispielsweise jQuery verwenden möchte, es aber keine solche js-Datei gibt, dauert das Herunterladen lange, und ich weiß nicht, ob Wenn die Version korrekt ist, kann ich nach dem Zufallsprinzip nach jquery cdn suchen, z. B. nach dem Bootstrap-CDN: http://www.bootcdn.cn/jquery/. Es gibt viele Versionen, aus denen Sie auswählen können Fügen Sie es dem Projekt hinzu. Der größte Nachteil besteht darin, dass Sie es nicht importieren können, wenn Sie keine Internetverbindung haben. </script>
2.1 Erstellen Sie die Datei js/other.js im Stammpfad von other. Der Inhalt von lautet wie folgt:
alert("this is other(8888) js");
2.2 In jsonp/index .jsp, fügen Sie das Skript-Tag hinzu, importieren Sie die js anderer Personen
<script></script>
in http://localhost:8080/jsonp/index.jsp. Es wird sofort eine Warnung angezeigt, die darauf hinweist, dass die importierte js-Datei vorhanden ist wird automatisch ausgeführt und die domänenübergreifende Anforderung für js ist erfolgreich.
2.3 In ähnlicher Weise führt ein direkter Verweis die Warnung sofort aus und schreibt dann die Funktion in other.js, genau wie jsonp/index.jsp. Es kann kann auch aufgerufen werden, aber ich werde diesen Punkt nicht demonstrieren. Dies geschieht hauptsächlich in der Projektentwicklung und die Seite ist von js/css getrennt.
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中文网其它相关文章!
推荐阅读:
Das obige ist der detaillierte Inhalt vonWie kann Jsonp Ajax domänenübergreifend lösen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!