封装ResultVO实现统一返回结果 您所在的位置:网站首页 success意思是什么 封装ResultVO实现统一返回结果

封装ResultVO实现统一返回结果

#封装ResultVO实现统一返回结果| 来源: 网络整理| 查看: 265

背景

为了在开发中,返回到前端的数据内容格式趋于一致,我们在开发过程中最好能够将返回数据对象的格式进行约定,以便于开发对接过程中的约定速成;本章将带你了解如何设计统一返回对象,以及与其相关的知识内容。

封装返回结果对象 ResultVO对象封装

通过RestFul接口开发的接口,一般含有接口执行状态(成功、失败、失败描述、成功的数据返回对象)

因此我们可以将返回结果对象结构定义如下如下:

@Data @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "统一请求的返回对象") public class ResultVO { @ApiModelProperty(value = "错误代码") private Integer code; @ApiModelProperty(value = "消息") private String msg; @ApiModelProperty(value = "对应返回数据") private T data; }

定义了统一的的返回对象,那么一般我们需要考虑不同场景的输出和调用;比如成功,失败,或其他异常等情况的便捷调用。如果是因为某种业务原因需要返回失败操作,一般包含有错误码和错误信息,更有胜者包含对应的错误堆栈异常明细;那么就需要我们对于错误码做比较好的规划和设计了;

错误代码结构设计

这里我们设计了如下的错误码规划,首先定义一个IErrorCode(错误代码的接口类),里面定义两个方法,即获取错误码和错误消息的接口方法,如下

public interface IErrorCode { /** * 描述:得到错误码 * @date 2020/11/21 **/ Integer getCode(); /** * 描述:得到错误消息 * @Author Hank **/ String getMsg(); }

定义了接口类,然后我们再定义ErrorCode的接口实现枚举;如下

