前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >@RestControllerAdvice 统一异常处理

@RestControllerAdvice 统一异常处理

作者头像
一个风轻云淡
发布2022-11-15 16:57:19
8720
发布2022-11-15 16:57:19
举报
文章被收录于专栏:java学习java

是什么

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

怎么用

假设有枚举

代码语言:javascript
复制
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;
    }
}

 控制层

代码语言:javascript
复制
    /**
     * 保存
     */
    @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 ,就可以获取到校验结果 */

代码语言:javascript
复制
@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 解决

代码语言:javascript
复制
@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());
    }
}

控制层可以简化为 

代码语言:javascript
复制
    @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();


    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 是什么
  • 为什么要有这个注解
  • 怎么用
    • 假设有枚举
      •  控制层
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档