目录
前言
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即可