1. 先说一下跨域的概念:
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。
跨域请求概念
2. 简述两者的区别
JSONJSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。
JSONP
3.什么是JSON?
JSON是一种基于文本的数据交换方式,或者叫做数据描述格式。
JSON的优点:
- 基于纯文本,跨平台传递极其简单;
- Javascript原生支持,后台语言几乎全部支持;
- 轻量级数据格式,占用字符数量极少,特别适合互联网传递;
- 可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;
- 容易编写和解析,(前提是你要知道数据结构);
JSON的格式(规则)
JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。
- JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符。
- 大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。
- 上述两种集合中若有多个子项,则通过英文逗号,进行分隔。
- 键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号”",以便于不同语言的解析。
- JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。
使用json格式的客户端代码:
$(function () {
var user = {
"username": "HelloWorld"
};
$.ajax({
url: "http://localhost:8080/Chengxuyuan/UserInfo",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json", //json不支持跨域请求,只能使用jsonp
data: {
user: JSON.stringify(user)
},
success: function (data) {
$("#user_name")[0].innerHTML = data.user_name;
$("#user_teleNum")[0].innerHTML = data.user_teleNum;
$("#user_ID")[0].innerHTML = data.user_ID;
},
error: function () {
alert("请求超时错误!");
}
})
});
.....然而,简单地使用json并不能支持跨域资源请求,为了解决这个问题,需要采用jsonp数据交互协议。众所周知,js文件的调用不受跨域与否的限制,因此如果想通过纯web端跨域访问数据,只能在远程服务器上设法将json数据封装进js格式的文件中,供客户端调用和进一步处理,这就是jsonp协议的原理。该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
简单的说,就是json不支持跨域,而js可以跨域,因此在服务器端用客户端提供的js函数名将json数据封装起来,再将函数提供给客户端调用,从而获得json数据。
开发过程中,如果出现类似 “Origin ****** is not allowed by Access-Control-Allow-Origin.” 的错误,则可能是由于json数据不支持跨域导致的,应考虑使用jsonp协议。
如果出现类似 ”SyntaxError: Unexpected token ':'. Parse error.“ 的错误,则可能是由于返回的json数据没有用”callback“传递的函数名封装导致的。
jsonp客户端代码:
$(function () {
var user = {
"username": "HelloWorld"
};
$.ajax({
url: "http://localhost:8080/Chengxuyuan/UserInfo",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "jsonp", //json不支持跨域请求,只能使用jsonp
data: {
user: JSON.stringify(user)
},
jsonp: "callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名,默认为callback
jsonpCallback: "userHandler", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function (data) {
$("#user_name")[0].innerHTML = data.user_name;
$("#user_teleNum")[0].innerHTML = data.user_teleNum;
$("#user_ID")[0].innerHTML = data.user_ID;
},
error: function () {
alert("请求超时错误!");
}
})
});
服务器端代码:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json; charset=utf-8");
String username = new String(request.getParameter("user").getBytes("ISO-8859-1"),"utf-8");
String callback = new String(request.getParameter("callback").getBytes("ISO-8859-1"),"utf-8");
System.out.println("接收到的数据:" + username);
System.out.println("callback的值:" + callback);
JSONObject user = JSONObject.fromObject(username);
System.out.println("接收到的用户名:" + user.get("username"));
JSONObject userinfo = new JSONObject();
userinfo.put("user_name", "程序员");
userinfo.put("user_teleNum", "18810011111");
userinfo.put("user_ID", "123456789098765432");
PrintWriter out = response.getWriter();
String backInfo = callback + "(" + userinfo.toString() + ")"; //将json数据封装在callback函数中提供给客户端
out.print(backInfo);
out.close();
}
尽管客户端没有实现userHandler函数,但也能成功运行,原因就是jquery在处理jsonp类型的ajax时,自动帮你生成回调函数并把数据取出来供success属性方法来调用
网友评论