jsonp跨域请求

先来创建web项目,包括一个jsp,内容如下:

<%
	out.write("this is content of JSP");
%>

我们可以用浏览器测试一下是否可以访问http://localhost:8080/TestJsonp/content.jsp

结果:this is content of JSP

现在要用ajax来进行访问(这里用原生的ajax,排除框架造成问题的可能):

var xmlhttp;
if (window.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
} else { //IE5 IE6
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open('GET', "http://localhost:8080/TestJsonp/content.jsp", true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
    document.getElementById('show').innerHTML = "ajax request:" + xmlhttp.responseText;
};

 

<div id="show"></div>

我们将这段代码放在同源环境下运行(http://localhost:8080),结果:ajax request:this is content of JSP

但我们这回不在同源环境下运行(上面javascript代码在http://localhost:63342运行),结果:Origin http://localhost:63342 is not allowed by Access-Control-Allow-Origin

上面的异常就是因为跨域访问造成的。浏览器访问地址的域名、协议、端口必须是相同的,否则就是跨域访问。浏览器出于安全的考虑,不允许javascript进行跨域访问,所以会给出警告。

那我们如何解决这个问题呢?哈哈,我们的主人公jsonp就要出场了。

1.json和jsonp

json(javascript object notation)大家都了解吧,是一种轻量级的数据交换格式,那jsonp是什么呢?

jsonp是json with padding的简称。它是一个非官方的协议,它允许在服务器端集成script tags返回至客户端,通过javascript callback的形式实现跨域访问。下面我们来看一个小例子。

2.跨域的简单原理

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="js/test.js"></script>
</head>
<body>
</body>
</html>

test.js的代码:

alert("success!");

这个结果大家都应该知道,跳出了“success!”这样的提示框。那我们换一种访问方式:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="http://localhost:8080/TestJsonp/test.js"></script>
</head>
<body>
</body>
</html>

我们访问http://localhost:8080上的test.js文件,同样跳出了”success!”的提示框。到这里大家应该明白了跨域访问的原理了:

<script>标签的src属性是可以进行跨域访问的,所以它可以获取任何服务器上的脚本并执行。

3.jsonp的实现形式

下面就来说说怎样用javascript callback来实现跨域访问。

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript">
        function callback(data) {
            alert(data.message);
        }
    </script>
    <script type="text/javascript" src="http://localhost:8080/TestJsonp/test.js"></script>
</head>
<body>
</body>
</html>

function的定义要在上面,否则不能识别callback方法。

test.js的代码:

callback({message:"success!"});

成功弹出“success!”。其实这就是jsonp的简单实现模式:

创建一个回调函数,然后在远程服务上调用这个函数并且将json数据形式作为参数传递,完成回调。

其实,我们也可以动态的来加载javascript文件:

//添加&lt;script&gt;标签的方法
function addScriptTag(src){
    var script = document.createElement('script');
    script.setAttribute("type","text/javascript");
    script.src = src;
    document.body.appendChild(script);
}
window.onload = function(){
    addScriptTag("http://localhost:8080/TestJsonp/test.js");
}

但服务器不知道我们回调函数的名称,所以我们都将名称传到服务器,然后服务器用java生成javascript代码传回客户端:

function testfunc(data) {
    alert(data.message);
}
//添加<script>标签的方法
function addScriptTag(src){
    var script = document.createElement('script');
    script.setAttribute("type","text/javascript");
    script.src = src;
    document.body.appendChild(script);
}
window.onload = function(){
    addScriptTag("http://localhost:8080/TestJsonp/content.jsp?callback=testfunc");
}

content.jsp的代码:

<%
    String callback = request.getParameter("callback");
    out.write(callback + "({'message':'success!'})");
%>

4.jquery下jsonp的实现

jquery ajax提供了jsonp的实现:

$(document).ready(function() {
    $.ajax({
        url : "http://localhost:8080/TestJsonp/content.jsp",
        type : "POST",
        async : true,
        dataType : "jsonp",
        jsonp : "callback",
        success : function(data) {
            alert(data.message);
        }
    });
});

jsonp设置为callback,就相当于在url后面添加的“callback=?”,jquery会自动生成回调函数名称来替代“?”,回调函数便是success方法。

1 Reply to “jsonp跨域请求”

发表评论