淘淘商城第104讲——jsonp的原理及两种实现方式

什么是jsonp?

我们知道了什么是跨域,而且也晓得解决js的跨域问题可以使用jsonp,那么jsonp到底是个啥呢?

jsonp不是新技术,它只是一种跨域的解决方案,使用js的特性绕过跨域请求,利用的特性便是js可以跨域加载js文件。 举个非常常见的例子,我们在html头部一般都会引入很多js,甚至我们直接引用在线的js,比如我们引用官方网站的jQuery路径从而加载进来jQuery的库文件。jQuery的官方域名与我们的工程所在的域名肯定是不一样的,但是并不影响使用,这就是我们所说的js可以跨域请求js文件!

jsonp的原理

jsonp是怎样解决跨域问题的呢?如下图所示,图的上半部分展示的是传统跨域请求,这种请求我们是获取不到服务端的json数据的,下半部分是介绍jsonp跨域获取数据的方案。我们在要跨域获取信息的js当中添加一个函数,该函数包含有返回值参数data,发起跨域请求的一端要想引入服务端定义好的一个js文件,请求的参数中必须要带一个callback回调函数,并且参数callback的值(例如mycall)一定要与我们添加的那个函数的名称一致,这样服务端接收到请求后,就会进行响应。
在这里插入图片描述
那么如何进行响应呢?首先判断参数中是否有callback参数,如果有callback参数的话,那么就对要返回的json数据进行处理,即将其伪装成一段js代码(很简单,就是把一个json串包裹成一个js函数,如上图中的mycall({id:1});)响应,jsonp本来就是要请求访问服务端的一个js文件的,现在返回的就是js代码,于是浏览器将不再进行拦截,而且js语句有个特点,就是一旦响应到浏览器便会立即执行,如此一来,我们刚刚添加的mycall这个函数便就会被调用,继而获取到json数据并进行业务处理。

使用jsonp解决js跨域问题的两种实现方式

第一种实现方式

其实,如果我们使用jQuery的话,那么使用jsonp解决跨域问题就会变得容易得多,我们只需要在发送ajax跨域请求时指定dataType属性的值为jsonp即可,如下图所示,这样jQuery便会帮我们自动创建一个函数。
在这里插入图片描述
然后我们刷新下淘淘商城首页,可以看到在请求后面自动为我们加上了回调函数,而且是随机为我们添加了一个名为jQuery4324401的函数。
在这里插入图片描述
接着我们要做的便是修改服务端的代码,以便能够配合客户端完成整个请求过程,修改的方法如下图所示,我们将原来返回的结果类型由TaotaoResult类型改为String类型,而且再添加一个callback参数。在方法内部我们所要做到事情就是判断一下是否有callback参数,若有则说明是jsonp请求,我们还得将result转换成json串并且包装成一个js函数返回,若不是jsonp请求,则直接将result转换成json串并返回。
在这里插入图片描述
getUserByToken方法修改后的代码如下所示:

/**
  * url:/user/token/{token}
  * 参数:token
  * 返回值:json数据
  * 请求限定的方法:get
  */
@RequestMapping(value="/user/token/{token}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String getUserByToken(@PathVariable String token, String callback) { // 最后一个参数的名称必须是callback
	TaotaoResult result = loginService.getUserByToken(token);
	// 判断是否是jsonp请求
	if (StringUtils.isNotBlank(callback)) {
		// 如果是jsonp请求,那么需要伪装,即拼接成类似于fun({"id":1});这种玩意并返回
		String jsonpstr = callback + "(" + JsonUtils.objectToJson(result) + ")";
		return jsonpstr;
	}
	// 如果不是jsonp请求,那么还用原来的方式
	// 1. 调用服务
	// token是UUID算法生成的一个字符串,还需要通过CookieUtils这个工具类从Cookie中获取token
	return JsonUtils.objectToJson(result);
}

好了,代码修改完了,我们现在重启taotao-sso-web工程,重启成功后,刷新淘淘商城首页,发现页面正常显示用户的姓名了!!注意,如果你这时还显示不出来,可能是因为token已经过期了,你需要重新登录一下,这样就可以看到了。
在这里插入图片描述

第二种实现方式

上面介绍的是最通用的一种方式,其实还有一种方式也可以解决js跨域问题,只是要求Spring的版本是4.1以上,还好,我们淘淘商城这个项目使用的版本是4.2.4,因此这是没问题的,要修改的还是UserLoginController类的getUserByToken方法,如下图所示。
在这里插入图片描述
getUserByToken方法修改后的代码如下所示,由于result和mappingJacksonValue属于不同类型,因此返回值类型需要修改成了Object。

/**
  * url:/user/token/{token}
  * 参数:token
  * 返回值:json数据
  * 请求限定的方法:get
  */
@RequestMapping(value="/user/token/{token}", method=RequestMethod.GET)
@ResponseBody
public Object getUserByToken(@PathVariable String token, String callback) { // 最后一个参数的名称必须是callback
	TaotaoResult result = loginService.getUserByToken(token);
	// 判断是否是jsonp请求
	if (StringUtils.isNotBlank(callback)) {
		// 如果是jsonp请求,那么需要伪装,即拼接成类似于fun({"id":1});这种玩意并返回
		MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
		// 设置回调方法
		mappingJacksonValue.setJsonpFunction(callback);
		return mappingJacksonValue;
	}
	// 如果不是jsonp请求,那么还用原来的方式
	return result;
}

然后我们重启下taotao-sso-web工程,再重新刷新下淘淘商城首页,如下图所示,发现也是可以正常显示用户名的!
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李阿昀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值