最近项目中用到 json 作为系统间交互的手段,自然就伴随着众多 ajax 请求,随之而来的就是要解决 ajax 的跨域问题。本篇将讲述一个小白从遇到跨域不知道是跨域问题,到知道是跨域问题不知道如何解决,再到解决跨域问题,最后找到两种方法解决 ajax 跨域问题的全过程。
起 因是这样的,为了复用,减少重复开发,单独开发了一个用户权限管理系统,共其他系统获取认证与授权信息,暂且称之为 A 系统;调用 A 系统以 B 为例。在 B 系统 中用 ajax 调用 A 系统系统的接口 (数据格式为 json),当时特别困惑,在 A 系统中访问相应的 url 可正常回返 json 数据,但是在 B 系统中使用 ajax 请求同样的 url 则一点儿反应都没有,好像什么都没有发生一样。这样反反复复改来改去好久都没能解决,于是求救同事,提醒可能是 ajax 跨域问 题,于是就将这个问题当做跨域问题来解决了。
知道问题的确切原因,剩下的就是找到解决问题的方法了。google 了好久,再次在同事的指点下知道 jQuery 的 ajax 有 jsonp 这样的属性可以用来解决跨域的问题。
现在也知道了怎样来解决跨域问题,余下的就是实现的细节了。实现的过程中错误还是避免不了的。由于不了解 json 和两种格式的区别,也犯了错误,google 了好久才解决。
首先来看看在页面中如何使用 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 格式的区别:
- {
- "message": "获取成功",
- "state": "1",
- "result": {
- "name": "工作组1",
- "id": 1,
- "description": "11"
- }
- }
- 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 插件 -。
有第一种方式的基础,使用 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://www.bubuko.com/infodetail-1973458.html