天天看点

jsonp解决js跨域请求

跨域产生的原因

在一个项目中,使用js的ajax请求,请求另外一个系统的数据时(协议不同(http、https)、域名不同、域名相同但端口号不同),能够请求到数据,但是因为这是跨域请求,浏览器不允许js拿到数据,这就是ajax跨域请求

解决方案

可以jsonp解决js的跨域请求,Jsonp不是新技术,是跨域的解决方案。因为在系统中可以通过跨域来加载js文件,所以可以使用js的特性绕过跨域请求。

jsonp的原理
jsonp解决js跨域请求

一个系统的访问url是localhost:8082,它需要同ajax请求来访问localhost:8088下的json数据,此时因为两个系统的端口不同,所以产生了ajax跨域请求,浏览器不允许js取得数据,此时,可以使用jsonp来结局跨域请求,定义一个js方法mycall(data){},data就是返回的从另一个服务返回的json数据,可以在这个方法中拿到json数据进行业务处理,而在ajax请求中,只需要多携带一个参数callback=mycall,在服务器接收到这个ajax请求之后,判断参数中是否有callback,如果有,就将json数据封装成一个js语句,返回到浏览器,返回的是"mycall({id:xx,name:xx});" 里面的数据就是json字符串,但js接收到这个响应后,就会调用mycall方法,就实现可跨域请求数据

jsonp的实现
  1. 客户端:

    可以直接使用jquery封装jsonp,只需要在ajax请求中加上dataType : “jsonp”, 其余的按照普通ajax处理方式,jquery内部写了一个方法callback(data),而且会自动在这个请求后面加上参数callback=mycall,参数名就是callback,但返回响应后,会自动调用mycall方法,将数据注入ajax请求的success : function(data){}中的data

  2. 服务端:
@Controller
public class TokenController {

	@Autowired
	private TokenService tokenService;
	
	/**
	 * 根据token,从redis中取出用户信息
	 * 如果是ajax跨域请求,则需要jsonp请求,需要传递一个callback参数,并且需要返回一个String类型的js语句
	 * 如果返回String的话,返回的的response默认是Content-Type默认是text/html,
	 * 这里需要用produces = MediaType.APPLICATION_JSON_UTF8_VALUE指明返回json类型的数据
	 * @param token
	 * @param callback
	 * @return
	 */
	/*@RequestMapping(value = "/user/token/{token}", 
			produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ResponseBody
	public String getUserByTokenFromRedis(@PathVariable String token, String callback){
		Result result = tokenService.getUserByTokenFromRedis(token);
		
		//响应结果之前,判断是否为jsonp请求,是的话把结果封装成js语句返回
		if(StringUtils.isNotBlank(callback)){
			return callback + "(" + JsonUtils.objectToJson(result ) + ");";
		}
		return JsonUtils.objectToJson(result );
	}*/
	
	/**
	 * 这个方法的写法和上述的效果是一样的,上面的是spring4.1以前的原生的写法,这个是4.1以后的封装了之后的写法
	 * @param token
	 * @param callback
	 * @return
	 */
	@RequestMapping(value = "/user/token/{token}")
	@ResponseBody
	public Object getUserByTokenFromRedis(@PathVariable String token, String callback){
		Result result = tokenService.getUserByTokenFromRedis(token);
		
		//响应结果之前,判断是否为jsonp请求,是的话把结果封装成js语句返回
		if(StringUtils.isNotBlank(callback)){
			MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result );
			mappingJacksonValue.setJsonpFunction(callback);
			return mappingJacksonValue;
		}
		return result ;
	}
}