Spring Boot框架-使用自建 Exception 实现异常处理

我们希望能在Postman中返回操作的异常或信息
在domain package中新建Result class

    public class Result {
        private Integer code;
        private String msg;
        private T data;//将data设定为泛型,用来存储返回的具体信息

        public Integer getCode() {return code;}

        public void setCode(Integer code) {this.code = code;}

        public String getMsg() {return msg;}

        public void setMsg(String msg) {this.msg = msg;}

        public T getData() {return data;}

        public void setData(T data) {this.data = data;}
    }

用Result来固定返回的信息,就返回code,msg,data三个信息
在控制器添加对Result的使用

    /**
     * 添加一个女生
     * @return
     */
    @PostMapping(value = "/girls")
    public Result girlAdd(@Valid Gril girl, BindingResult bindingResult){//Result存储信息数据
        if(bindingResult.hasErrors()){
            Result result = new Result();
            result.setCode(1);//随便设定
            result.setMsg(bindingResult.getFieldError().getDefaultMessage());
            result.setData("出错了0");
            return result;
        }
        girl.setCupSize(girl.getCupSzie());
        girl.setAge(girl.getAge());
        Result result = new Result();
        result.setCode(0);
        result.setMsg("成功了!");
        result.setData(girlRepository.save(girl));
        return result;
    }

返回信息:
{
    "code": 0,
    "msg": "成功了!",
    "data": {
        "id": 11,
        "age": 18,
        "cupSzie": "B"
    }
}
或者
{
    "code": 1,
    "msg": "未成年禁止入内",
    "data": "出错了0"
}

整合一下重复代码:新建一个Utils Package,建一个 ResultUtil class

public class ResultUtil {
    public static Result success(Object object){
        Result result = new Result();
        result.setCode(0);
        result.setMsg("成功!");
        result.setData(object);

        return result;
    }
    public static Result success(){
        return success(null);
    }
    public static Result error(Integer code,String msg){
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);

        return result;
    }
}

通过调用类来输出信息

    /**
     * 添加一个女生
     * @return
     */
    @PostMapping(value = "/girls")
    public Result girlAdd(@Valid Gril girl, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            //调用 ResultUtil 
            return ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
        }

        girl.setCupSize(girl.getCupSzie());
        girl.setAge(girl.getAge());
        //调用 ResultUtil 
        return ResultUtil.success(girlRepository.save(girl));
    }

我们通过这个信息返回,可以反馈给我们信息提示,比如根据提交的年龄反馈学籍
先建一个服务类

@Service
public class GirlService {

    @Autowired
    private GirlRepository girlRepository;//查询的接口
    @Autowired
    private GirlService girlService;//调用服务类

    public void getAge(Integer id){
       Gril gril = girlRepository.findById(id).get();
       Integer age = gril.getAge();
       if(age<10){
           //返回“你可能上小学”
       }else if (age>10&&age<16){
           //返回“你可能在上初中”
       }
    }
}

通过服务类来控制逻辑的判断
再在控制器新建一个判断年龄的方法

    @GetMapping(value = "/age")
    public void getAge(@PathVariable("id") Integer id){
        girlService.getAge(id);
    }

但是这样判断的方式太低效,我们通过抛异常的方式来解决

    public void getAge(Integer id) throws Exception{//抛出异常
       Gril gril = girlRepository.findById(id).get();
       Integer age = gril.getAge();
       if(age<10){
           //返回“你孩子啊上小学”
           throw new Exception("你就是个小屁孩");
       }else if (age>10&&age<16){
           //返回“你可能在上初中”
           throw new Exception("你就是个小姑娘");
       }
    }

在控制器中继续抛出异常

    @GetMapping(value = "/age")
    public void getAge(@PathVariable("id") Integer id) throws Exception{
        girlService.getAge(id);
    }

就可以收集到如下的异常

{
    "timestamp": "2018-06-23T06:56:59.466+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "你就是个小屁孩",
    "path": "/girls/getAge/1"
}

那我们要拦截异常信息并且对信息进行封装,建 handle 包,建 ExceptionHandle 类

    @ControllerAdvice
    public class ExceptionHandle {

        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public Result handle(Exception e){
            return ResultUtil.error(100,e.getMessage());
        }
    }

这样就可以实现只输出 Message 但是我们要想输出多个值怎么办? Exception 只能输出 e呀?我们自己写一个抛出类

Package excption -> Class GrilExcption

    public class GirlException extends RuntimeException {
        private Integer code;
        public GirlException(Integer code,String message) {
            super(message.toString());
            this.code = code;
        }
        public Integer getCode() {
            return code;
        }
        public void setCode(Integer code) {
            this.code = code;
        }
    }

GrilExcption类可以传进一个code参数(用来简易标记异常)和一个message参数(用来显示异常内容)我们在拦截异常信息的class ExceptionHandle中使用它

    @ExceptionHandler(value = Exception.class)//拦截异常信息
    @ResponseBody
    public Result handle(Exception e){
        if(e instanceof GirlException){//判断异常是否由自己定义
            GirlException girlException = (GirlException)e;//转换异常格式
            return ResultUtil.error(girlException.getCode(),girlException.getMessage());//完成信息的发送
        }else {
            return ResultUtil.error(-1,"未知错误");
        }
    }

那我们打出未知错误怎么知道出什么错了?拿就来做一个日志吧

    @ControllerAdvice
    public class ExceptionHandle {
        private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);

        @ExceptionHandler(value = Exception.class)//拦截异常信息
        @ResponseBody
        public Result handle(Exception e){
            if(e instanceof GirlException){//判断异常是否由自己定义
                GirlException girlException = (GirlException)e;//转换异常格式
                return ResultUtil.error(girlException.getCode(),girlException.getMessage());//完成信息的发送
            }else {
                logger.error("【系统异常】{}",e);//打印异常信息
                return ResultUtil.error(-1,"未知错误");
            }
        }
    }

其实我们可以将GrilExcption类中的参数统一起来,利用枚举类型

Package enums -> Class ResultEnum
    public enum ResultEnum {

        //建立一些枚举,替代参数
        UNKNOWN_ERROR(-1,"未知错误"),
        SUCCESS(0,"成功"),
        PRIMARY_SCHOOL(100,"你可能还在小学"),
        MIODLE_SCHOOL(101,"你可能还在上初中");

        private Integer code;

        private String msg;

        ResultEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public Integer getCode() {return code;}

        public String getMsg() {return msg;}
    }

然后我们就可以修改getAge方法的参数

    public void getAge(Integer id) throws Exception{
        Gril girl = grilRepository.findById(id).get();
        Integer age = girl.getAge();
        if (age < 10) {
            //返回"你还在上小学吧" code=100
            throw new GirlException(ResultEnum.PRIMARY_SCHOOL);//替换成了枚举类型
        }else if (age > 10 && age < 16) {
            //返回"你可能在上初中" code=101
            throw new GirlException(ResultEnum.MIODLE_SCHOOL);
        }
    }
别忘了我们把枚举值转给GrilExcption类后要修改实参
    public GirlException(ResultEnum resultEnum) {
        super(resultEnum.getMsg());
        this.code = resultEnum.getCode();
    }
然后负责封装异常信息的ExceptionHandle类就可以获取GrilExcption的信息输出啦

你可能感兴趣的:(Spring,Boot,框架)