问题:
为什么要统一异常处理:
软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半 以上的时间都是在处理各种异常情况,所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块,不仅有大量的冗余代码,而且还影响代码的可读性。
何时throw抛异常:
- dao层异常上抛-->service层上抛(只对RunTimeException异常期作用)-->controller层统一处理 (@ControllerAdvice)
- 默认我们需要service层的异常需要抛出
- servcie层被Spring管理,默认Spring的事务回滚只对RunTimeException起作用,所以我们要把service层的编译器异常转换为运行时异常抛出。
何时try/cash捕捉异常:
-
只有这种异常不需要影响业务,或者通过这种异常可以执行其他业务,我们才需要try
-
否则统一抛出throw
步骤:
1、自定义异常切面处理,统一拦截controller层的RunTimeException,进行统一处理
@ControllerAdvice public class BaseExceptionAdvice { @ExceptionHandler(LyException.class) public ResponseEntity<ExceptionResult> handlerLyException(LyException e) { return ResponseEntity.status(e.getStatus()).body(new ExceptionResult(e)); } }注解:
@ControllerAdvice
作用:拦截所有的以@Controller为注解的类,以及他们的子类
@ExceptionHandler
作用:配合@ControllerAdivce使用
2、自定义异常类,继承RuntimeException,可以自己录入状态码和异常信息:
public class LyException extends RuntimeException {
private int status;
public LyException(ExceptionEnum e){
super(e.getMessage());
this.status=e.getStatus();
}
3、自定义异常返回结果类:
public class ExceptionResult {
private int status;
private String message;
private String timestamp;
public ExceptionResult(LyException e) {
this.status = e.getStatus();
this.message = e.getMessage();
this.timestamp = DateTime.now().toString("yyyy-MM-dd HH:mm:ss");
}
}
4、使用枚举,将状态码和对应信息做好一一对应:
public enum ExceptionEnum {
USER_ADDRESS_NOT_FOUND(400,"找不到用户地址"),
PRICE_CANNOT_BE_NULL(400,"价格不能为空"),
//成员变量
private int status;
private String message;
//构造函数
ExceptionEnum(int status, String message) {
this.status = status;
this.message = message;
}
}
==注意:枚举项必须写在最前面==
建议:通用异常类一般写在项目的共工模块中。
总结:
方便管理、减少代码冗余、增强可读性。