先来创建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文件:
//添加<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/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方法。
好文章!666,学习了