@RestControllerAdvice 统一异常处理

简介: @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 帮助我们来封装异常信息并返回给前端,这样用户也不会得到一些奇奇怪怪的错误提示。


怎么用

假设有枚举

public enum BizCodeEnume {
    UNKNOW_EXCEPTION(10000,"系统未知异常"),
    VAILD_EXCEPTION(10001,"参数格式校验失败");
    private int code;
    private String msg;
    BizCodeEnume(int code,String msg){
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

控制层

    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
        if(result.hasErrors()){
            //1.获取校验错误的结果
            Map<String, String> map = new HashMap<>();
            result.getFieldErrors().forEach((item)->{
           //FieldError获取到错误的提示
           String message = item.getDefaultMessage();
            //获取错误的属性的名字
           String field = item.getField();
           map.put(field,message);
           System.out.println("******");
       });
            return R.error(400,"提交的数据不合法").put("data",map);
        }
            brandService.save(brand);
            return R.ok();
    }

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


/**

* jsr303

* 1)给bean添加校验注解,并定义自己的message提示

* 2)开启校验功能@valid

* 效果:校验错误以后会有默认的响应

* 3)给校验的bean后紧跟一个bindingResult ,就可以获取到校验结果

*/


@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
  private static final long serialVersionUID = 1L;
  /**
   * 品牌id
   */
  @TableId
  private Long brandId;
  /**
   * 品牌名
   */
  @NotBlank(message = "品牌名必须提交")
  private String name;
  /**
   * 品牌logo地址
   */
  @NotEmpty
  @URL(message = "logo必须是一个url地址")
  private String logo;
  /**
   * 介绍
   */
  private String descript;
  /**
   * 显示状态[0-不显示;1-显示]
   */
  @NotNull
  private Integer showStatus;
  /**
   * 检索首字母
   */
    @NotEmpty
    @Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字母必须是首字母")
  private String firstLetter;
  /**
   * 排序
   */
  @Min(value = 0,message = "排序必须大于等于0")
  private Integer sort;
}

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

@Slf4j
@RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleVaildException(MethodArgumentNotValidException e){
        Map<String, String> map = new HashMap<>();
        log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        bindingResult.getFieldErrors().forEach((item)->{
          map.put(item.getField(),item.getDefaultMessage());
        });
        return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",map);
    }
    @ExceptionHandler(value = Throwable.class)
    public  R all(Exception e){
        log.error("出现问题{},异常类型:{}",e.getMessage(),e.getClass());
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }
}

控制层可以简化为

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

7648368984694bacbf1f34819a81c4a1.png


相关文章
|
2月前
|
前端开发 Java Spring
统一异常处理
统一异常处理
23 2
|
1月前
|
前端开发 Java 程序员
SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常
SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常
|
2月前
|
JavaScript 中间件 测试技术
中间件应用异常处理
【5月更文挑战第2天】中间件应用异常处理
27 2
中间件应用异常处理
|
2月前
|
JSON 前端开发 Java
统一数据返回格式 及 可能遇到的问题;统一异常处理
统一数据返回格式需要创建一个新类并使其实现ResponseBodyAdvice 接口并重写里面的方法,然后给当前类加上@ControllerAdvice注解。 实际应用时还有几个问题: 问题一:重复打包 问题二:ClassCastException: com.example.Spring_demo.Resp cannot be cast to java.lang.String 统一异常处理需要使用两个注解@ExceptionHandler@ControllerAdvice
55 2
统一数据返回格式 及 可能遇到的问题;统一异常处理
|
2月前
|
存储 C++
C++中的异常处理与错误管理
C++中的异常处理与错误管理
22 0
C++中的异常处理与错误管理
|
10月前
统一404异常
统一404异常
|
10月前
全局统一异常处理
全局统一异常处理
42 0
|
11月前
|
JSON Java API
基于SpringCloud封装统一的异常处理
在 Spring Cloud 中,可以通过自定义异常处理器来封装统一的异常处理逻辑。异常处理器能够捕获并处理应用程序中的异常,然后返回适当的错误响应。以下是一个基于 Spring Cloud 的统一异常处理的示例
|
消息中间件 JSON JavaScript
SpringMVC 统一异常处理实战
SpringMVC 统一异常处理实战
|
安全 前端开发 Java
权限控制之异常处理方式三|学习笔记
快速学习权限控制之异常处理方式三
81 0
权限控制之异常处理方式三|学习笔记

热门文章

最新文章

  • 1
    流量控制系统,用正则表达式提取汉字
    27
  • 2
    Redis09-----List类型,有序,元素可以重复,插入和删除快,查询速度一般,一般保存一些有顺序的数据,如朋友圈点赞列表,评论列表等,LPUSH user 1 2 3可以一个一个推
    26
  • 3
    Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
    27
  • 4
    Redis07命令-String类型字符串,不管是哪种格式,底层都是字节数组形式存储的,最大空间不超过512m,SET添加,MSET批量添加,INCRBY age 2可以,MSET,INCRSETEX
    28
  • 5
    S外部函数可以访问函数内部的变量的闭包-闭包最简单的用不了,闭包是内层函数+外层函数的变量,简称为函数套函数,外部函数可以访问函数内部的变量,存在函数套函数
    24
  • 6
    Redis06-Redis常用的命令,模糊的搜索查询往往会对服务器产生很大的压力,MSET k1 v1 k2 v2 k3 v3 添加,DEL是删除的意思,EXISTS age 可以用来查询是否有存在1
    31
  • 7
    Redis05数据结构介绍,数据结构介绍,官方网站中看到
    22
  • 8
    JS字符串数据类型转换,字符串如何转成变量,+号只要有一个是字符串,就会把另外一个转成字符串,- * / 都会把数据转成数字类型,数字型控制台是蓝色,字符型控制台是黑色,
    20
  • 9
    JS数组操作---删除,arr.pop()方法从数组中删除最后一个元素,并返回该元素的值,arr.shift() 删除第一个值,arr.splice()方法,删除指定元素,arr.splice,从第一
    21
  • 10
    定义好变量,${age}模版字符串,对象可以放null,检验数据类型console.log(typeof str)
    19