首頁 web前端 js教程 Jsonp怎麼能解決ajax跨域

Jsonp怎麼能解決ajax跨域

Apr 25, 2018 pm 04:42 PM
ajax javascript jsonp

這次帶給大家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怎麼能解決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:&#39;http://localhost:8888/other/index.jsp&#39;,
type:&#39;post&#39;,
dataType:&#39;text&#39;,
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控制台

Jsonp怎麼能解決ajax跨域

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成功。

Jsonp怎麼能解決ajax跨域

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:&#39;http://localhost:8888/other/index.jsp&#39;,
type:&#39;post&#39;,
dataType:&#39;text&#39;,
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标签就会去发送请求,然后返回数据。那么我们刷新页面,看看效果。

Jsonp怎麼能解決ajax跨域

Uncaught SyntaxError: Unexpected identifier

报错了,如上,然后代码有问题?No,点击错误,你会看到请求的东西也打印出来了,就是提示错误,表示这个东西浏览器不认识,其实是script不认识啦。

Jsonp怎麼能解決ajax跨域

还不明白,那么你去页面加上如下内容,你看报不报错!!肯定报错

<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>
登入後複製

刷新页面,发现大工告成。

Jsonp怎麼能解決ajax跨域

至此,大部分原理已经讲完了,还有一个问题,这里服务器返回的是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:&#39;http://localhost:8888/other/other.jsp&#39;,
type:&#39;post&#39;,
data:{&#39;params&#39;:&#39;fromjsonp&#39;},
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"getResult",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以不写这个参数,jQuery会自动为你处理数据
success: function(data){
},
error: function(){
alert(&#39;fail&#39;);
}
});
}
</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底层拼装了一个函数名,当然生成函数规则就没研究了。

Jsonp怎麼能解決ajax跨域

补充:

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中文网其它相关文章!

推荐阅读:

不使用插件让Ajax实现异步刷新

ajax请求操作返回数据顺序

以上是Jsonp怎麼能解決ajax跨域的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

解決jQuery AJAX請求遇到403錯誤的方法 解決jQuery AJAX請求遇到403錯誤的方法 Feb 20, 2024 am 10:07 AM

標題:解決jQueryAJAX請求出現403錯誤的方法及程式碼範例403錯誤是指伺服器禁止存取資源的請求,通常會導致出現這個錯誤的原因是請求缺少權限或被伺服器拒絕。在進行jQueryAJAX請求時,有時會遇到這種情況,本文將介紹如何解決這個問題,並提供程式碼範例。解決方法:檢查權限:首先要確保請求的URL位址是正確的,同時驗證是否有足夠的權限來存取該資

PHP 與 Ajax:建立一個自動完成建議引擎 PHP 與 Ajax:建立一個自動完成建議引擎 Jun 02, 2024 pm 08:39 PM

使用PHP和Ajax建置自動完成建議引擎:伺服器端腳本:處理Ajax請求並傳回建議(autocomplete.php)。客戶端腳本:發送Ajax請求並顯示建議(autocomplete.js)。實戰案例:在HTML頁面中包含腳本並指定search-input元素識別碼。

解決jQuery AJAX請求403錯誤的方法 解決jQuery AJAX請求403錯誤的方法 Feb 19, 2024 pm 05:55 PM

jQuery是一個受歡迎的JavaScript函式庫,用來簡化客戶端端的開發。而AJAX則是在不重新載入整個網頁的情況下,透過發送非同步請求和與伺服器互動的技術。然而在使用jQuery進行AJAX請求時,有時會遇到403錯誤。 403錯誤通常是伺服器禁止存取的錯誤,可能是由於安全性原則或權限問題導致的。在本文中,我們將討論如何解決jQueryAJAX請求遭遇403錯誤

如何解決jQuery AJAX報錯403的問題? 如何解決jQuery AJAX報錯403的問題? Feb 23, 2024 pm 04:27 PM

如何解決jQueryAJAX報錯403的問題?在開發網頁應用程式時,經常會使用jQuery來發送非同步請求。然而,有時在使用jQueryAJAX時可能會遇到錯誤代碼403,表示伺服器禁止存取。這種情況通常是由伺服器端的安全性設定所導致的,但可以透過一些方法來解決這個問題。本文將介紹如何解決jQueryAJAX報錯403的問題,並提供具體的程式碼範例。一、使

如何使用Ajax從PHP方法取得變數? 如何使用Ajax從PHP方法取得變數? Mar 09, 2024 pm 05:36 PM

使用Ajax從PHP方法取得變數是Web開發中常見的場景,透過Ajax可以實作頁面無需刷新即可動態取得資料。在本文中,將介紹如何使用Ajax從PHP方法中取得變量,並提供具體的程式碼範例。首先,我們需要寫一個PHP檔案來處理Ajax請求,並傳回所需的變數。下面是一個簡單的PHP檔案getData.php的範例程式碼:

PHP 與 Ajax:建立動態載入內容的解決方案 PHP 與 Ajax:建立動態載入內容的解決方案 Jun 06, 2024 pm 01:12 PM

Ajax(非同步JavaScript和XML)允許在不重新載入頁面情況下新增動態內容。使用PHP和Ajax,您可以動態載入產品清單:HTML建立一個帶有容器元素的頁面,Ajax請求載入資料後將資料加入到該元素中。 JavaScript使用Ajax透過XMLHttpRequest向伺服器傳送請求,從伺服器取得JSON格式的產品資料。 PHP使用MySQL從資料庫查詢產品數據,並將其編碼為JSON格式。 JavaScript解析JSON數據,並將其顯示在頁面容器中。點選按鈕觸發Ajax請求,載入產品清單。

PHP 與 Ajax:提升 Ajax 安全性的方法 PHP 與 Ajax:提升 Ajax 安全性的方法 Jun 01, 2024 am 09:34 AM

為了提升Ajax安全性,有幾種方法:CSRF保護:產生令牌並將其傳送到客戶端,在請求中新增至伺服器端進行驗證。 XSS保護:使用htmlspecialchars()過濾輸入,防止惡意腳本注入。 Content-Security-Policy頭:限制惡意資源加載,指定允許載入腳本和樣式表的來源。驗證伺服器端輸入:驗證從Ajax請求接收的輸入,防止攻擊者利用輸入漏洞。使用安全Ajax函式庫:利用jQuery等函式庫提供的自動CSRF保護模組。

透過使用Ajax函數實現非同步資料交換的方法 透過使用Ajax函數實現非同步資料交換的方法 Jan 26, 2024 am 09:41 AM

如何利用Ajax函數實現非同步資料互動隨著網路和Web技術的發展,前端與後端之間的資料互動變得十分重要。傳統的資料互動方式,如頁面刷新和表單提交,已經無法滿足使用者的需求。而Ajax(AsynchronousJavaScriptandXML)則成為了實現非同步資料互動的重要工具。 Ajax透過使用JavaScript和XMLHttpRequest對象,使得網

See all articles