1 .什么是跨域问题:
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:
首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:
URL | 说明 | 是否允许通信 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js | 同一域名下 | 允许 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js | 同一域名下不同文件夹 | 允许 |
http://www.a.com:8000/a.js http://www.a.com/b.js | 同一域名,不同端口 | 不允许 |
http://www.a.com/a.js https://www.a.com/b.js | 同一域名,不同协议 | 不允许 |
http://www.a.com/a.js http://70.32.92.74/b.js | 域名和域名对应ip | 不允许 |
http://www.a.com/a.js http://script.a.com/b.js | 主域相同,子域不同 | 不允许 |
http://www.a.com/a.js http://a.com/b.js | 同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
http://www.cnblogs.com/a.js http://www.a.com/b.js | 不同域名 | 不允许 |
-
特别注意两点:
- 第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
- 第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。 “URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls》
2. 解决方法首先来看看在页面中如何使用jQuery的ajax解决跨域问题的简单版:
$(document).ready(function(){ var url='http://localhost:8080/WorkGroupManagment/open/getGroupById" +"?id=1&callback=?'; $.ajax({ url:url, dataType:'jsonp', processData: false, type:'get', success:function(data){ alert(data.name); }, error:function(XMLHttpRequest, textStatus, errorThrown) { alert(XMLHttpRequest.status); alert(XMLHttpRequest.readyState); alert(textStatus); }}); }); 复制代码 这样写是完全没有问题的,起先error的处理函数中仅仅是alert(“error”),为了进一步弄清楚是什么原因造成了错误,故将处理函数变 为上面的实现方式。最后一行alert使用为;parsererror。百思不得其解,继续google,最终还是在万能的stackoverflow找 到了答案,链接在这里。原因是jsonp的格式与json格式有着细微的差别,所以在server端的代码上稍稍有所不同。 比较一下json与jsonp格式的区别: json格式: { "message":"获取成功", "state":"1", "result":{"name":"工作组1","id":1,"description":"11"} } jsonp格式: callback({ "message":"获取成功", "state":"1", "result":{"name":"工作组1","id":1,"description":"11"} }) 看出来区别了吧,在url中callback传到后台的参数是神马callback就是神马,jsonp比json外面有多了一层,callback()。这样就知道怎么处理它了。于是修改后台代码。 后台java代码最终如下: 复制代码 @RequestMapping(value = "/getGroupById") public String getGroupById(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response) throws IOException { String callback = request.getParameter("callback"); ReturnObject result = null; Group group = null; try { group = groupService.getGroupById(id); result = new ReturnObject(group, "获取成功", Constants.RESULT_SUCCESS); } catch (BusinessException e) { e.printStackTrace(); result = new ReturnObject(group, "获取失败", Constants.RESULT_FAILED); } String json = JsonConverter.bean2Json(result); response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.print(callback + "(" + json + ")"); return null; } 复制代码 注意这里需要先将查询结果转换我json格式,然后用参数callback在json外面再套一层,就变成了jsonp。指定数据类型为jsonp的ajax就可以做进一步处理了。 虽然这样解决了跨域问题,还是回顾下造成parsererror的原因。原因在于盲目的把json格式的数据当做jsonp格式的数据让ajax处理,造成了这个错误,此时server端代码是这样的: 复制代码 @RequestMapping(value = "/getGroupById") @ResponseBody public ReturnObject getGroupById(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response){ String callback = request.getParameter("callback"); ReturnObject result = null; Group group = null; try { group = groupService.getGroupById(id); result = new ReturnObject(group, "获取成功", Constants.RESULT_SUCCESS); } catch (BusinessException e) { e.printStackTrace(); result = new ReturnObject(group, "获取失败", Constants.RESULT_FAILED); } return result; } 复制代码 至此解决ajax跨域问题的第一种方式就告一段落。 追加一种解决方式 追求永无止境,在google的过程中,无意中发现了一个专门用来解决跨域问题的jQuery插件-jquery-jsonp。 有第一种方式的基础,使用jsonp插件也就比较简单了,server端代码无需任何改动。 来看一下如何使用jquery-jsonp插件解决跨域问题吧。 复制代码 var url="http://localhost:8080/WorkGroupManagment/open/getGroupById" +"?id=1&callback=?"; $.jsonp({ "url": url, "success": function(data) { $("#current-group").text("当前工作组:"+data.result.name); }, "error": function(d,msg) { alert("Could not find user "+msg); } }); 参考文章列表: http://zhidao.baidu.com/link?url=sJ7NKZ978yogRqRq0UbWHtzWvhEcoJGGef-xBLioieOHR70zpAG4CbZ18yCRyNVAFXe http://www.360doc.com/content/12/1009/15/6161903_240444143.shtml