自定义spring mvc的json视图实现思路解析
场景 我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范, 前端(安卓,Ios,web前端)和后端进行了数据的格式规范的讨论,确定了json的数据格式: { "code":"200","data":{"":""},"message":"处理成功" } { "code":"300","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 ZhuangJunxiang(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,data); return map; } } 分析一下 @Component 这个注解表示将这个对象交给spring容器进行实例化 @Aspect 表示这是一个切面类
表示凡是方法上带有@ResponseBody注解的都是这个切面中切点,换句话说都会被拦截。 注意: warp方法中的ProceedingJoinPoint参数只有环绕通知才可以使用JoinPoint的子类ProceedingJoinPoint, 各连接点类型可以调用代理的方法,并获取、改变返回值。否则就是用JoinPoint。 情况一:假设conroller类中的函数不需要任何返回值 比如:我对一个实体对象进行更新我只需要把更新结果返回去就OK了,不需要填充数据 返回的数据格式: { "code":"200","data":"","message":"处理成功" } 实现思路: 在切面处理类的处理函数中获取到这个函数的返回值类型如果是void就返回指定格式的数据。 你只需要将函数的返回值为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视图实现思路解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |