自定义spring mvc的json视图实现思路解析
场景
我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范,
前端(安卓,ios,web前端)和后端进行了数据的格式规范的讨论,确定了json的数据格式:
{ "code":"200", "data":{"":""}, "message":"处理成功" } { "code":"300", "data":{"":""}, "message":"没有此用户" }
code代表请求处理状态:200为正常处理,300为业务异常处理,500就系统异常处理。
data代表后台返回的数据。
message后台的提示语,正常或者成功的时候会返回错误原因。
问题来了
让每一个人对每一个json视图的返回值都要进行包装的话,岂不很麻烦,
这个时候aop就登场了,我们可以利用aop的思想在请求返回json之后还未response到客户端时为其包装上一层。
实现步骤
启用aop
<!-- base-package 如果多个,用“,”分隔 --> <context:component-scan base-package="com.we,cn.isuyang"> <context:include-filter type="annotation" expression="org.springframework.stereotype.service" /> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.controller" /> </context:component-scan> <!-- 打开aop 注解 --> <aop:aspectj-autoproxy />
创建切面
/** * json返回切面 * <p> * 用于处理json返回结果 * * @author z*nxiang(529272571@qq.com) * @date 2017年4月28日 */ @component @aspect @order(2) public class jsonreturnaspect { /** * 设置分页默认值 * <p> * 如果分页没有设置值,则默认从系统的配置文件里读取 * * @param pjp 切点 */ @around(value = "@annotation(org.springframework.web.bind.annotation.responsebody)") @order(1) public object warp(final proceedingjoinpoint pjp) throws throwable { object list = pjp.proceed(); if (isreturnvoid(pjp)) { httpservletresponse response = ((servletrequestattributes) requestcontextholder.getrequestattributes()) .getresponse(); if (isneedwrap(pjp)) { response.getwriter().write(jsonutil.tojson(success("操作成功"))); } return list; } return data(list); } /** * 是否需要包裹 * * @param pjp 切点 * * @return true表示不需要 */ private boolean isneedwrap(final proceedingjoinpoint pjp) { method method = aspectutil.getmethod(pjp); return !method.isannotationpresent(void.class); } /** * 是否返回空 * * @param pjp * @return true:返回类型为void,false:返回类型不是void */ private boolean isreturnvoid(proceedingjoinpoint pjp) { method method = aspectutil.getmethod(pjp); class<?> returntype = method.getreturntype(); return "void".equals(returntype.getname()); } /** * 构建成功后的返回对象 * <p> * 消息为空时,不提示,不为空则进行提示 * * @param message 成功消息 * @return json对象 */ public static map<string, object> success(final string message) { map<string, object> map = maputil.map(); map.put("code", statuscode.success.key()); map.put("message", message); map.put("data",""); return map; } /** * 构建成功后的返回对象 * <p> * 消息为空时,不提示,不为空则进行提示 * * @param message 成功消息 * @return json对象 */ public static map<string, object> data(final object data) { map<string, object> map = maputil.map(); map.put("code", statuscode.success.key()); map.put("message", message); map.put("data",data); return map; } }
分析一下
@component 这个注解表示将这个对象交给spring容器进行实例化
@aspect 表示这是一个切面类
@around(value = "@annotation(org.springframework.web.bind.annotation.responsebody)")
表示凡是方法上带有@responsebody注解的都是这个切面中切点,换句话说都会被拦截。
注意:
warp方法中的proceedingjoinpoint参数只有环绕通知才可以使用joinpoint的子类proceedingjoinpoint,
各连接点类型可以调用代理的方法,并获取、改变返回值。否则就是用joinpoint。
情况一:假设conroller类中的函数不需要任何返回值
比如:我对一个实体对象进行更新我只需要把更新结果返回去就ok了,不需要填充数据
返回的数据格式:
{ "code":"200", "data":"", "message":"处理成功" }
实现思路:
在切面处理类的处理函数中获取到这个函数的返回值类型如果是void就返回指定格式的数据。
上面的isreturnvoid()就是做这样的一个判断。
你只需要将函数的返回值为void即可:
@requestmapping @responsebody public void add(long matchid, model model) { slxsignupviewservice.setaddinfo(matchid, model); }
情况二:假设conroller类中的函数的返回值不需要包裹呢
比如:
某些前端插件以及第三方对接(支付)的返回值是规定好的,
以及下载文件,我们这些就是多余了,
实现思路:
自定一个@void的注解:
/** * 空注解 * <p> * 用于标识将controller层中的返回值原模原样的out出去 * * @author wangsen(wangsenhehe@126.com) * @date 2017年8月17日 */ @target({ elementtype.method }) @retention(retentionpolicy.runtime) @documented public @interface void { }
在controller层的方法上添加这个注解
/** * 支付完成 */ @void @responsebody @requestmapping public void payfinish() throws ioexception { alipayviewservice.payfinish(); }
在这个切面处理类上判断这个函数是否包含这个注解如果包含
就不作处理,原模原样的返回出去。
jsonreturnaspect类中的isneedwrap()方法就是处理这个需求。
总结
以上所述是小编给大家介绍的自定义spring mvc的json视图实现思路解析,希望对大家有所帮助
推荐阅读
-
自定义spring mvc的json视图实现思路解析
-
FeignClient原理解析,100行代码实现feign功能,mybatis的mapper、dubbo、feign实现原理模拟。spring扫描自定义注解原理。Javassist实现动态代理原理
-
利用Razor在ASP.NET MVC中的实现,自定义视图引擎框架(2)
-
spring MVC自定义视图实现jsonp
-
Spring技术内幕——深入解析Spring架构与设计原理(四)Web MVC的实现
-
整合Spring MVC,mybatis,hibernate,freemarker框架实现的自定义注解Validator验证机制实现对敏感词过滤的代码分享
-
spring MVC cors跨域实现源码的示例代码解析
-
spring MVC cors跨域实现源码的示例代码解析
-
FeignClient原理解析,100行代码实现feign功能,mybatis的mapper、dubbo、feign实现原理模拟。spring扫描自定义注解原理。Javassist实现动态代理原理
-
Spring技术内幕——深入解析Spring架构与设计原理(四)Web MVC的实现