Springboot全局异常处理
- 一、不使用全局异常处理器
- 二、全局异常处理器
- 1.自定义常量(返回状态码)
- 2.手动抛出异常
- 3.编写全局异常处理器
- 4.测试结果
- 三、全局异常处理方式二
- 1.定义状态码常量
- 2. 定义基础接口(面向接口编程)
- 3.定义枚举类
- 4.自定义数据传输对象
- 5.定义全局异常处理器
- 6.测试1
- 7.测试2
- 四、值得参考的博客
为什么使用全局异常?
- 在开发过程中,不管是
Dao、Servie、Controller
,层都有可能发生异常,对于异常处理,通常是try-catch
或者直接throw
,这会让try-catch
的代码在代码中任意出现,系统的代码耦合度高,代码不美观,统一异常处理可以美化代码。
如何使用全局异常?
- 在后端处理请求过程中发生了异常,
DispatcherServlet
将异常处理委托给异常处理器(处理异常的类)。实现HandlerExceptionResolver
接口的都是异常处理类。 - 项目的异常一般集中处理,定义全局异常处理器。再结合框架提供的注解,诸如:
@ExceptionHandler
,@ControllerAdvice
或@RestControllerAdvice
一起完成异常的处理。注意: 一定要和Controller中的注解(@Controller 和 RestController)保持一致性。 @ControllerAdvice
与@RestControllerAdvice
区别在于:@RestControllerAdvice
加了@RepsonseBody
。
一、不使用全局异常处理器
-
① 编写控制器相关的代码,模拟出现了空指针异常。
NullPointerException
@RestController public class Controller {@GetMapping("/divide")public String divide(){String str = null;str.toString();return "success";} }
-
② 发送请求返回结果查看。
二、全局异常处理器
- SpringBoot中,
@ControllerAdvice 或 @RestControllerAdvice
即可开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler
注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。
1.自定义常量(返回状态码)
/*** 返回状态码的常量**/
public class StatusCodeConstant {public static final Integer ERROR = 500; //服务器非法错误
}
2.手动抛出异常
@RestController
public class Controller {@GetMapping("/divide")public String divide(){String str = null;str.toString();return "success";}
}
3.编写全局异常处理器
/*** 处理空指针的异常*/@ExceptionHandler(NullPointerException.class)@ResponseBodypublic String exceptionHandler(NullPointerException e){return "<h1>服务器出现错误,请联系管理员 ====> " + e.getMessage() + "</h1>";}
4.测试结果
- 建议在参数签名中尽可能具体异常类,以减少异常类型和原因异常之间不匹配的问题,考虑创建多个
@ExceptionHandler
方法的,每个方法通过其签名匹配单个特定的异常类型。最后增加一个根异常,考虑没有匹配的其他情况。
三、全局异常处理方式二
1.定义状态码常量
public class StatusCodeConstant {public static final Integer SUCCESS = 200; //返回状态正常public static final Integer ERROR = 0; //返回错误
}
2. 定义基础接口(面向接口编程)
/*** 响应信息的基础接口**/
public interface ResponseResultBaseInfo {/*** 错误码*/Integer getResultCode();/*** 错误描述*/String getResultMsg();
}
3.定义枚举类
/*** 异常处理枚举类*/
public enum ResponseEnum implements ResponseResultBaseInfo{// 数据操作错误定义SUCCESS(200, "success"),ERROR(500,"error");/*** 错误码*/private final Integer resultCode;/*** 错误描述*/private final String resultMsg;ResponseEnum(Integer resultCode, String resultMsg) {this.resultCode = resultCode;this.resultMsg = resultMsg;}@Overridepublic Integer getResultCode() {return resultCode;}@Overridepublic String getResultMsg() {return resultMsg;}
}
4.自定义数据传输对象
/*** 自定义数据传输对象*/
@Data
public class ResponseResult {/*** 响应代码*/private Integer code;/*** 响应消息*/private String message;/*** 响应结果*/private Object result;public ResponseResult(){}public ResponseResult(ResponseResultBaseInfo res) {this.code = res.getResultCode();this.message = res.getResultMsg();}/*** 成功*/public static ResponseResult success() {return success(null);}/*** 成功*/public static ResponseResult success(Object data) {ResponseResult responseResult = new ResponseResult();responseResult.setCode(ResponseEnum.SUCCESS.getResultCode());responseResult.setMessage(ResponseEnum.SUCCESS.getResultMsg());responseResult.setResult(data);return responseResult;}/*** 失败*/public static ResponseResult error(ResponseResultBaseInfo res) {ResponseResult responseResult = new ResponseResult();responseResult.setCode(res.getResultCode());responseResult.setMessage(res.getResultMsg());responseResult.setResult(null);return responseResult;}/*** 失败*/public static ResponseResult error(Integer code, String message) {ResponseResult responseResult = new ResponseResult();responseResult.setCode(code);responseResult.setMessage(message);responseResult.setResult(null);return responseResult;}/*** 失败*/public static ResponseResult error(String message) {ResponseResult responseResult = new ResponseResult();responseResult.setCode(StatusCodeConstant.ERROR);responseResult.setMessage(message);responseResult.setResult(null);return responseResult;}}
5.定义全局异常处理器
/*** 全局异常处理器**/
@RestControllerAdvice
public class ExceptionHandlerConfig {@ExceptionHandler(NullPointerException.class)public ResponseResult nullPointException(NullPointerException e) {return ResponseResult.error(e.getMessage());}@ExceptionHandler(Exception.class)public ResponseResult exception() {return ResponseResult.error(ResponseEnum.ERROR);}
}
6.测试1
@GetMapping("/latest")public ResponseResult getSensorDataLatest() {return ResponseResult.success("数据传输成功");}
7.测试2
@GetMapping("/latest")public ResponseResult getSensorDataLatest() {int a = 1;if(a == 1)throw new ArithmeticException();return ResponseResult.success("数据传输成功");}
四、值得参考的博客
- Spring Boot项目优雅的全局异常处理方式(全网最新)
- Spring的@ExceptionHandler注解使用方法
- SpringBoot全局异常处理(优缺点)以及统一返回对象、错误码按业务模块设计示例,序列化后与数据库数据时间差8小时