首先,说下什么是跨域?有以下两种:
1.域名不同
2.域名相同,端口不同
接着说下什么是jsonp?
jsonp不是新技术,它只是一种解决方案,使用js的特性绕过跨域请求,利用的特性便是js可以跨域加载js文件!!举个非常常见的例子,我们在html头部一般都会引入很多js,甚至我们直接引用在线的js,比如我们引用官方网站的jQuery路径加载进来也是可以的。JQuery的官方域名与我们的工程所在的域名肯定是不一样的,但是不影响使用,这就是我们所说的js可以跨域请求js文件!
跨域的特点是什么呢?我们可以在"Network"一栏看到请求的token信息,在Headers当中发现服务端已经正常响应了,如下图所示。
我们再看下Response一栏,发现没有任何信息,其实流程是这样的,我们使用ajax调用服务端的接口,服务端不管你请求是否是同一个域下,只管响应,于是 我们可以看到服务端响应的头信息,但是当数据经过浏览器时,浏览器判断出js访问的数据来自不同的域,于是便拒绝将数据返给页面。我们拿不到Response信息,也就无法展示内容了。
那么jsonp是怎样解决跨域问题的呢?流程图如下,图的上半部分展示的是传统跨域请求,这种请求我们是获取不到Response数据的,下半部分是介绍jsonp跨域获取数据的方案的。我们现在要跨域获取信息的js当中添加一个函数,该函数有返回值参数data,发起跨域请求的一端引入服务端定义好的一个js文件,请求的参数中是带callback回调函数的,并且callback=mycall中的"mycall"一定是与我们添加的那个函数的名称一致的,服务端接收到请求,就进行响应,并且判断参数中是否有callback参数,如果有callback参数的话,就对要返回的数据进行处理,加工成一段js代码(很简单,就是把一个json串包装成一个js函数,如下图mycall({id:1,name:z});)然后响应,js本来就是要请求访问服务端的一个js文件,现在返回的也是js代码,于是浏览器将不再进行拦截,由于返回的是js代码,而且js语句有个特点就是,一旦响应到浏览器端便立即执行,我们已经添加了该函数,于是便调用我们添加的那个函数,我们只需把数据做下处理并进行展示就可以了!!!
下面我们便来实现jsonp请求,上图所介绍的方法是比较复杂的,如果我们用jquery的话,如下图所示。
这样就会帮我们省很多事,我们只需要在ajax请求时指定dataType为jsonp,如下图所示。jquery便会帮我们自动创建一个函数。
我们刷新下淘淘商城首页,可以看到请求中自动为我们加上了回调函数,而且随机为我们添加了函数名为"jQuery3257776"的函数。
现在我们要做的便是修改服务端的代码,以便能够配合客户端完成整个请求过程,修改的方法如下图所示,我们将原来返回一个Map类型改为返回String类型,而且添加了callback参数,判断下是否有callback参数,如果有就说明是jsonp请求,我们要将result转换成json串并且包装成一个js函数返回。如果不是jsonp请求,那就直接将result转换成json串返回。
@RequestMapping(value = "/user/token/{token}",method = RequestMethod.GET) @ResponseBody public String getUserByToken(@PathVariable String token,String callback){ TaotaoResult result = userService.getUserByToken(token); if(StringUtils.isNotBlank(callback)){ return callback+"("+JSON.toJSONString(result)+");"; } return JSON.toJSONString(result); }好了,代码修改完了,我们现在重启taotao-sso-web工程,重启后,我们刷新淘淘商城首页,发现页面正常显示用户的姓名了!! 注意,如果你这时还显示不出来,是因为token已经过期了,你需要重新登录一下,这样就可以看到了。
上面介绍的是最通用的一种方法,还有一种方法也可以解决,只是要求Spring的版本是4.1以上,还好,我们的淘淘商城用的版本是4.2,因此是没问题的,要修改的还是UserController,如下图所示。
修改后代码如下,由于result和mappingJacksonValue 属于不同类型,因此返回值类型修改成了Object。
@RequestMapping(value = "/user/token/{token}",method = RequestMethod.GET) @ResponseBody public Object getUserByToken(@PathVariable String token,String callback){ TaotaoResult result = userService.getUserByToken(token); if(StringUtils.isNotBlank(callback)){ MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result); mappingJacksonValue.setJsonpFunction(callback); return mappingJacksonValue; } return result; }我们重启下taotao-sso-web工程,然后重新刷新下淘淘商城首页,如下图所示,发现也可以正常显示用户名!
原文链接:https://www.f2er.com/json/288887.html