用一个切面来统一返回前端的JSON格式
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了用一个切面来统一返回前端的JSON格式,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5154字,纯文字阅读大概需要8分钟。
内容图文
![用一个切面来统一返回前端的JSON格式](/upload/InfoBanner/zyjiaocheng/1124/3851d9bca4f64eb4ab46b46c351428a2.jpg)
新项目使用Spring MVC
+ MyBatis
架构来做,这套框架自己应该比较得心应手,这里来写一下这两天做的一些设计。
首先是静态资源的处理,关于这个之前有写文章单独讲过,这里不再重复写,不太清楚的童鞋可以移步查看
接着需要统一JSON
的返回格式,和前端工程师约定,对于字符串类型和日期类型都返回字符串,而对于普通数字类型的话都返回数字,金额类数字都返回格式化好的保留一位小数的字符串(比如”10.0”),另外数字和金额的默认值为0,而字符串的默认值为字符串空(“”),并且对于返回的格式也有规范,所有的JSON
返回必须形如:
{
"status": 1,
"data": data,
"msg": ""}
其中:
-
status
代表了该请求的成功与否,若为1表示成功,若为0表示失败,此时msg
中将包含显示给用户的错误信息 -
data
代表了返回给前端的数据,可以是一个复杂的数据结构 -
msg
前面提到了,一般放异常信息。
下面,我们首先需要对默认的Jackson
的序列化规则做出修改,这里自定义一个ObjectMapper
:
/**
* 自定义jackson解析器
* @author Zhu
* @date 2015-5-14
* @version 0.0.1
* @description
*/
@Component
public
class
CustomerObjectMapper
extends
ObjectMapper {
/**
*
*/
private
static
final
long serialVersionUID = 1L;
/**
*
*/publicCustomerObjectMapper() {
super();
// this.setSerializationInclusion(Include.NON_NULL);// 允许单引号// this.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);// 字段和值都加引号// this.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);// 数字也加引号// this.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);// this.configure(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS, true);this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
@Overridepublicvoidserialize(Object value, JsonGenerator generator,
SerializerProvider provider) throws IOException,
JsonProcessingException {
generator.writeString("");
}
});
}
}
然后将我们自定义的ObjectMapper
注入到MappingJackson2HttpMessageConverter
中去并重新配置Spring MVC
中的message converter
<beanid="mappingJackson2HttpMessageConverter"class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<propertyname="objectMapper"ref="customerObjectMapper">
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters>
<refbean="mappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
接下来,我们可以在Controller
方法上添加@ResponseBody
注解来返回JSON
(这里需要说一句,classpath
下需要有jackson
的jar包,这是前提),但是这就要求我们在每个Controller
方法中都进行一些重复的工作,比如:
public ModelMap getUserList(){
ModelMap modelMap = new ModelMap();
try {
modelMap.put("status", 1);
modelMap.put("data", userSerivce.getUserList());
modelMap.put("", "");
} catch (Exception e) {
modelMap.put("status", 0);
modelMap.put("data", "");
modelMap.put("msg", e.getMessage());
logger.error("getUserList occurs error:", e);
}
}
这样的重复代码在项目中不建议出现,我们其实只需要关心其中的data就可以了,所以我打算将其统一写到一个方法中,并且这也有利于以后对于公共结构的更改。下面就是一个切面来统一处理所有的接口:
/**
* 其中ResponseBase类和注解类CustomResponseBody都是自己写的
*/
/**
* @author Zhu
* @date 2015-5-18
* @version 0.0.1
* @description 负责将返回转换成统一消息格式
* 序列化为的格式如下:
* {
"status": 1,
"data": data,
"msg": ""
}
其中被注解的方法只需要关心data的内容即可
*/
@Aspect
@Component
public
class
ResponseAspect {
@Resource
private MappingJackson2HttpMessageConverter converter;
privatefinal Logger logger = LoggerFactory.getLogger(getClass());
/**
* 拦截所有@ResponseBody
* @author Zhu
* @date 2015-5-18上午11:32:26
* @description
*/@Pointcut("execution(* com.xxx.*.web.controller.*.*(..)) && @annotation(com.xxx.common.annotation.CustomResponseBody)")
publicvoidresponseBodyPointCut() {
}
/**
* @author Zhu
* @date 2015-5-18上午11:35:42
* @description
* @param pjp
* @throws Throwable
*/@Around(value = "responseBodyPointCut()")
@ResponseBodypublicvoidformatResult2JSON(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed();
ResponseBase responseBase = new ResponseBase();
responseBase.setData(ret);
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
converter.write(responseBase, MediaType.APPLICATION_JSON, outputMessage);
shutdownResponse(response);
}
/**
*
* @author Zhu
* @date 2015-5-18下午6:01:46
* @description
* @param jp
* @param error
* @throws Throwable
*/@AfterThrowing(pointcut = "responseBodyPointCut()", throwing = "error")
publicvoidhandleForException(JoinPoint jp, Throwable error) throws Throwable{
ResponseBase responseBase = new ResponseBase();
responseBase.setStatus(0);
responseBase.setMsg(error.getMessage());
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
logger.error(jp.getSignature().getName() + "-error!", error);
HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);
converter.write(responseBase, MediaType.APPLICATION_JSON, outputMessage);
shutdownResponse(response);
}
privatevoidshutdownResponse(HttpServletResponse response) throws IOException{
response.getOutputStream().close();
}
}
当然这里有几个关键点,需要提一下:
- 这也就提到了一个如何在
Spring
中手动使用配置好的Jackson
来序列化输出,这里我注入MappingJackson2HttpMessageConverter
,因为这里想要统一项目的JSON
序列化都交由Jackson
来做 - 由于是对
Controller
的代理,而一般Controller
是不实现接口的,那么就无法使用JDK
自带的动态代理,需要用到cglib
来做 - 关于上下文的问题,这里我在做的时候,由于碰到了两个上下文,即一般所说的rootContext和webContext。。。。
- 在自己返回json的情况下,需要shutdownResponse,即将Response关掉,不然可能会在这里输出json后还会再次输出一些内容
其余的内容后续再写吧,现在手头上项目太多,需要整理的东西也太多了~
原文:http://blog.csdn.net/u012345283/article/details/45850117
内容总结
以上是互联网集市为您收集整理的用一个切面来统一返回前端的JSON格式全部内容,希望文章能够帮你解决用一个切面来统一返回前端的JSON格式所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。