• SpringMvc(四、统一异常处理


    导学 ==> 项目异常统一处理:

    • 异常处理器

    • 自定义异常

    • 自定义异常编码

    一、异常处理器 

    平时开发可能出现的异常及其原因

    • 框架内抛出异常:因使用规范不一致导致
    • 数据层(Repository)抛出异常:因外部服务器故障导致
    • 业务层(Service)排除异常:因业务逻辑书写错误导致
    • 表现层(Controller)抛出异常:因数据手机,效验规则导致
    • 工具类(Utils)抛出异常:因工具类书写不严谨、不健壮导致

    各个层级均有可能抛出异常,如果我们每层都处理异常,代码过于冗余

    我们可以将各层的异常统统抛出,到表现层(Controller)对这些异常进行统一的处理 

    那我们如何在表现层处理这些异常呢?每个方法都去单独书写异常处理方案?这样不仅书写量巨大且耗时,又不利于维护。我们可以采用AOP思想 ,SpringMvc已经为我们造好了轮子

    1,在Controller层下新建ProjectException类

    1. @RestControllerAdvice
    2. public class ProjectException {
    3. @ExceptionHandler(Exception.class)
    4. public void executeException(Exception e){
    5. System.out.println("异常被我处理啦");
    6. }
    7. }

    2,在SpringMvc配置类下扫描当前类

    1. package com.brrbaii.config;
    2. import org.springframework.context.annotation.ComponentScan;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    5. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    7. @Configuration
    8. @ComponentScan("com.brrbaii.controller")
    9. //Json数据转对象
    10. @EnableWebMvc
    11. public class SpringMvcConfig implements WebMvcConfigurer {
    12. //过滤静态资源,防止被SpringMvc拦截
    13. @Override
    14. public void addResourceHandlers(ResourceHandlerRegistry registry) {
    15. registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
    16. registry.addResourceHandler("/js/**").addResourceLocations("/js/");
    17. registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    18. registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    19. }
    20. }

    3,测试

    我们在Service层手动制造一个异常 

    访问这个方法,观察控制台输出结果

    4,设置异常处理统一格式 

    新建Result类

    1. package com.brrbaii.controller;
    2. import lombok.Getter;
    3. import lombok.NoArgsConstructor;
    4. import lombok.Setter;
    5. @Getter
    6. @Setter
    7. @NoArgsConstructor
    8. public class Result {
    9. //数据
    10. T data;
    11. //消息
    12. String msg;
    13. //状态码
    14. Integer code;
    15. public Result(Integer code,T data, String msg) {
    16. this.data = data;
    17. this.msg = msg;
    18. this.code = code;
    19. }
    20. public Result(Integer code,T data) {
    21. this.data = data;
    22. this.code = code;
    23. }
    24. }

    修改ProjectException类,使其方法返回Result


    前端收到的结果: 

    二、自定义异常 

    项目遇到的异常分类:

    • 业务异常(BusinessException)
      • 规范的用户行为产生的异常
      • 不规范的用户行为操作产生的异常
    • 系统异常(SystemException)
      • 项目运行过程中可预计但无法避免的异常
    • 其他异常(Exception)
      • 编程人员未预期到的异常 

    上述异常处理方案: 

    • 业务异常(BusinessException)
      • 发送对应的消息传递给客户,题型规范操作
    • 系统异常(SystemException)
      • 发送固定消息传递给用户,安抚用户
      • 发送特定的消息给运维人员,提醒维护
      • 记录日志
    • 其他异常(Exception)
      • 发送固定消息传递给用户,安抚用户
      • 发送特定的消息给编程人员,提醒维护(纳入后续预期范围)
      • 记录日志

    我们对可能出现的种种异常集中为上面三类异常,分别创建对应的类

    1,BusinessException

    1. package com.brrbaii.controller.exception;
    2. import lombok.Data;
    3. @Data
    4. public class BusinessException extends RuntimeException{
    5. //自定义异常编码
    6. private Integer code;
    7. public BusinessException(Integer code, String message) {
    8. super(message);
    9. this.code = code;
    10. }
    11. public BusinessException(Integer code, String message, Throwable cause ) {
    12. super(message, cause);
    13. this.code = code;
    14. }
    15. }

    2,SystemException

    1. package com.brrbaii.controller.exception;
    2. import lombok.Data;
    3. import org.springframework.web.bind.annotation.ExceptionHandler;
    4. import org.springframework.web.bind.annotation.RestControllerAdvice;
    5. @Data
    6. public class SystemException extends RuntimeException{
    7. private Integer code;
    8. public SystemException(Integer code, String message) {
    9. super(message);
    10. this.code = code;
    11. }
    12. public SystemException(Integer code, String message, Throwable cause ) {
    13. super(message, cause);
    14. this.code = code;
    15. }
    16. }

    3,修改我们的异常处理器(ProjectException),然它处理上述两异常异常 

    1. package com.brrbaii.controller.exception;
    2. import com.brrbaii.controller.Result;
    3. import org.springframework.web.bind.annotation.ExceptionHandler;
    4. import org.springframework.web.bind.annotation.RestControllerAdvice;
    5. @RestControllerAdvice
    6. public class ProjectException {
    7. //处理系统异常
    8. @ExceptionHandler(SystemException.class)
    9. public Result executeSystemException(SystemException e){
    10. // 1,发送固定消息传递给用户,安抚用户
    11. // 2,发送特定的消息给运维人员,提醒维护
    12. // 3,记录日志
    13. // 4,返回异常消息
    14. return new Result(e.getCode(),null,e.getMessage());
    15. }
    16. //处理业务异常
    17. @ExceptionHandler(BusinessException.class)
    18. public Result executeBusinessException(BusinessException e){
    19. // 1,发送固定消息传递给用户,安抚用户
    20. // 2,发送特定的消息给开发人员,提醒维护(后续纳入可预期异常范畴)
    21. // 3,记录日志
    22. // 4,返回异常消息
    23. return new Result(e.getCode(),null,e.getMessage());
    24. }
    25. }

     接下来我们对可能出现异常的代码进行包装,将异常转换为我们上述自定义的异常

    三、自定义异常编码

     对于返回的异常编码,我们不想固定写死

    可以创建一个Code类,对异常编码进行统一

    1. package com.brrbaii.controller;
    2. public class Code {
    3. //系统异常
    4. public static final Integer SYSTEM_ERR = 50001;
    5. //业务异常
    6. public static final Integer BUSINESS_ERR = 50006;
    7. //请求成功
    8. public static final Integer SAVE_OK = 20011;
    9. public static final Integer DELETE_OK = 20021;
    10. public static final Integer UPDATE_OK = 20031;
    11. public static final Integer SELECT_OK = 20041;
    12. //请求失败
    13. public static final Integer SAVE_ERR = 20010;
    14. public static final Integer DELETE_ERR = 20020;
    15. public static final Integer UPDATE_ERR = 20030;
    16. public static final Integer SELECT_ERR = 20040;
    17. }

     修改方法返回的异常编码

  • 相关阅读:
    C/C++教程 从入门到精通《第十五章》—— MFC资源详解
    专业软件测评中心:关于软件性能测试的实用建议
    操作系统:操作系统相关概念博客系统整理
    【Exception】Error: Dynamic require of “path“ is not supported
    私募基金CRM客户关系管理系统软件开发应该具备的功能清单
    C. Water the Trees Educational Codeforces Round 126 (Rated for Div. 2)
    极坐标扇图使用场景与功能详解
    【性能优化】(域名发散)为什么主页面和静态资源要置于不同的域名下?
    Linux | gdb的基本使用
    mysql UUID 作为主键的问题
  • 原文地址:https://blog.csdn.net/weixin_48841931/article/details/126770067