项目开发中,某个可独立、也可集成的子业务模块须要向外开放相关API接口,先说下项目本身使用了jersery来实现RESTful webservice以名词形式公布API。有意思的是在实际的操作中同事却通过Ajax跨域请求的方式去调用该API,先不说成功与否,这样的方式本就是“滑稽"的。和他一起探讨了此种做法的不合理性,之后选择jersey client的方式进行远程调用。只是他在跨域请求中遇到了问题,自己闲暇时间予以解决,这才是此篇文章的由来。
jQuery对跨域请求有两种解决方式各自是jQuery的jquery.ajax jsonp格式和jquery.getScript方式,并且这两种方式都仅仅支持get方法。
这里主要谈的是jsonp跨域的实现。
json格式我们倒是经常使用,可是jsonp就不那么经常使用了,所以首先须要对jsonp要有一个了解。
JSONP解释
在解释JSONP之前,我们须要了解下”同源策略“这个概念,这对理解跨域有帮助。基于安全的原因,浏览器是存在同源策略机制的,同源策略阻止从一个源载入的文档或脚本获取或设置还有一个源载入额文档的属性。有点绕,说的简单点就是浏览器限制脚本仅仅能和同协议、同域名、同port的脚本进行交互。
JSONP就是为了解决这一问题的,JSONP是英文JSON with Padding的缩写,是一个非官方的协议。他同意服务端生成script tags返回值client,通过javascript callback的形式来实现网站訪问。JSONP是一种script tag的注入,将server返回的response加入到页面是实现特定功能。
简而言之,JSONP本身不是复杂的东西,就是通过scirpt标签对javascript文档的动态解析绕过了浏览器的同源策略。
JSONP原理及实现
接下来,来实际模拟一个跨域请求的解决方式。后端为Spring MVC架构的,前端则通过Ajax进行跨域訪问。
1、首先client须要注冊一个callback(服务端通过该callback(jsonp)能够得到js函数名(jsonpCallback))。然后以JavaScript语
法的方式,生成一个function
2、接下来,将JSON数据直接以入參的方式,放置到function中,这样就生成了一段js语法文档,返回给client。
3、最后client浏览器动态的解析script标签,并运行返回的JavaScript语法文档片段,此时数据作为參数传入到了预先定义好的
回调函数里(动态运行回调函数)。
这样的动态解析js文档和eval函数是类似的。
接下来就是怎样实现了,client代码。
$.ajax({
type: "get",
async: false,
url: "http://localhost:8080/buy/get",
dataType: "jsonp",
jsonp: "callbackparam", //服务端用于接收callback调用的function名的參数
jsonpCallback: "success_jsonpCallback", //callback的function名称,服务端会把名称和data一起传递回来
success: function(json) {
alert(json[0].name);
}
});
注解:jsonp会创建一个查询字符串參数callback=?
,这个參数会载入请求的URL后面,服务端应当在JSON数据前加上回调函数
名,以便完毕一个JSONP请求。也就是说server端须要对返回的数据做处理,格式为例如以下形式:
jsonpCallback([{ name:"jhon"}])
接下来看server端针对上述代码的处理:
@RequestMapping("/get")
public void get(HttpServletRequest req,HttpServletResponse res) {
res.setContentType("text/plain");
String callbackFunName =req.getParameter("callbackparam");//得到js函数名称
try {
res.getWriter().write(callbackFunName + "([ { name:\"John\"}])"); //返回jsonp数据
} catch (IOException e) {
e.printStackTrace();
}
}
前端Ajax跨域请求触发之后,可以有效的得到JSON数据,情况例如以下:
至此,Ajax跨域请求也已经攻克了,只是还是有两点地方须要注意:
1、没有关于JSONP调用的错误处理,动态插入的脚本有效,则运行调用,无效就默默失败(无不论什么提示)。
2、JSONP被不信任的服务使用会有一定的安全隐患,不信任的服务提供的脚本可能是恶意的。