首先介绍几个方法:能让我们更容易的理解下文
SpringMVC 统一异常处理有三种方式,分别是:
-
使用@ExceptionHandler注解
-
实现HandlerExceptionResolver接口
-
使用@controlleradvice注解
这里我就不介绍不常用的了,介绍一种比较实用的异常处理方式,通常以后工作也可以用到的
写之前需要导入SpringMVC包
User实体类的定义
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private String password;
private Integer id;
private String names;
}
第一步:编写自己的异常类
public class MyException extends RuntimeException{
private Integer code;
public MyException (Integer code,String message){
super(message); //调用了父类的方法,所以我们不需要重写getter和setter方法
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
第二步:编写响应数据实体类,并封装方法
这个实体类就是我们每次运行完方法之后返回给前端的数据对象,成功的时候返回编码为0,和data数据,异常的时候返回编码不为0,和错误信息message
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Resp {
//返回的异常码
private int code;
//返回的异常信息
private String message;
//返回的正常数据
private Object data;
//成功需要传的对象
public static Resp success(Object data){
Resp resp = new Resp();
resp.setData(data);
return resp;
}
//异常时需要传的对象
public static Resp error(int code,String message){
Resp resp = new Resp();
resp.setCode(code);
resp.setMessage(message);
return resp;
}
}
第三步:编写控制类Controller类
在这里我使用了特殊的方式:字符串,其他对象照样可以转化的
@GetMapping("/s")
public String select(){
return "你好";
}
第四步:编写处理异常类
简化来说就是:当我们运行时发生异常都会走到这里
@RestControllerAdvice
//异常处理
//实现ResponseBodyAdvice<Object>,主要是为了给Controller类中的方法实现增强
public class MyRestException implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
//true就是执行下面的beforeBodyWrite方法,false就是不执行下面的beforeBodyWrite方法
return true;
}
@Override
//Object o 就是Controller执行成功后返回的对象,也就是需要返回的数据data
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//由于失败的时候也会走到这里,失败的相应对象已经被下面转成了json数据,又被系统当成了data数据,又包装了一次,所以判断是否是Resp类型,是的话直接返回
if (o instanceof Resp){
return o;
}
//既然控制成功的时候走到这里,我们可以在这里给控制器方法,增强,相当于切面
Resp success = Resp.success(o);
//由于String类型走过来的时候,也是被当作了Object,放入了Resp.success方法中,被封装成了json类型,而StringStringHttpMessageConverter只能处理String
if (aClass == StringHttpMessageConverter.class){
//我们自己判断如果为String类型的json转换器,就自己处理
//利用了hutool工具类,JSONUtil.toJsonStr可以将任意对象(Bean、Map、集合等)直接转换为JSON字符串
return JSONUtil.toJsonStr(success);
}else {
return success;
}
}
@ExceptionHandler(Exception.class)
public Object error(Exception e){
int code = 999;
//由于出错后就跑到这里了,而且是指定的异常,所以我们可以将Exception强转为我们指定的异常,方便取数据
if (e instanceof MyException) {
MyException ex = (MyException) e;
code = ex.getCode();
}
return Resp.error(code,e.getMessage());
}