JsonP的优化
标签(空格分隔): 淘淘商城
一、前端优化
上篇文章,我们讲解了Jsonp的原理以及如何解决前端的跨域调用的问题,当然Jquery早已为我们实现了采用json原理的调用方式:代码如下:
<script>
alert($);
$(function(){$.ajax({
url :"http://manager.taotao.com/rest/page/jsonp",
dataType:"jsonp",
type : "GET",
success : function(data){
alert(data.abc);
}
})
});
/*function fun(data){
alert(data.abc);
}*/
</script>
Jquery会默认为我们声明好一个临时的回调方法,并且自动在ajax请求中在后面参数中追加这个方法名到后台服务端,后台服务端只需要取到变量名:callback所对应的参数值进行封装成js方法就行了。
上述代码中的请求为:
http://manager.taotao.com/rest/page/jsonp?callback=jQuery111107980531553944776_1512709449553^&_=1512709449554
前端就无需做其他操作。
二、服务端优化
作为一个服务,我们需要支持前端各种请求方式,所以一般代码都得这么写:
如果每次都需要判断callback参数是否有值然后进行封装的话,代码有点硬编码了。可以使用Spring提供的Converter插件的模式。
1、写一个Converter:
public class CallbackMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
// 做jsonp的支持的标识,在请求参数中加该参数
private String callbackName;
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
// 从threadLocal中获取当前的Request对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String callbackParam = request.getParameter(callbackName);
if(StringUtils.isEmpty(callbackParam)){
// 没有找到callback参数,直接返回json数据
super.writeInternal(object, outputMessage);
}else{
JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
try {
String result =callbackParam+"("+super.getObjectMapper().writeValueAsString(object)+");";
IOUtils.write(result, outputMessage.getBody(),encoding.getJavaName());
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
}
}
public String getCallbackName() {
return callbackName;
}
public void setCallbackName(String callbackName) {
this.callbackName = callbackName;
}
}
2、配置Converter:
<mvc:annotation-driven>
<mvc:message-converters register-defaults = "true">
<!-- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg index="0" value="UTF-8"></constructor-arg>
</bean> -->
<bean class="com.taotao.common.spring.exetend.converter.json.CallbackMappingJackson2HttpMessageConverter">
<property name="callbackName" value="callback" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
3、服务端代码(后台实现无线再关心是否需要提供Jsonp的支持):
@RequestMapping(value = "query/{token}", method = RequestMethod.GET)
public ResponseEntity<User> queryUserByToken(@PathVariable("token") String token) {
try {
User user = userService.queryUserByToken(token);
if (null == user) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
return ResponseEntity.ok(user);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}