多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > web前端 > htmlcss > Jsonp解決ajax跨域問題

Jsonp解決ajax跨域問題

來源:程序員人生   發布時間:2016-06-03 18:54:41 閱讀次數:5153次

1、介紹

最近跨域問題比較多,而且自己恰好也看到這1塊,就總結了1下,關于JSONP的東西百度的話東西確切很多,很多人都是復制他人的,如此下去,其實找的資料就那末幾份,關鍵是我還看不懂,多是能力問題吧,自己經過很多嘗試,所以總結了1下,終究還是弄懂了皮毛。注意1點是,這里是用Jsonp解決ajax的跨域問題,具體的實現其實不是ajax

1、同源策略

閱讀器有1個很重要的概念——同源策略(Same-Origin Policy)。所謂同源是指,域名,協議,端口相同。不同源的客戶端腳本(javascript、ActionScript)在沒明確授權的情況下,不能讀寫對方的資源。

2、JSONP

JSONP(JSON with Padding)是JSON的1種”使用模式”,可用于解決主流閱讀器的跨域數據訪問的問題。由于同源策略,1般來講位于 server1.example.com 的網頁沒法與不是 server1.example.com的服務器溝通,而 HTML 的script 元素是1個例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這類使用模式就是所謂的 JSONP。用 JSONP 抓到的資料其實不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器履行而不是用 JSON 解析器解析。

2、實踐

1、摹擬跨域要求

在本機弄兩個tomcat,端口分別為8080,8888,也就滿足了非同源的條件,那末要是從1個端口發送ajax去獲得另外1個端口的數據,那末肯定會報跨域要求問題。

這里寫圖片描述

這里有兩個項目,分別是jsonp(8080),other(8888),在jsonp項目中index.jsp以下:

<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%> <!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演示。

<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%> <!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 access.

以上提示就是指跨域問題,不能從8080這個域去訪問8888域的資源。

2、利用script標簽去訪問other域的js文件

由于<script>標簽的src是支持跨域要求的。最多見的就是CDN服務的利用啦,比如我項目中,如果想用jquery,但是就沒有這個js文件,去下載要找很久,而且版本還不知道下的對不對,那末可以百度搜jquery cdn,我隨意找1個,比如bootstrap的cdn:http://www.bootcdn.cn/jquery/,有很多版本供你選擇,只要在項目中加上就好了,最大缺點的話就是你沒網的話,就引入不到啦。

  • 2.1 在other根路徑創建js/other.js文件,內容以下:
alert("this is other(8888) js");
  • 2.2 在jsonp/index.jsp中,加入script標簽,引入other的js
<script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

進入http://localhost:8080/jsonp/index.jsp,會立馬彈出alert,表示引入的js文件自動履行了,跨域要求js成功。

這里寫圖片描述

  • 2.3 一樣的,直接援用,會立馬履行立馬的alert,那末在other.js中寫函數,一樣jsonp/index.jsp中也能調用到,這點就不演示了,項目開發中大多都是這樣做的,頁面與js/css分離。

  • 2.4 另外說明1點,如果在other.js中有函數通過ajax調用8080中的東西,然后引入以后,調用這個函數,也是可以的,但是如果other.js中函數ajax調用8888的東西,引入以后,調用這個函數,一樣是跨域的。

3、script實現跨域要求

將jsonp/index.jsp改成以下:這里注意引入的other.js的位置,是在函數getResult以后的,如果在它之前的話,會提示函數不存在。js加載順序是從上開始,在之前調用沒創建的,不能成功。注意這里是指引入的js文件,如果是同1個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', type:'post', dataType:'text', 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
  • 3.2 摹擬接口訪問
    看到這里,你會不會還是想不懂,上面js弄啥的,傳個死的數據,有甚么實際意義嗎?,其實script的src不但可以接js的地址,還可以接servlet的地址,也就是http接口地址,所以接下來,懶得寫servlet,這里還是寫jsp當作接口,在other項目中新建other.jsp頁面,內容以下:
<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%> <% String params = request.getParameter("params"); out.println("ajax cross success,the server receive params :"+params); %>

內容很簡單,也就是接受1個params的參數,然后返回數據給調用者。

我們在jsonp/index.jsp中加上

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

看到這個地址,你是否是很熟習,不熟習的證明你用servlet用蠢了,jsp也是servlet,流程就是頁面1加載的時候,script標簽就會去發送要求,然后返回數據。那末我們刷新頁面,看看效果。

這里寫圖片描述

Uncaught SyntaxError: Unexpected identifier

報錯了,如上,然后代碼有問題?No,點擊毛病,你會看到要求的東西也打印出來了,就是提示毛病,表示這個東西閱讀器不認識,實際上是script不認識啦。

這里寫圖片描述

還不明白,那末你去頁面加上以下內容,你看報不報錯!!肯定報錯

<script type="text/javascript"> ajax cross success,the server receive params : jsonp_param </script>

那末js不能解析,我們換1種思路,要是我們輸出的是JSON字符串或調用當前頁面函數的字符串了,類似于3.1中返回的
getResult({“result”:”this is other domain’s data”});

所以改造1下,把other.jsp中的內容改成

<%@ page language="java" contentType="text/html; charset=UTF⑻" pageEncoding="UTF⑻"%> <% 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://www.vxbq.cn/upload/caiji/20160601/http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

刷新頁面,發現大工告成。

這里寫圖片描述

