您的当前位置:首页js实现跨域的4种实用方法原理分析_javascript技巧
广告

js实现跨域的4种实用方法原理分析_javascript技巧

2023-12-06 来源:哗驼汽车网
什么是js跨域呐?

js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

要解决跨域的问题,我们可以使用以下几种方法:

一、通过jsonp跨域

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php,那么a.html中的代码就可以这样:

我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

因为是当做一个js文件来引入的,所以http://example.com/data.php返回的必须是一个能执行的js文件,所以这个页面的php代码可能是这样的:

最终那个页面输出的结果是:

所以通过http://example.com/data.php?callback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

2、通过修改document.domain来跨子域

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

在页面 http://www.example.com/a.html 中设置document.domain:

在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

这样我们就可以通过js访问到iframe中的各种属性和对象了。

不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。

3、使用window.name来进行跨域

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

比如:有一个页面a.html,它里面有这样的代码:

再看看b.html页面的代码:

a.html页面载入后3秒,跳转到了b.html页面,结果为:

我们看到在b.html页面上成功获取到了它的上一个页面a.html给window.name设置的值。如果在之后所有载入的页面都没对window.name进行修改的话,那么所有这些页面获取到的window.name的值都是a.html页面设置的那个值。当然,如果有需要,其中的任何一个页面都可以对window.name的值进行修改。注意,window.name的值只能是字符串的形式,这个字符串的大小最大能允许2M左右甚至更大的一个容量,具体取决于不同的浏览器,但一般是够用了。

上面的例子中,我们用到的页面a.html和b.html是处于同一个域的,但是即使a.html与b.html处于不同的域中,上述结论同样是适用的,这也正是利用window.name进行跨域的原理。

下面就来看一看具体是怎么样通过window.name来跨域获取数据的。还是举例说明。

比如有一个www.example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.gxlcms.com/data.html里的数据。

data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

那么在a.html页面中,我们怎么把data.html页面载入进来呢?显然我们不能直接在a.html页面中通过改变window.location来载入data.html页面,因为我们想要即使a.html页面不跳转也能得到data.html里的数据。答案就是在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。

充当中间人的iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为www.gxlcms.com/data.html就行了。然后a.html想要得到iframe所获取到的数据,也就是想要得到iframe的window.name的值,还必须把这个iframe的src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是整个跨域过程。

看下a.html页面的代码:

上面的代码只是最简单的原理演示代码,你可以对使用js封装上面的过程,比如动态的创建iframe,动态的注册各种事件等等,当然为了安全,获取完数据后,还可以销毁作为代理的iframe。网上也有很多类似的现成代码,有兴趣的可以去找一下。

通过window.name来进行跨域,就是这样子的。

4、使用HTML5中新引进的window.postMessage方法来跨域传送数据

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第二种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的,而且也可以使用window.postMessage这个方法。下面看一个简单的示例,有两个页面

我们运行a页面后得到的结果:

我们看到b页面成功的收到了消息。

使用postMessage来跨域传送数据还是比较直观和方便的,但是缺点是IE6、IE7不支持,所以用不用还得根据实际需要来决定。

除了以上几种方法外,还有flash、在服务器上设置代理页面等跨域方式,这里就不做介绍了。

以上四种方法,可以根据项目的实际情况来进行选择应用,希望这篇文章对大家的学习有所帮助。

小编还为您整理了以下内容,可能对您也有帮助:

js实现跨域的几种方法汇总(图片ping、JSONP和CORS)_javascript技巧

跨域

虽然有同源策略的存在,但是在js中跨域也依然很常见,有document.domain、window.name、图片ping、jsonp、CORS,在这里简单总结下图片ping、jsonp和CORS备忘。

图片ping

图片可以从任何URL中加载,所以将img的src设置成其他域的URL,即可以实现简单的跨域,可以使用onload和onerror事件来确定是否接受到了响应。

这里新建了一个img对象,给出的url是博客地址,这里是个error事件,所以弹出error;如果将URL改为一张图片http://images.jb51.net//710118/o_MacBook%20Air.png,就会弹出onload加载信息success,从而实现了简单的跨域。

