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

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

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

如果要在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,才能完成跨域请求。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

jQuery jsonp跨域请求的更多相关文章

  1. jQuery jsonp跨域请求详解

    跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的. 浏览器的同源策略限制从一个源加载的文档或脚本与来自另一个源的资源进行交互. 如果协议,端口和主机对于两个页面是相同的,则两个页面具 ...

  2. jQuery ajax的jsonp跨域请求

    一直在听“跨域跨域”,但是什么是跨域呢?今天做了一些了解.(利用jQuery的jsonp) jQuery使用JSONP跨域 JSONP跨域是利用script脚本允许引用不同域下的js实现的,将回调方法 ...

  3. .net学习之母版页执行顺序、jsonp跨域请求原理、IsPostBack原理、服务器端控件按钮Button点击时的过程、缓存、IHttpModule 过滤器

    1.WebForm使用母版页后执行的顺序是先执行子页面中的Page_Load,再执行母版页中的Page_Load,请求是先生成母版页的控件树,然后将子页面生成的控件树填充到母版页中,最后输出 2.We ...

  4. JSONP跨域请求数据报错 “Unexpected token :”的解决办法

    原文  http://www.cnphp6.com/archives/65409 Jquery使用ajax方法实现jsonp跨域请求数据的时候报错 “Uncaught SyntaxError: Une ...

  5. Django学习---jsonp跨域请求

    jsonp跨域请求 我们通过ajax进行跨域请求的时候,请求发送过去,但是在接受返回数据的时候浏览器会进行拦截. 这是由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源 ...

  6. NodeJ node.js Jquery Ajax 跨域请求

    Jquery + Ajax 跨域请求 说白了就是前台请求ajax数据(JSON)但是请求的数据不在本地的绝对路径下,接口数据 是没有这个安全性的我对外公开的接口数据,只要你找到接口你就可以使用里面的数 ...

  7. jsonp跨域请求响应结果处理函数(python)

    接口测试跨域请求接口用的jsonp,需要将回调函数里的json字符串提取出来. jsonp跨域请求的响应结果格式: callback_functionname(json字符串). #coding:ut ...

  8. 原生JavaScript封装的jsonp跨域请求

    原生JavaScript封装的jsonp跨域请求 <!DOCTYPE html> <html lang="en"> <head> <met ...

  9. jQuery的ajax jsonp跨域请求

    了解:ajax.json.jsonp.“跨域”的关系 要弄清楚以上ajax.json.jsonp概念的关系,我觉得弄清楚ajax是“干什么的”,“怎么实现的”,“有什么问题”,“如果解决存在的问题”等 ...

随机推荐

  1. AWS 之 S3篇<.NET(c#)批量上传文件>

    第一次知道AWS然后网上就研究了一番,如果也是第一次知道这个的话,或者对这个只知道是干什么,并没有写个相关的程序的话,可以看看这个网址http://docs.aws.amazon.com/zh_cn/ ...

  2. C# 实现对接电信交费易自动缴费

    他有这样一个JS PassGuardCtrl.js 部分代码    1 defaults:{  2             obj:null,  3             random:null,/ ...

  3. UVa 11542 (高斯消元 异或方程组) Square

    书上分析的太清楚,我都懒得写题解了.=_=|| #include <cstdio> #include <cstring> #include <cmath> #inc ...

  4. Oracle中使用escape关键字实现like匹配特殊字符,以及&字符的转义

    转:http://blog.chinaunix.net/uid-26896647-id-3433968.html 问题描述:如果在一个表中的一个字段上存在'&',  '_',  '%'这样的特 ...

  5. I.MX6 Ethernet UI patch failed

    /*********************************************************************** * I.MX6 Ethernet UI patch f ...

  6. dialog组件

    /** * @description Mask 弹层 * @function * @name Mask * @param {Object} options 配置项 */ var passport = ...

  7. uestc 1720无平方因子数

    求素数 然后容斥原理// n之内有平方因子的数的个数sum =n/(2^2) + n/(3^2)+……+n/(k^2) - n/(2^2 * 3^2)-……+……. // #pragma commen ...

  8. Android精美的日历控件

    网上看到的精美日历控件,谨以此文记录一下,用到的时候再来翻翻 源码地址 : http://download.csdn.net/detail/abc13939746593/7265459

  9. TCP/IP详解学习笔记(3)-IP协议,ARP协议,RARP协议

    把这三个协议放到一起学习是因为这三个协议处于同一层,ARP协议用来找到目标主机的Ethernet网卡Mac地址,IP则承载要发送的消息.数据链路层可以从ARP得到数据的传送信息,而从IP得到要传输的数 ...

  10. codeforces 691E Xor-sequences 矩阵快速幂

    思路:刚开始 n个元素,a[i][j]代表以i开头,j结尾的二元组符合条件的有多少 这是等于长度为2的数量 长度为3的数量为a*a,所以长度为n的数量是a^(k-1) 然后就是矩阵快速幂,然而我并不能 ...