暑期微基础学java的2天。

项目异常处理方案

基于昨天的基础框架,思考在连接前端时,数据传输格式应该以一个什么样的统一标准,使得后端的增删改查以一种相同的格式传给前端,前端统一接收。

设置统一返回结果类 用data来储存查询到的数据,code来储存成功或者失败的状态,用msg来给前端带去查询后的相关信息:

public class Result {
    private Object data;
    private Integer code;
    private String msg;
}

开始基于昨天的框架增加数据分装类 Result,添加get,set方法,并且创建两个带参构造(一个为带消息的,一个为不带消息)和一个无参构造方法:

public class Result {
    private Object data;
    private Integer code;
    private String msg;

    public Result() {
    }

    public Result(Integer code,Object data,String msg ) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public Result( Integer code,Object data) {
        this.data = data;
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.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;
    }
}

创建完成后再创建状态代码值 Code类,分别定义了增删改查的成功与失败的代码值:

public class Code {
    public static final Integer SAVE_OK = 20011;  //保存成功
    public static final Integer DELETE_OK = 20021; //删除成功
    public static final Integer UPDATE_OK = 20031; //更新成功
    public static final Integer GET_OK = 20041;  //查询成功

    public static final Integer SAVE_ERR = 20010;  //保存失败
    public static final Integer DELETE_ERR = 20020; //删除失败
    public static final Integer UPDATE_ERR = 20030; //更新失败
    public static final Integer GET_ERR = 20040;  //查询失败
}

将这些做好后,返回Contorller层,在之前定义的方法里,改变返回值为Result对象,并且在获得成功失败的时候用三元表达式来判断成功失败,将值传入Result对象并返回该对象。

eg:

@PostMapping
    public Result save(@RequestBody Book book) {
        boolean flag = bookService.save(book);

        return new Result(flag? Code.SAVE_OK:Code.SAVE_ERR,flag);
    }

异常处理器(上面我们已经解决了后端返回数据给前端的数据统一格式,但是当数据获取报错的时候,前端在接收时,就会接收到一大堆报错的代码,使得前端获取数据出错,我们要怎样解决报错后的数据传递呢?)

出现异常现象的常见位置与常见诱因如下(黑马视频内复制的):

  • 框架内部抛出的异常:因使用不合规导效
  • 数据层抛出的异常: 因外部服务器故障导致(例如: 服务器访问超时)
  • 业务层抛出的异常: 因业务逻辑书写错误导致(例如: 遍历业务书写操作,导致索引异常等)
  • 表现层抛出的异常:因数据收集、校验等规则导致(例如: 不匹配的数据类型间导致异常)
  • 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)

思考:报错会在不同的逻辑层抛出,我们应该怎么样来将报错进行统一处理,可以将报错都往上抛,统一到表现层(Controller层)进行处理并且使用AOP思想,这样就能处理不同的异常,而不用每个异常使用一次Try catch 大大减少了代码量使用,异常处理器(Spring MVC 已经帮我们想到了如何分类的使用AOP思想处理异常)来处理异常  创建ProjectExceptionAdvice.java 用来创建异常处理器 并定义doException来接收所有异常 :

@RestControllerAdvice  //声明这个类是用来做异常处理的
public class ProjectExceptionAdvice {

    @ExceptionHandler(Exception.class) //异常处理标志(拦截异常)
    public Result doException(Exception ex){
        System.out.println("抓到你了..");
        return new Result(66,null);
    }
}

在Controller层中添加完异常处理器类后,测试异常是否成功被接收,在Controller层中的getById方法中添加一个除以0报错,在调用该方法看看控制台是否显示抓到你了..(显示抓到你了..就表明异常处理器成功处理异常):

 以上的处理异常只是在Controller层出现的异常我们进行处理,但是其他层出现异常又该怎么办呢?学习黑马给的项目异常处理方案:

1.业务异常 (BusinessException):

  • 发送对应消息传递给用户,提醒规范操作

2.系统异常 (SystemException)

  • 发送固定消息传递给用户,安抚用户
  • 发送特定消息给运维人员,提醒维护
  • 记录日志

3.其他异常 (Exception)

  • 发送固定消息传递给用户,安抚用户
  • 发送特定消息给编程人员,提醒维护 (纳入预期范围内)
  • 记录日志

在根目录在创建exception文件夹,在里面创建两个异常类,使得在出现该异常的时候i能够以统一的格式去接收数据。

BusinessException.java:

public class BusinessException extends RuntimeException{
    private Integer code;


    public Integer getCode() {
        return code;
    }

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

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException( Integer code,String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }
}

SystemException.java:

public class SystemException extends RuntimeException {  //运行时异常
    private Integer code;


    public Integer getCode() {
        return code;
    }

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

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException( Integer code,String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

}

我们根据不同异常可以将异常分为3大类写入ProjectExceptionAdvice.java内。

@RestControllerAdvice  //声明这个类是用来做异常处理的
public class ProjectExceptionAdvice {
    @ExceptionHandler(SystemException.class) //异常处理标志(拦截异常)
    public Result doSystemException(SystemException ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发人员
        return  new Result(ex.getCode(),ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class) //异常处理标志(拦截异常)
    public Result doBusinessException(BusinessException ex){

        return  new Result(ex.getCode(),null,ex.getMessage());
    }


    @ExceptionHandler(Exception.class) //异常处理标志(拦截异常)
    public Result doException(Exception ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发人员
        System.out.println("抓到你了..");
        return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后重试!");
    }
}

再在Code类中添加三个异常处理的代码:

 public static final Integer SYSTEM_ERR = 50001;  //系统错误
    public static final Integer BUSINESS_ERR = 50002;  //业务错误
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;  //业务错误

测试:(我们在Service层的实现类中测试是否能够成功接收到异常并处理)在getById方法中人为的添加两个异常:

@Override
    public Book getById(Integer id) {
        if (id == -1){
            throw new BusinessException(Code.BUSINESS_ERR,"输入的数据有误,请重新输入正确的数据");
        }

        //将可能出现的异常进行打包,转换成自定义异常
        try{
            int i = 1/0;
        }catch (Exception e){
            throw  new SystemException(Code.SYSTEM_ERR,"服务器访问超时,请重试1!",e);
        }

        Book book = bookDao.getById(id);
        return book;
    }

在Postman中测试:

 

 测试完成发现成功的接收了两个异常,并且将返回值进行统一的格式处理,这样在报错的时候前端也能接收到统一的数据。

总结:

今天学的异常处理,能够让后端发给前端的数据统一,有着一种统一的格式,这样能使得前端看得懂后端发送的数据,可以根据返回的数据进行对应的处理,在之前的项目中就没有这样的约束,使得前端接收到的数据五花八门。通过今天的学习可以让我更加明白前后端的数据交互以及返回数据的格式问题。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值