• @RestControllerAdvice 统一异常处理


    是什么

    @RestControllerAdvice 统一异常处理

    @RestControllerAdvice是一个组合注解,由@ControllerAdvice、@ResponseBody组成

    ControllerAdvice和RestControllerAdvice的区别
    两者都是全局捕获异常,但是RestControllerAdvice更加强大,其作用相当于ControllerAdvice+ResponseBody 

    basePackages: 指定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理

    @ExceptionHandler(value = Exception.class) ExceptionHandler的作用是用来捕获指定的异常。

    为什么要有这个注解

    对于异常处理情况,我们也需要统一成上面的格式。如果我们在controller中通过try catch来处理异常的话,会出现一个问题就是每个函数里都加一个Try catch,代码会变的很乱。下面我们就通过spring boot的注解来省略掉controller中的try-catch 帮助我们来封装异常信息并返回给前端,这样用户也不会得到一些奇奇怪怪的错误提示。

    怎么用

    假设有枚举

    1. public enum BizCodeEnume {
    2. UNKNOW_EXCEPTION(10000,"系统未知异常"),
    3. VAILD_EXCEPTION(10001,"参数格式校验失败");
    4. private int code;
    5. private String msg;
    6. BizCodeEnume(int code,String msg){
    7. this.code = code;
    8. this.msg = msg;
    9. }
    10. public int getCode() {
    11. return code;
    12. }
    13. public String getMsg() {
    14. return msg;
    15. }
    16. }

     控制层

    1. /**
    2. * 保存
    3. */
    4. @RequestMapping("/save")
    5. public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
    6. if(result.hasErrors()){
    7. //1.获取校验错误的结果
    8. Map map = new HashMap<>();
    9. result.getFieldErrors().forEach((item)->{
    10. //FieldError获取到错误的提示
    11. String message = item.getDefaultMessage();
    12. //获取错误的属性的名字
    13. String field = item.getField();
    14. map.put(field,message);
    15. System.out.println("******");
    16. });
    17. return R.error(400,"提交的数据不合法").put("data",map);
    18. }
    19. brandService.save(brand);
    20. return R.ok();
    21. }

    这个控制层主要是接受请求对象保存到数据库中,为防止老6跳过前端的页面,用postman发送请求。需要对请求对象进行判断 ,这里直接在BrandEntity 这个类上用

    /**
     * jsr303
     * 1)给bean添加校验注解,并定义自己的message提示
     * 2)开启校验功能@valid
     * 效果:校验错误以后会有默认的响应
     * 3)给校验的bean后紧跟一个bindingResult ,就可以获取到校验结果
     */
    1. @Data
    2. @TableName("pms_brand")
    3. public class BrandEntity implements Serializable {
    4. private static final long serialVersionUID = 1L;
    5. /**
    6. * 品牌id
    7. */
    8. @TableId
    9. private Long brandId;
    10. /**
    11. * 品牌名
    12. */
    13. @NotBlank(message = "品牌名必须提交")
    14. private String name;
    15. /**
    16. * 品牌logo地址
    17. */
    18. @NotEmpty
    19. @URL(message = "logo必须是一个url地址")
    20. private String logo;
    21. /**
    22. * 介绍
    23. */
    24. private String descript;
    25. /**
    26. * 显示状态[0-不显示;1-显示]
    27. */
    28. @NotNull
    29. private Integer showStatus;
    30. /**
    31. * 检索首字母
    32. */
    33. @NotEmpty
    34. @Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字母必须是首字母")
    35. private String firstLetter;
    36. /**
    37. * 排序
    38. */
    39. @Min(value = 0,message = "排序必须大于等于0")
    40. private Integer sort;
    41. }

    大家可以看到在控制层的判断还是十分繁琐 ,这个时候使用@RestControllerAdvice 解决

    1. @Slf4j
    2. @RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
    3. public class GulimallExceptionControllerAdvice {
    4. @ExceptionHandler(value = MethodArgumentNotValidException.class)
    5. public R handleVaildException(MethodArgumentNotValidException e){
    6. Map map = new HashMap<>();
    7. log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
    8. BindingResult bindingResult = e.getBindingResult();
    9. bindingResult.getFieldErrors().forEach((item)->{
    10. map.put(item.getField(),item.getDefaultMessage());
    11. });
    12. return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",map);
    13. }
    14. @ExceptionHandler(value = Throwable.class)
    15. public R all(Exception e){
    16. log.error("出现问题{},异常类型:{}",e.getMessage(),e.getClass());
    17. return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    18. }
    19. }

    控制层可以简化为 

    1. @RequestMapping("/save")
    2. public R save(@Valid @RequestBody BrandEntity brand/*, BindingResult result*/){
    3. // if(result.hasErrors()){
    4. // //1.获取校验错误的结果
    5. // Map map = new HashMap<>();
    6. // result.getFieldErrors().forEach((item)->{
    7. // //FieldError获取到错误的提示
    8. // String message = item.getDefaultMessage();
    9. // //获取错误的属性的名字
    10. // String field = item.getField();
    11. // map.put(field,message);
    12. // System.out.println("******");
    13. // });
    14. // return R.error(400,"提交的数据不合法").put("data",map);
    15. // }
    16. brandService.save(brand);
    17. return R.ok();
    18. }

     

  • 相关阅读:
    [2022安恒夏令营] 5个小题
    分包(微信小程序)
    springboot全局异常处理详解
    Kafka与Spring Boot等应用框架的集成及消息驱动模型
    SSM+基于SSM的课堂考勤管理系统的设计与实现 毕业设计-附源码191617
    查找内轮廓(孔洞)
    【01】Spring源码-手写篇-手写IoC实现
    【JAVA】01 JAVA概述
    用go获取IPv4地址,WLAN的IPv4地址,本机公网IP地址详解
    Apache DolphinScheduler新一代分布式工作流任务调度平台实战-中
  • 原文地址:https://blog.csdn.net/m0_62436868/article/details/127398313