自定义spring mvc的json视图实现思路解析
作者:王森 发布时间:2023-03-12 12:04:44
场景
我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范,
前端(安卓,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 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, 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视图实现思路解析网站的支持!
来源:http://www.cnblogs.com/wangsen/p/8031283.html


猜你喜欢
- cin的返回值今天在用STL时用到while(cin>>s1>>a>>s2>>b)这样的语句
- JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId1、自动主键默认情况下,主键是一个连续的64位数字(lon
- 首先看如下代码示例:System.out.println(0.05 + 0.01);System.out.println(0.05 - 0.
- 本文实例为大家分享了java将某个数据库的表全部导出到excel中的方法,供大家参考,具体内容如下第一步:如何用POI操作Excel@Tes
- Android11 读写权限申请Android11系统对应用写入权限做了严格的限制。本文介绍如何获取文件读写权限。项目中 build.gra
- 本文实例讲述了Android观察者模式。分享给大家供大家参考。具体分析如下:一、环境:主机:WIN8开发环境:Eclipse二、说明:1.打
- 使用maven的profile功能,我们可以实现多环境配置文件的动态切换,可参考我的上一篇博客。但随着SpringBoot项目越来越火,越来
- 这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- 如下所示://定义二维数组写法1 class numthree{public static void main(String[] args)
- #region 解压 文件 zip 格式 rar 格式
- 一.前言RabbitMQ 是一种快速、灵活、可靠的消息传递方式,可用于构建分布式应用程序、异步处理任务、实现消息队列等。下面是 Java 原
- 本文为大家分享了C#基于Socket套接字的网络通信封装代码,供大家参考,具体内容如下摘要之所以要进行Socket套接字通信库封装,主要是直
- 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文。http://developer.an
- 芬兰数学家因卡拉花费3个月设计出了世界上迄今难度最大的数独游戏,而且它只有一个答案。因卡拉说只有思考能力最快、头脑最聪明的人才能破解这个游戏
- Java中线程的创建有两种方式: 1. 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在
- 生成随机数可以用伪随机数发生器Random,受种子控制生成伪随机数,默认以当前时间值为种子。如果程序运行的很快,就会导致在几乎同一时刻运行多
- 1: Nacos搭建可以参考 https://www.jb51.net/article/196842.htmSpringCloud 版本&l
- 一、int还记得 C 语言里的 int 吗,C里面的 int 有着无符号与有符号之分但是Java内就没有,且固定占4个字节大小,也就是32比
- maven配置项目的jdk版本无效排查最近在配置项目的jdk的时候发现在pom.xml中配置的1.8版本无效,maven更新后就变成了1.7
- 本文实例汇总了Java文件操作。分享给大家供大家参考,具体如下:1.创建文件夹//import java.io.*; File myFold