欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

自定义spring mvc的json视图实现思路解析

程序员文章站 2023-12-05 17:16:16
场景 我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范, 前端(安卓,ios,web前端)和后端进行了数据的格式规范的讨论,确定了js...

场景

我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范,

前端(安卓,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视图实现思路解析,希望对大家有所帮助