使用图片ping跨域只能发送get请求,并且不能访问响应的文本,只能监听是否响应而已,可以用来追踪广告点击。

jsonp

jsonp是带有回调函数callback的json,原名json with padding,翻译是填充式json,参数式json。

因为script的src可以跨域,所以在发送的URL后添加一个callback参数传递给服务器,然后服务器返回的数据会作为callback的参数,因为这个callback是我们自己来实现的,所以可以对接受到的json数据进行处理。

简单代码如下:

function call(data){

alert(data.city);

}

这里,我们把脚本的src设置为http://freegeoip.net/json/?callback=call,这是一个获取用户ip地址的api(有兴趣的可以点击这里查看),然后将callback作为一个参数拼接在URL后,返回的json数据就会作为callback的参数,在这里callback我们定义为call函数,即返回的json数据就会作为call的参数传进去,这个call函数仅仅弹出用户的城市city。笔者这里的输出结果是河北。其他ip信息可以查看官网,上面有详细的列表,比如country_name,time_zone等。

CORS(跨资源共享)

CORS是跨资源共享,cross site resourse sharing,它和ajax其实是大体相同的,对于ie实例化的是xdr对象,XDomainRequest,我们能访问的也只有responseText,触发的事件有load和error,写法和xhr大体相同,也需要open和send。

对于ff,chrome等其他浏览器实例化的是xhr,在这里myvin仅仅拿xhr来演示下,如果要实现跨浏览器,可以配合xdr实现兼容。

xhr如下:

这里使用的url是http://www.gxlcms.com,和ajax唯一的区别就是url使用的是跨域的绝对地址,在ajax中使用的本页面内的相对地址或绝对地址。

看一下控制台,这里用的是ff40.0.3,显示信息如下:

已阻止跨源请求:同源策略禁止读取位于 http://www.gxlcms.com 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

所以用CORS实现跨域还有一步要做,就是在服务器端设置Access-Control-Allow-Origin。

使用JavaScript 实现各种跨域的方法

一、一些概念
①传统Ajax:交互的数据格式——自定义字符串或XML描述;
    跨域——通过服务器端代理解决。
②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域。
③JSON:一种数据交换格式。基于纯文本、被原生JS支持。
  
格式:两种数据类型描述符:大括号{
}、方括号[
]。分隔符逗号、映射符冒号、定义符双引好。
④JSONP:一种跨域数据交互协议,非官方。
  1、Web页面调用js文件,可跨域。扩展:但凡有src属性的标签都具有跨域能力。
  2、跨域服务器
动态生成数据
并存入js文件(通常json后缀),供客户端
调用。
  3、为了便于客户端使用数据,形成一个非正式传输协议,称为JSONP。该协议重点是允许用户传递一个callback参数给服务器,然后服务器返回数据时
将此callback参数作为函数名包裹住JSON数据,使得客户端可以随意定制自己的函数来自动处理返回数据。
二、JSONP实现
实例1——客户端单方面接收:
①客户端——在客户端设置创建一个函数对象,名称可为callFunc,用于接收服务器的js数据和对其进行处理。
  js数据中的核心是:调用callFunc函数的同时附带着参数,此参数即data对象的值。
复制代码
代码如下:
<script
type="text/javascript">

var
callFunc
=
function(data){

alert('远程js文件传来的数据:'
+
data.result);//data为服务器端的JSON数据对象。

};
</script>
<script
type="text/javascript"
src="http://其他域的js文件.com/remote.js"></script>
②服务器端——直接调用客户端js中的函数,并传入数据。
复制代码
代码如下:
callFunc({"result":"value1"});
实例2——客户端向服务器传送
指定函数名,服务器端接收该函数名
并调用对应函数
将数据以参数形式传入。
复制代码
代码如下:
<script
type="text/javascript">

//
得到航班信息查询结果后的回调函数

