這次帶給大家Jsonp解決ajax的跨域問題,Jsonp解決ajax跨域問題的注意事項有哪些,下面就是實戰案例,一起來看一下。
一、介紹
最近跨域問題比較多,而且自己剛好也看到這一塊,就總結了一下,關於JSONP的東西百度的話東西確實很多,很多人都是複製別人的,如此下去,其實找的資料就那麼幾份,關鍵是我還看不懂,可能是能力問題吧,自己經過很多嘗試,所以總結了一下,終究還是弄懂了皮毛。注意一點是,這裡是用Jsonp解決ajax的跨域問題,具體的實作其實不是ajax。
1、同源策略
瀏覽器有一個很重要的概念-同源策略(Same-Origin Policy)。所謂同源是指,域名,協議,端口相同。不同源的客戶端腳本(JavaScript、ActionScript)在沒明確授權的情況下,不能讀寫對方的資源。
2、JSONP
JSONP(JSON with Padding)是JSON的一種”使用模式”,可用於解決主流瀏覽器的跨域資料存取的問題。由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而 HTML 的script 元素是例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這個使用模式就是所謂的 JSONP。用 JSONP 抓到的資料不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。 </script>
二、實作
1、模擬跨域請求
在本機弄兩個tomcat,端口分別為8080,8888,也就滿足了非同源的條件,那麼要是從一個端口發送ajax去獲取另外一個端口的數據,那麼肯定會報跨域請求問題。
這裡有兩個項目,分別是jsonp(8080),other(8888),在jsonp專案中index.jsp如下:
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)專案中index.jsp如下:// 因為jsp其實就是servlet,這裡就用jsp取代servlet示範。
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
其實中上面看無非就是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,我隨便找一個,例如bootstrap的cdn:http://www.bootcdn.cn/jquery/,有很多版本供你選擇,只要在項目中加上就行了,最大缺點的話就是你沒網的話,就引入不到啦。 </script>
2.1 在other根路徑建立js/other.js文件,內容如下:
alert("this is other(8888) js");
2.2 在jsonp/index.jsp中,加入script標籤,引入other的js
<script></script>
進入http://localhost:8080/jsonp/index.jsp,會立刻彈出alert,表示引入的js檔案自動執行了,跨域請求js成功。
2.3 同樣的,直接引用,會立刻執行立馬的alert,那麼在other.js中寫函數,同樣jsonp/index.jsp中也能調用到,這點就不演示了,專案開發中大多都是這樣做的,頁面與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中文网其它相关文章!
推荐阅读:
以上是Jsonp解決ajax的跨域問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver Mac版
視覺化網頁開發工具