• 代码优雅之道——断言 + Springboot统一异常处理


    第一集 代码优雅之道——统一返回结果

    1、为什么要这么做

    在上一篇最后提到就是面对业务代码中出现异常的情况,如果不处理,则展示给用户的信息是非常不友好的。比如以下代码出现空指针

    那么前端得到的响应是啥样?

    此外在业务代码中可能会用很多的校验,有的校验返回一些提示信息,有的校验可能需要抛出指定的异常。

    通常我们使用try {...} catch {...} finally {...} 代码块来处理异常,而这些异常我们是不能直接展现给用户。所以对异常进行分类统一处理,减少冗余代码,使代码风格统一更优雅。

    2、断言处理

    像上图中一个代码块中会有很多的校验,而实际项目中非空或者一些业务判断都是很频繁的。我们来改造一下上图中的代码,使用断言后两行代码就解决了

    到这里不用看源码大家肯定也已经猜到了,它肯定用的if(){}

    是null就抛出异常,而state()却不一样,为false时抛出异常,所以这里的表达式填我们想要的结果。

    用之前去Assert类中看一看,多用几次自然就熟练了,开发起来也会更加的快速。

    实际项目中我们可能还需要调用其他服务暴露出来的接口,调用失败后抛出自定义的异常

    此时我们也可以写个断言工具类

    1. public class AssertUtil {
    2. /**
    3. * 服务调用异常
    4. * @param expression
    5. * @param message
    6. */
    7. public static void isTrueServiceInvoke(boolean expression, String message) {
    8. if (!expression) {
    9. throw new ServiceInvokeException(message);
    10. }
    11. }
    12. }

    那么这一类问题,都可以使用,解决了代码冗余问题

    3、统一异常处理

    通过以上描述我们也可以看出,项目中除了空指针这种异常,还有断言抛出的异常,还有自定义异常,对各种各样的异常统一处理,使得返回更加友好的信息。

    主要通过 @RestControllerAdive 提升作用域,通过 @ExceptionHandler 注解来处理不同的异常。

    1. import com.example.assertdemo.common.exception.ServiceInvokeException;
    2. import com.example.assertdemo.constant.ResultCodeEnum;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.springframework.web.bind.annotation.ControllerAdvice;
    5. import org.springframework.web.bind.annotation.ExceptionHandler;
    6. import org.springframework.web.bind.annotation.ResponseBody;
    7. @Slf4j
    8. @ControllerAdvice
    9. public class GlobalExceptionHandler {
    10. @ResponseBody
    11. @ExceptionHandler(NullPointerException.class)
    12. public ApiResult nullPointerExceptionHandler(NullPointerException exception) {
    13. log.error(exception.getMessage());
    14. return ApiResult.fail(ResultCodeEnum.SERVE_EXCEPTION);
    15. }
    16. @ResponseBody
    17. @ExceptionHandler(ServiceInvokeException.class)
    18. public ApiResult serviceInvokeExceptionHandler(ServiceInvokeException exception){
    19. log.error(exception.getMessage());
    20. return ApiResult.fail(ResultCodeEnum.SERVE_EXCEPTION);
    21. }
    22. }

    返回的状态码和提示信息搞个枚举类

    1. @Getter
    2. public enum ResultCodeEnum{
    3. /**
    4. * success
    5. */
    6. SUCCESS(0,"操作成功"),
    7. /**
    8. * fail
    9. */
    10. FAIL(-1,"操作失败"),
    11. /**
    12. * 参数错误:1001-1999
    13. */
    14. PARAM_IS_INVALID(1001,"参数无效"),
    15. PARAM_TYPE_ERROR(1002,"参数类型错误"),
    16. /**
    17. * 业务错误:2001-2999
    18. */
    19. TERMINATE_CONTRACT_FAIL(2001,"终止合同失败,请联系管理员"),
    20. SERVE_EXCEPTION(3001,"当前服务出小差了,请联系管理员"),
    21. ;
    22. /**
    23. * 状态码
    24. */
    25. private final int code;
    26. /**
    27. * 提示信息
    28. */
    29. private final String message;
    30. ResultCodeEnum(Integer code, String message){
    31. this.code = code;
    32. this.message = message;
    33. }
    34. }

    此时我们再去请求2、断言处理中的接口,这种提示就非常友好,不会给用户展示看不懂的一连串异常信息,还能让开发者及时定位到问题去处理。

    4、断言类中的方法

    说白了很多方法就是填入你希望的结果,比如isTrue(a==1,""),也就是我希望a等于1,如果不等于就抛出异常。

    对象和类型断言

    方法

    说明

    notNull()

    对象是null抛出异常

    isNull()

    对象不是null抛出异常

    isInstanceOf()

    检查对象必须为另一个特定类型的实例

    isAssignable()

    检查类型

    文本断言

    方法

    说明

    hasLength()

    只要不是null和空字符串就不会报异常

    hasText()

    增强检查条件,字符串至少包含一个非空白字符,可以使用hasText()方法

    doesNotContain()

    检查参数不包含特定子串

    逻辑断言

    方法

    说明

    isTrue()

    条件为假抛出IllegalArgumentException 异常

    state()

    该方法与isTrue一样,但抛出IllegalStateException异常

    Collection和map断言

    方法

    说明

    Collection应用notEmpty()

    Collection不是null并包含至少一个元素

    map应用notEmpty()

    检查map不null,并至少包含一个entry(key,value键值对)

    数组断言

    方法

    说明

    notEmpty()

    可以检查数组不null,且至少包括一个元素

    noNullElements()

    确保数组不包含null元素

  • 相关阅读:
    Python数据驱动测试 unittest+ddt
    LeetCode刷题复盘笔记——37. 解数独(一文搞懂回溯解决经典的解数独问题)
    操作系统漏洞验证及加固-MS08_067漏洞利用与安全加固
    GO语言的由来与发展历程
    使用VMware16克隆功能快速准备CentOS 7.9操作系统集群
    MySQL --- 数据库查询 - 排序查询、分页查询
    如果快速有效的开项目启动会?
    Qt如何保证控件调用时候的线程安全
    linux rsyslog安装配置
    在VS Code 中调试远程服务器的PHP代码
  • 原文地址:https://blog.csdn.net/QingXu1234/article/details/126590702