var
flightHandler
=
function(data){

alert('你查询的航班结果是:票价
'
+
data.price
+
'
元,'
+
'余票
'
+
data.tickets
+
'
张。');

};

//
动态添加链接服务器js文件的script。
  //
在url地址中传递了一个code参数匹配JSON数据中的某个key,callback参数则告诉服务器:本地回调函数名为callFuncName。

var
url
=
"http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=callFuncName";

var
script
=
document.createElement('script');

script.setAttribute('src',
url);

//
将script元素在网页加载时插入head头部

document.getElementsByTagName('head')[0].appendChild(script);
</script>
总结:实现的代码并不复杂,但在实现Ajax跨域、frameset/iframe跨域等却是效率颇高的。

使用JavaScript 实现各种跨域的方法

一、一些概念
①传统Ajax:交互的数据格式——自定义字符串或XML描述;
    跨域——通过服务器端代理解决。
②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域。
③JSON:一种数据交换格式。基于纯文本、被原生JS支持。
  
格式:两种数据类型描述符:大括号{
}、方括号[
]。分隔符逗号、映射符冒号、定义符双引好。
④JSONP:一种跨域数据交互协议,非官方。
  1、Web页面调用js文件,可跨域。扩展:但凡有src属性的标签都具有跨域能力。
  2、跨域服务器
动态生成数据
并存入js文件(通常json后缀),供客户端
调用。
  3、为了便于客户端使用数据,形成一个非正式传输协议,称为JSONP。该协议重点是允许用户传递一个callback参数给服务器,然后服务器返回数据时
将此callback参数作为函数名包裹住JSON数据,使得客户端可以随意定制自己的函数来自动处理返回数据。
二、JSONP实现
实例1——客户端单方面接收:
①客户端——在客户端设置创建一个函数对象,名称可为callFunc,用于接收服务器的js数据和对其进行处理。
  js数据中的核心是:调用callFunc函数的同时附带着参数,此参数即data对象的值。
复制代码
代码如下:
<script
type="text/javascript">

var
callFunc
=
function(data){

alert('远程js文件传来的数据:'
+
data.result);//data为服务器端的JSON数据对象。

};
</script>
<script
type="text/javascript"
src="http://其他域的js文件.com/remote.js"></script>
②服务器端——直接调用客户端js中的函数,并传入数据。
复制代码
代码如下:
callFunc({"result":"value1"});
实例2——客户端向服务器传送
指定函数名,服务器端接收该函数名
并调用对应函数
将数据以参数形式传入。
复制代码
代码如下:
<script
type="text/javascript">

//
得到航班信息查询结果后的回调函数

var
flightHandler
=
function(data){

alert('你查询的航班结果是:票价
'
+
data.price
+
'
元,'
+
'余票
'
+
data.tickets
+
'
张。');

};

//
动态添加链接服务器js文件的script。
  //
在url地址中传递了一个code参数匹配JSON数据中的某个key,callback参数则告诉服务器:本地回调函数名为callFuncName。

var
url
=
"http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=callFuncName";

var
script
=
document.createElement('script');

script.setAttribute('src',
url);

//
将script元素在网页加载时插入head头部

document.getElementsByTagName('head')[0].appendChild(script);
</script>
总结:实现的代码并不复杂,但在实现Ajax跨域、frameset/iframe跨域等却是效率颇高的。

javascript 跨域调用js文件问题.....

三种方法实现js跨域访问

1.基于iframe实现跨域 

     基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com,或是xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是80),这样在两个页面中同时添加document.domain,就可以实现父页面调用子页面的函数,代码如下:

页面一代码:

<html>

<head>

  <script>

   document.domain = "xx.com";

    function aa(){

      alert("p");

   }

  </script>

</head>

<body>

   <iframe src="http://localhost:8080/cmsui/2.html" id="i">

   

   </iframe>

   <script>

  document.getelementbyid('i').oncg = function(){

 var d = document.getelementbyid('i').contentwindow;

 d.a();

 

 };

   </script>

 </body>

</html>

页面二代码:

<html>

 <head>

  <script>

    document.domain = "xx.com";

    function a(){

    alert("c");

     }

  </script>

 </head>

 <body>

 </body>

</html>

这时候父页面就可以调用子页面的a函数,实现js跨域访问

2.基于script标签实现跨域 

     script标签本身就可以访问其它域的资源,不受浏览器同源策略的,可以通过在页面动态创建script标签,代码如下

  var script = document.createElement('script');

  script.src = "http://aa.xx.com/js/*.js";

  document.body.appendChild(script);

 这样通过动态创建script标签就可以加载其它域的js文件,然后通过本页面就可以调用加载后js文件的函数,这样做的缺陷就是不能加载其它域的文档,只能是js文件,jsonp便是通过这种方式实现的,jsonp通过向其它域传入一个callback参数,通过其他域的后台将callback参数值和json串包装成javascript函数返回,因为是通过script标签发出的请求,浏览器会将返回来的字符串按照javascript进行解析执行,实现了域与域之间的数据传输。 

jquery中对jsonp的支持也是基于此方案

3.后台代理方式 

     这种方式可以解决所有跨域问题,也就是将后台作为代理,每次对其它域的请求转交给本域的后台,本域的后台通过模拟http请求去访问其它域,再将返回的结果返回给前台,这样做的好处是,无论访问的是文档,还是js文件都可以实现跨域

使用jquery的jsonp如何发起跨域请求及其原理详解

前言

本文主要给大家介绍的是关于jquery jsonp发起跨域请求及其原理的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:

跨域的安全都是对浏览器端来说的,服务器端是不存在跨域安全的。

浏览器的同源策略从一个源加载的文档或脚本与来自另一个源的资源进行交互。

如果协议,端口和主机对于两个页面是相同的,则两个页面具有相同的源,否则就是不同源的。

如果要在js里发起跨域请求,则要进行一些特殊处理了。或者,你可以把请求发到自己的服务端,再通过后台代码发起请求,再将数据返回前端。

这里讲下使用jquery的jsonp如何发起跨域请求及其原理。

先看下准备环境:两个端口不一样,构成跨域请求的条件。

获取数据:获取数据的端口为9090

请求数据:请求数据的端口为8080

1、先看下直接发起ajax请求会怎么样

下面是发起请求端的代码:

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

$(document).ready(function () {

$("#btn").click(function () {

$.ajax({

url: 'http://localhost:9090/student',

type: 'GET',

success: function (data) {

$(text).val(data);

}

});

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

请求的结果如下图:可以看到跨域请求因为浏览器的同源策略被拦截了。

2、接下来看如何发起跨域请求。解决跨域请求的方式有很多,这里只说一下jquery的jsop方式及其原理。

首先我们需要明白,在页面上直接发起一个跨域的ajax请求是不可以的,但是,在页面上引入不同域上的js脚本却是可以的,就像你可以在自己的页面上使用<img src=""> 标签来随意显示某个域上的图片一样。

比如我在8080端口的页面上请求一个9090端口的图片:可以看到直接通过src跨域请求是可以的。

3、那么看下如何使用<script src="">来完成一个跨域请求:

当点击"跨域获取数据"的按钮时,添加一个<script>标签,用于发起跨域请求;注意看请求地址后面带了一个callback=showData的参数;

showData即是回调函数名称,传到后台,用于包裹数据。数据返回到前端后,就是showData(result)的形式,因为是script脚本,所以自动调用showData函数,而result就是showData的参数。

至此,我们算是跨域把数据请求回来了,但是比较麻烦,需要自己写脚本发起请求,然后写个回调函数处理数据,不是很方便。

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

//回调函数

function showData (result) {

var data = JSON.stringify(result); //json对象转成字符串

$("#text").val(data);

}

$(document).ready(function () {

$("#btn").click(function () {

//向头部输入一个脚本,该脚本发起一个跨域请求

$("head").append("<script src='http://localhost:9090/student?callback=showData'></script>");

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

服务端:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=UTF-8");

//数据

List<Student> studentList = getStudentList();

JSONArray jsonArray = JSONArray.fromObject(studentList);

String result = jsonArray.toString();

//前端传过来的回调函数名称

String callback = request.getParameter("callback");

//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了

result = callback + "(" + result + ")";

response.getWriter().write(result);

}

结果:

4、再来看jquery的jsonp方式跨域请求:

服务端代码不变,js代码如下:最简单的方式,只需配置一个dataType:'jsonp' ,就可以发起一个跨域请求。jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。

这里的success就跟上面的showData一样,如果有success函数则默认success()作为回调函数。

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

$(document).ready(function () {

$("#btn").click(function () {

$.ajax({

url: "http://localhost:9090/student",

type: "GET",

dataType: "jsonp", //指定服务器返回的数据类型

success: function (data) {

var result = JSON.stringify(data); //json对象转成字符串

$("#text").val(result);

}

});

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

效果:

再看看如何指定特定的回调函数:第30行代码

回调函数你可以写到<script>下(默认属于window对象),或者指明写到window对象里,看jquery源码,可以看到jsonp调用回调函数时,是调用的window.callback。

然后看调用结果,发现,请求时带的参数是:callback=showData;调用回调函数的时候,先调用了指定的showData,然后再调用了success。所以,success是返回成功后必定会调用的函数,就看你怎么写了。

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

function showData (data) {

console.info("调用showData");

var result = JSON.stringify(data);

$("#text").val(result);

}

$(document).ready(function () {

// window.showData = function (data) {

// console.info("调用showData");

//

// var result = JSON.stringify(data);

// $("#text").val(result);

// }

$("#btn").click(function () {

$.ajax({

url: "http://localhost:9090/student",

type: "GET",

dataType: "jsonp", //指定服务器返回的数据类型

jsonpCallback: "showData", //指定回调函数名称

success: function (data) {

console.info("调用success");

}

});

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

效果图:

再看看如何改变callback这个名称:第23行代码

指定callback这个名称后,后台也需要跟着更改。

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

function showData (data) {

console.info("调用showData");

var result = JSON.stringify(data);

$("#text").val(result);

}

$(document).ready(function () {

$("#btn").click(function () {

$.ajax({

url: "http://localhost:9090/student",

type: "GET",

dataType: "jsonp", //指定服务器返回的数据类型

jsonp: "theFunction", //指定参数名称

jsonpCallback: "showData", //指定回调函数名称

success: function (data) {

console.info("调用success");

}

});

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

后台代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=UTF-8");

//数据

List<Student> studentList = getStudentList();

JSONArray jsonArray = JSONArray.fromObject(studentList);

String result = jsonArray.toString();

//前端传过来的回调函数名称

String callback = request.getParameter("theFunction");

//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了

result = callback + "(" + result + ")";

response.getWriter().write(result);

}

效果图:

最后看看jsonp是否支持POST方式:ajax请求指定POST方式

可以看到,jsonp方式不支持POST方式跨域请求,就算指定成POST方式,会自动转为GET方式;而后端如果设置成POST方式了,那就请求不了了。

jsonp的实现方式其实就是<script>脚本请求地址的方式一样,只是ajax的jsonp对其做了封装,所以可想而知,jsonp是不支持POST方式的。

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8" language="java" %>

<html>

<head>

<title>跨域测试</title>

<script src="js/jquery-1.7.2.js"></script>

<script>

$(document).ready(function () {

$("#btn").click(function () {

$.ajax({

url: "http://localhost:9090/student",

type: "POST", //post请求方式

dataType: "jsonp",

jsonp: "callback",

success: function (data) {

var result = JSON.stringify(data);

$("#text").val(result);

}

});

});

});

</script>

</head>

<body>

<input id="btn" type="button" value="跨域获取数据" />

<textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>

</html>

效果图:

再补充一点,回到第一条:CORS头缺少“Access-Control-Allow-Origin” 。

有时候你会发现其它都没问题,出现这个错误:这个错误代表服务端拒绝跨域访问。如果出现这个错误,就需要在服务端设置允许跨域请求。

response.setHeader("Access-Control-Allow-Origin", "*"); 设置允许任何域名跨域访问

设置可以跨域访问:第6行代码或第8行代码,设置其中一个即可。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=UTF-8");

// * 表示允许任何域名跨域访问

response.setHeader("Access-Control-Allow-Origin", "*");

// 指定特定域名可以访问

response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/");

//数据

List<Student> studentList = getStudentList();

JSONArray jsonArray = JSONArray.fromObject(studentList);

String result = jsonArray.toString();

//前端传过来的回调函数名称

String callback = request.getParameter("callback");

//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了

result = callback + "(" + result + ")";

response.getWriter().write(result);

}

总结

jQuery ajax方式以jsonp类型发起跨域请求,其原理跟<script>脚本请求一样,因此使用jsonp时也只能使用GET方式发起跨域请求。跨域请求需要服务端配合,设置callback,才能完成跨域请求。

好了,

哗驼汽车网还为您提供以下相关内容希望对您有帮助:

使用JavaScript 实现各种跨域的方法

②如今最优方案:使用JSON格式来传输数据,使用JSONP来跨域。③JSON:一种数据交换格式。基于纯文本、被原生JS支持。格式:两种数据类型描述符:大括号{ }、方括号[]。分隔符逗号、映射符冒号、定义符双引好。④JSONP:一...

js实现跨域的几种方法汇总(图片ping、JSONP和CORS)_javascript技巧

图片ping图片可以从任何URL中加载,所以将img的src设置成其他域的URL,即可以实现简单的跨域,可以使用onload和onerror事件来确定是否接受到了响应。这里新建了一个img对象,给出的url是博客地址,这里是个error事件,所以弹出err...

Javascript跨域请求的4种解决方式

如果所请求的域名跟这个域名不致,这种情况就是跨域,由于跨域存在漏洞,所以一般来说正常的跨域请求方式是请求不到的。解决方式:一、window.name 1、服务器返回 复制代码 代码如下:window.name='{"id":"3","name":"le...

使用jquery的jsonp如何发起跨域请求及其原理详解

4、再来看jquery的jsonp方式跨域请求:服务端代码不变,js代码如下:最简单的方式,只需配置一个dataType:'jsonp' ,就可以发起一个跨域请求。jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,...

javascript 跨域调用js文件问题...

1.基于iframe实现跨域 基于iframe实现的跨域要求两个域具有aa.xx.com,bb.xx.com这种特点,也就是两个页面必须属于一个基础域(例如都是xxx.com,或是xxx.com.cn),使用同一协议(例如都是 http)和同一端口(例如都是...

如何解决跨域请求的问题

跨域请求的方法JSONPJSONP 称为带有填充的JavaScript对象表示,是一种通过利用HTML页面中的脚本标记可以来加载来自不同来源的代码来执实现跨域请求的方法。JSONP依赖于标签可以来自不同来源的事实。当浏览器解析标记时,它将获...

javascript如何来实现跨域发请求??

javascript 跨域请求的两种方法 还在为javascript跨域访问头疼么?以下两种解决方案或许可以帮你解忧: 1. 使用跳转请求页 使用跳转页不做详细介绍了,原理比较简单,因为服务器端脚本不存在跨域访问,所以在当前域名下新增一个...

JavaScript跨域总结与解决办法 什么是跨域

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。 特别注意两点: 第一,如果是协议和端口造成的跨域问题“前台”是无能为力的, 第二:在跨域问题上,域仅仅是通...

js 简单使用postMessage iframe跨域通信

postMessage是html5引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口,跨域消息传递.多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案.要发送到其他窗口的...

前端跨域的几种解决方式总结(推荐)

搞大前端的,肯定都会遇到跨域问题的,虽然网上这方面的资料也很多,但我还是喜欢自己写一遍,自己理解过、总结过的东西才记得最深刻。同源策略JavaScript 的同源策略,是由Netscape提出的一个著名的安全策略,为了阻止A站的JS去...

Top