public enum ErrorCode implements IErrorCode { /*** * 1. 以下错误码的定义,需要提前与前端沟通 * 2. 错误码按模块进行错误码规划 * 3. 所有错误码枚举类均需要实现错误码接口类 */ SUCCESS(0,"操作成功"), SYSTEM_BUSY(10000,"系统繁忙,请稍后再试!"), FORM_VALIDATION_ERROR(10001,"表单验证错误"), // 用户登录方面错误码 LOGIN_ERROR(101001, "你还未登陆,请及时登陆"), TOKEN_ERROR(101002, "登录凭证已过期,请重新登录"); private Integer code; private String msg; ErrorCode(Integer code,String message){ this.code=code; this.msg=message; } @Override public Integer getCode() { return code; } @Override public String getMsg() { return msg; } } 小试牛刀

做了如上定义,我们就可以在对应的方法中去进行使用了,使用过程中,我们可以直接 return ResultVO;如下:

@RestController @RequestMapping(value = "/test") @Api(tags = "基础模块接口") public class IndexCtrl { @ApiOperation(value = "hello 接口",notes = "hello接口的描述") @GetMapping(value = "/index") public ResultVO hello(){ ResultVO rv=new ResultVO(); rv.setCode(ErrorCode.SUCCESS.getCode()); rv.setMsg(ErrorCode.SUCCESS.getMsg()); return rv; } } 效果增强

从上面的代码中我们可以看到,要做这样的返回,貌似还是比较繁琐,基本上要四行代码才能有一个完成的返回,并且ErrorCode类是固定的。

我们尝试将上面代码再做一次修改,希望达到如下效果:

在使用返回对象的时候能够尽量简单,或开发中无感各个模块可以定义自己的错误码实现类,融入到基础框架中 ResultVO对象增强

需要达到如上两点,我们首先修改ResultVO类,丰富构造函数和支持枚举方法的传值,代码如下:

@Data @AllArgsConstructor @NoArgsConstructor @ApiModel(value = "统一请求的返回对象") public class ResultVO { @ApiModelProperty(value = "错误代码") private Integer code; @ApiModelProperty(value = "消息") private String msg; @ApiModelProperty(value = "对应返回数据") private T data; public ResultVO(int code, String mesage) { setCode(code); setMsg(mesage); } public ResultVO(IErrorCode errorCode, T data) { setCodeMessage(errorCode); setData(data); } public ResultVO setCodeMessage(IErrorCode codeMessage) { setCode(codeMessage.getCode()); setMsg(codeMessage.getMsg()); return this; } } 封装助手工具

完成如上,我们还可以封装一个工具类RV,方便使用:

public class RV { /*** * 成功的返回对象 * @param data * @return */ public static ResultVO success(Object data) { return new ResultVO(ErrorCode.SUCCESS,data); } /** * 失败的返回对象 * @Param: ErrCodeInterface * @return: [ResultVO] * **/ public static ResultVO fail(IErrorCode errorCode) { return new ResultVO().setCodeMessage(errorCode); } /** * 描述: 通过errorCode和数据对象参数,构建一个新的对象 * @param [errorCode, data] * @return: [ResultVO] **/ public static ResultVO result(IErrorCode errorCode,Object data){ return new ResultVO(errorCode,data); } } 简洁性验证

还是以上面应用代码为例,最终代码修改如下

@RestController @RequestMapping(value = "/test") @Api(tags = "基础模块接口") public class IndexCtrl { @ApiOperation(value = "hello 接口",notes = "hello接口的描述") @GetMapping(value = "/index") public ResultVO hello(){ return RV.success(null);; } } 扩展性验证

前面我们描述了那么多,这里所谓的扩展性怎么理解呢,这里所谓的扩展性,更多是在不同业务系统,对于错误码的定义的扩展,比如一个我们项目里面,分成了多个不同的模块,但每个模块的实现都依赖于基础common包中封装的工具;对于错误码,我们不可能一次性在common中定义出所有模块的错误码;因此我们在设计的时候,特意定义了IErrorCode接口库类,默认由ErrorCode做了实现;

也就意味着,在common包中定义的这些类,没有特殊情况不用高频的修改,那我们在其他业务模块要定义自己的错误码可以怎么做呢。

如下,我们只需要在对应的业务模块,定义自己的错误码枚举类即可,比如在设备管理模块

/** * new-retail *

* 错误码定义范围 10101-10200 *

* @author Hank * @since 2020-11-21 */ public enum DeviceErrorCode implements IErrorCode { DEVICE_OFFLINE(10101,"设备已离线"), COMMAND_ERROR(10102,"指令错误"); private Integer code; private String msg; DeviceErrorCode(Integer code,String message){ this.code=code; this.msg=message; } @Override public Integer getCode() { return code; } @Override public String getMsg() { return msg; } }

在Controller中的应用

我们根据设备管理模块定义了对应的错误枚举类,也就意味着,在做该模块实际业务的时候,我们可以直接对外抛出对应的错误码,而不必考虑与其他模块的适配问题;其应用如下;

@PostMapping(value = "/restart") public ResultVO restart(@RequestBody DeviceInfo deviceInfo) { load(deviceInfo); if (!deviceInfo.online()) { return RV.result(DeviceErrorCode.DEVICE_OFFLINE, deviceInfo); } return RV.success(deviceInfo); }

在异常中的应用

在前章节我们讲到异常BusinessException的封装,但是我们只是做了简单的继承RuntimeException而已,没有继续深入;那我们再结合本章所讲到的错误代码进行完善增强

/** * new-retail-lesson *

* 自定义业务异常类 *

* @author Hank * @since 2020-10-31 */ public class BusinessException extends RuntimeException { private int code; private String detailMessage; public BusinessException(int code, String message) { super(message); this.code = code; this.detailMessage = message; } public BusinessException(IErrorCode errorCode) { this(errorCode.getCode(),errorCode.getMsg()); } public int getCode() { return code; } public String getDetailMessage() { return detailMessage; } }

从上面代码中,我们可以看出,我们在BusinessException中增加了两个变量code,detailMessage;并对构造函数做了多样性处理,值得注意的是我们在构造函数中,增加了IErrorCode接口的参数;

既然在异常做了增强,那我们的异常拦截处也需要做响应的处理,找到我们前面定义的全局异常类GlobalExceptionHander,在对应的拦截BusinessException处做对应的处理,如下

@RestControllerAdvice public class GlobalException { /** * 描述:业务异常拦截 * @param * @date 2020/10/31 * @Author Hank **/ @ExceptionHandler(value = BusinessException.class) public ResultVO businessException(BusinessException e){ ResultVO rv= new ResultVO(e.getCode(),e.getDetailMessage()); return rv; } }

完成了上面的基础工作,我们接下来看下在编码中能够如何使用;

在Controller中有业务异常抛出时,拿我们刚才的例子,代码调整如下,不用直接return,可以直接抛出对应的业务异常,由GlobalExceptionHander来兜底就行 @PostMapping(value = "/restart") public ResultVO restart(@RequestBody DeviceInfo deviceInfo) { load(deviceInfo); if (!deviceInfo.online()) { throw new BusinessException(DeviceErrorCode.DEVICE_OFFLINE); } return RV.success(deviceInfo); } 在业务代码中,可以直接抛出对应的业务异常,最终由GlobalException来兜底

当然在异常处理部分,我们可以根据场景需要,定义不同类型的异常,结构与上面类似,即可达到相同的效果

小结

上面我们主要介绍了

ResultVO对象的封装然后介绍了统一错误代码接口类和错误枚举类的设计以及结合ResultVO对象和IErrorCode接口做了整合通过IErrorCode与自定义异常结合再结合全局异常拦截与ResultVO对象结合做全局异常拦截;最后还介绍了结合定义的ResultVO对象和IErrorCode接口类,可以如何做到异常方面的扩展。

以上为本章介绍的所有内容,希望对你有帮助,如果你在统一返回对象封装和异常封装方面有更好的不同实践,也欢迎在留言区进行留言。

想要了解更多信息,可关注本公众号(一起学开源);或请长按以下二维码添加助手。将拉你加入社区进行更多交流

在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有