全局异常处理解决方案

目录

修改代码

异常处理流程图

编写自定义异常类

异常处理类

处理不可预知异常


前言

spring mvc 异常处理(必看) 

https://blog.csdn.net/yzj17025693/article/details/89287308#异常处理器

spring boot写spring mvc的异常处理器(必看) 

https://blog.csdn.net/yzj17025693/article/details/90601997#spring%20boot定义spring%20mvc异常处理器

java se的异常基础(必看)

https://blog.csdn.net/yzj17025693/article/details/82725884

spring aop的异常通知(了解)  https://blog.csdn.net/yzj17025693/article/details/88696551#异常通知

注意 

@ControllerAdvice只是拦截在controller发送的的异常

修改代码

以添加操作为例

这是service层的添加数据代码,添加前需要判断数据库里是否已经有对应的内容

如果有,就提交失败

但是如果箭头所指的对象为空,当getPageName的时候就会报异常

修改后的代码

先处理异常,处理完之后,再进行正常的保存返回操作

异常处理流程图

可预知的异常,就和上面的add方法一样,知道可能哪里会出错,那个可以自定义异常抛出并由异常处理类

编写自定义异常类

自定义异常里继承RuntimeException

需要注意的是ResultCode是一个接口,所有的枚举类都实现这个接口

ResultCode的形式,只有3个方法,继续往下看

增加方法判断的时候直接加上错误代码抛出

这里的CommonCode是一个枚举类,里面有很多异常的常量,枚举类传递数值,类是与传递枚举对象

所以对应的,CustomerException的构造参数是ResultCode

肯定这个枚举类肯定也要要实现ResultCode,这样才能构成多态

写一个工具类优化,抛出异常的代码

CommonCode

既然实现了ResultCode,那么也就需要实现它的方法,枚举是比较特殊的,这里用的是private修饰枚举构造函数(具体看基础部分)

枚举值的书写要和构造函数对应,所以就成了下面的形式

@ToString
public enum CommonCode implements ResultCode{
    INVALID_PARAM(false,10003,"非法参数!"),
    SUCCESS(true,10000,"操作成功!"),
    FAIL(false,11111,"操作失败!");

    //操作是否成功
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;
    private CommonCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return success;
    }
    @Override
    public int code() {
        return code;
    }
    @Override
    public String message() {
        return message;
    }
}

异常处理类

上面只是我们自定义的异常,但是异常还需要处理

这里就可以参考spring boot+spring mvc 异常处理

记得在spring boot启动类上扫描我们的处理异常的包

这样可以把错误代码返回给客户,而不用繁琐的写 return new xxxxx(false,code);

并且可以传递精确的错误信息,比如哪里哪里出错了

捕获异常后获取异常的代码,然后封装进ResponseResult类里

ResponseResult

用于返回给客户的类,里面定义了操作的状态,默认操作成功

@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response
{
    //操作是否成功
    boolean success=SUCCESS;

    //操作代码
    int code=SUCCESS_CODE;

    //提示信息
    String message;

    public ResponseResult(ResultCode resultCode)
    {
        this.success=resultCode.success();
        this.code=resultCode.code();
        this.message=resultCode.message();
    }
}

response

是我们自己定义的顶级接口,用于定义成功的状态和状态码

public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}

一般异常了还需要记录日志

以及加上@ReponseBody注解,因为信息需要转换成json返回回去

创建另外一个Code枚举,专门用来管理某个模块的异常,而CommondCode就是全局的异常,表示通用的异常

因为实现了ResultCode接口,所以这里是需要实现接口里的方法的,返回对应的状态

抛出异常的标准形式

处理不可预知异常

从上面异常处理流程图可以知道,不可预知异常,通常是我们将一些常用的异常放入map

一些突发的异常可以用9999代替,表示位置错误

下面这个参数在post请求中,没有写参数的时候会报

先定义一个自定义的枚举类型

immutableMap (immutable不可变的) 是google开发的一个工具类,数据一旦存进去,便不可变,且是线程安全的

<Class<? extends Throwablre>>也就是代表所有Throwablre的子类都能存入

<? super T>是下界通配符,表示只能存入T或T的父类

但是它需要使用immutableMap来构建它自身,但是此时还不算build成功,只是获取了一个builder

写一个捕获不可预知异常的方法,和可预知异常放在同一个类也可以

判断EXCEPTIONS如果等于空,也就是代表builder还没有使用build方法构建immutableMap,需要构建

 下面就是从我们的静态代码块根据异常类,取出对应的代码即可

写一个静态代码块,用于把常用的异常放入进去

我们在自己的工程下面也可以定义一个异常,继承ExceptionCatch即可

发布了143 篇原创文章 · 获赞 36 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/yzj17025693/article/details/90722301
今日推荐