@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
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
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
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();
-
-
- }