至此,大部份原理已講完了,還有1個問題,這里服務器返回的是getResult(xxx),其中這里的xxx可以當作是經過接口的很多處理,然后塞進去的值,但是這個getResult這個函數名,調用方與其他域服務器這1方怎樣約定這個名字是1致的了,況且很多公司自己做服務的,別的公司的開發人員去調用,難道每一個人都去那末公司去約定調用函數的名字?怎樣可能,所以有人就想出來了1種解決方案,固然不是我~~,其實也很簡單啦,也就是把回調的函數名字也1起傳過去不就好了,所以代碼以下:

<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⑻" pageEncoding="UTF⑻"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 經過該接口1系列操作,然后得到data,將data返回給調用者 String data = "{'result':'"+params+"'}"; out.println(callback + "("+data+")"); %>

代碼很簡單,也就是傳遞1個回調函數的參數名,然后經過該接口1系列操作,將返回數據,塞到回調函數里面,調用真個函數就得到了該接口的數據,也就是類似于ajax中succsss:function(data),然后處理data1樣,這里的success回調函數,相當于上面的getResult函數。固然你也能夠寫的優雅1點,比如:

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

至此跨域要求的原理已講清楚了,但是依然還有1個問題,總覺得這樣用有點怪是否是,如果用jquery的話,調用就很簡單了,其實jquery底層實現也是拼了1個script,然后指定src這類方式,跟上面講的1樣,只是jquery封裝了1下,顯得更加優雅,跟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', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//傳遞給要求處理程序或頁面的,用以取得jsonp回調函數名的參數名(1般默許為:callback) jsonpCallback:"getResult",//自定義的jsonp回調函數名稱,默許為jQuery自動生成的隨機函數名,也能夠不寫這個參數,jQuery會自動為你處理數據 success: function(data){ }, error: function(){ alert('fail'); } }); } </script> <body> <input type="button" value="jsonp" onclick="jsonp_fun()"/> </body>

這里的jsonCallback,回調函數設置為getResult,那末返回后會先調用getResult函數中的代碼,再調用success函數中的代碼,1般情況下,不用定義getResult函數,一樣jsonCallback不需要設置,那末就只履行success中的代碼,也就跟平時的ajax1樣用啦。

所以實際工作用法以下:

function jsonp_fun(){ $.ajax({ url:'http://localhost:8888/other/other.jsp', type:'post', data:{'params':'fromjsonp'}, dataType: "jsonp", jsonp: "callback",//傳遞給要求處理程序或頁面的,用以取得jsonp回調函數名的參數名(1般默許為: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⑻" pageEncoding="UTF⑻"%> <% String params = request.getParameter("params"); String callback = request.getParameter("callback"); // 經過該接口1系列操作,然后得到data,將data返回給調用者 String data = "{\"result\":\""+params+"\"}"; out.println(callback + "("+data+")"); %>

這里沒有指定jsonpCallback,實際上jquery底層拼裝了1個函數名,固然生成函數規則就沒研究了。

這里寫圖片描述

補充:

  • 1、ajax和jsonp這兩種技術在調用方式上“看起來”很像,目的也1樣,都是要求1個url,然后把服務器返回的數據進行處理,因此jquery和ext等框架都把jsonp作為ajax的1種情勢進行了封裝;

  • 2、但ajax和jsonp其實本質上是不同的東西。ajax的核心是通過XmlHttpRequest獲得非本頁內容,而jsonp的核心則是動態添加<script>標簽來調用服務器提供的js腳本。

  • 3、所以說,其實ajax與jsonp的區分不在因而否跨域,ajax通過服務端代理1樣可以實現跨域,jsonp本身也不排擠同域的數據的獲得。

  • 4、還有就是,jsonp是1種方式或說非強迫性協議,猶如ajax1樣,它也不1定非要用json格式來傳遞數據,如果你愿意,字符串都行,只不過這樣不利于用jsonp提供公然服務。

另外補充最后1點:

Jsonp能解決的ajax跨域要求其實相當有限,推薦還是使用CROS,由于Jsonp的要求只能是get,雖然在上面演示中,我設置的type為post,但是實際上發的要求還是get,所以也就造成了萬1我的要求是post了,怎樣辦,要是跨域ajax文件上傳了,怎樣辦,這點希望大家注意:

這里寫圖片描述

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产福利在线免费观看 | 无人区一区二区三区乱码 | 亚洲欧美视频一区二区三区 | 亚洲精品在线不卡 | 亚洲欧美色欧另类欧 | 国产成人久久精品区一区二区 | 国产免费一区二区在线看 | 欧美性美 | 亚洲视频在线观看视频 | 综合自拍亚洲综合图区美腿丝袜 | 亚洲精品视频免费观看 | 国产精品爱久久久久久久9999 | 国产在线乱子伦一区二区 | 欧美成人吃奶高清视频 | 第一福利在线观看永久视频 | 亚洲私人影院 | 老女人做爰免费的视频 | 欧美久久久久久 | 欧美高清另类video | 国产成人精品区在线观看 | 伊人国产在线观看 | 欧美精品国产综合久久 | 麻豆精品国产自产在线 | 白嫩美女一级毛片免费看 | 久草在线新首页 | 免费人成毛片乱码 | 秋霞午夜 | 成人国产网站v片免费观看 成人国产亚洲 | 亚洲精品第一区二区三区 | 国产在线观看福利片 | 国产日韩欧美一区 | 午夜伊人 | 999yy成年在线视频免费看 | 欧美大交乱xxxx | 欧美成人网在线综合视频 | 亚洲无吗在线视频 | 国产美女一级做受在线观看 | 九九精品视频一区二区三区 | 免费一区二区三区四区五区 | 日日撸夜夜操 | 日本高清69 |