前言
在第一次写博文的时候,写的是JSONP的基本原理,因为是第一次写可能有些不足。这一篇博文是简单的介绍在SpringMVC中JSONP的基本使用。(要是有不足,请各位指出,(~ ̄▽ ̄)~)。
1、回顾
1.1、当遇到跨域请求的时候,也就是以下错误的时候,怎么解决:
XMLHttpRequest cannot load http://www.a.com/foo. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://www.b.com’ is therefore not allowed access.
1.2、只要简单的两步就可以解决跨域问题:
1.2.1、对原有的Ajax(就是产生跨域的Ajax)的进行改造,主要是将dataType 设置为jsonp:
$.ajax({
url : "http://www.a.com/foo",
type : "GET",
dataType : "jsonp", //只要将dataType设置为jsonp即可,其他的参数设置不需要修改
success : function(data){
alert(data.name);
}
});
1.2.2、Controller中的方法的改造:
@RequestMapping(value = "foo", method = RequestMethod.GET)
@ResponseBody
public String foo(String callback) {
try {
// 构造返回的数据data
Map<String, String> data = new HashMap<String, String>();
data.put("name", "LinHenk");
// 将data对象序列化为JSON对象,此处使用的是jackson中提供的ObjectMapper将data对象序列化为JSON对象
String json = objectMapper.writeValueAsString(data);
// 判断请求是否是josnp请求
if (StringUtils.isNotBlank(callback)) {
// jsonp请求,使用字符串拼接的方式,生成一段js脚本片段
return callback + "(" + json + ");";
}
// 非jsonp请求
return json;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2、代码改善
2.1、跨域问题是解决了,但是代码看起来不怎么好,看以下代码:
return callbackName + "(" + json + ");"
以上代码,使用了字符串拼接,看起来不怎么好,而且在字符串拼接时也可能写错,可能写少了个括号什么的(PS:个人认为这样的字符串拼接,更容易让初学者理解ヾ(o◕∀◕)ノヾ)。
2.2、使用JSONPObject进行代码改善
JSONPObject该类是jackson提供的(com.fasterxml.jackson.databind.util.JSONPObject),该类使用起来也是相当的简单,请看代码:
@RequestMapping(value = "foo", method = RequestMethod.GET)
@ResponseBody
public Object foo(String callback) {
try {
// 构造返回的数据data
Map<String, String> data = new HashMap<String, String>();
data.put("name", "LinHenk");
// 判断请求是否是josnp请求
if (StringUtils.isNotBlank(callback)) {
// jsonp请求
//参数一(String类型):回调函数名,参数二(Object类型):需要返回的数据
JSONPObject jsonpObject = new JSONPObject(callback, data);
return jsonpObject;
}
// 非jsonp请求
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
说说为什么要使用JSONPObject来进行数据返回吧,个人的理解比较浅显,主要由以下两点:
1、避免了字符串拼接问题,防止拼接过程中出错。
2、当返回的数据含有中文时,不需要手动指定Content-Type:application/json;charset=UTF-8 。PS:使用字符串拼接的方式,如果返回的数据包含中文,需要使用@RequestMapping,通过produces进行指定Content-Type为application/json;charset=UTF-8(否则会出现乱码),如下代码:
@RequestMapping(produces=MediaType.APPLICATION_JSON_VALUE+";charset=UTF-8")
其实我主要想说的是,使用JSONPObject会简化我们的开发,提高开发效率。
2.3、使用MappingJacksonValue进行代码改善
MappingJacksonValue是Spring4.1及以上版本所提供的类,看下图:
MappingJacksonValue使用起来和JSONPObject一样的简单,如下代码:
@RequestMapping(value = "foo", method = RequestMethod.GET)
@ResponseBody
public Object foo(String callback) {
try {
// 构造返回的数据data
Map<String, String> data = new HashMap<String, String>();
data.put("name", "LinHenk");
// 判断请求是否是josnp请求
if (StringUtils.isNotBlank(callback)) {
// jsonp请求
MappingJacksonValue jacksonValue = new MappingJacksonValue(data);
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
// 非jsonp请求
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
再次提醒,MappingJacksonValue需要在Spring4.1及以上的版本才能使用。
3、小小的小结
使用JSONPObject和MappingJacksonValue都可以使得我们在遇到JSONP跨域请求的时候,开发相对简便,但是要使用这两个类都需要满足相应的条件:
1、使用JSONPObject,需要添加jackson的相关依赖
2、使用MappingJacksonValue,需要在Spring4.1及以上版本才能使用(并且也需要jackson的相关依赖)
本文中主要讲解的是SpringMVC中JSONP的基本使用,还有其他的基本使用方式,也希望可以留言告诉我!为什么强调基本,因为除了以上两个比较基本的解决方法(我所接触过的比较简单的方法),其实也可以通过自定义MessageConverter来实现,但是感觉对SpringMVC使用不是很了解的朋友来说,使用该种方法,相对来说会比较有难度一点。