统一异常处理

927 阅读2分钟

问题:

为什么要统一异常处理:

软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半 以上的时间都是在处理各种异常情况,所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块,不仅有大量的冗余代码,而且还影响代码的可读性。

何时throw抛异常:

  1. dao层异常上抛-->service层上抛(只对RunTimeException异常期作用)-->controller层统一处理 (@ControllerAdvice)
  2. 默认我们需要service层的异常需要抛出
  3. servcie层被Spring管理,默认Spring事务回滚只对RunTimeException起作用,所以我们要把service层的编译器异常转换为运行时异常抛出。

何时try/cash捕捉异常:

  1. 只有这种异常不需要影响业务,或者通过这种异常可以执行其他业务,我们才需要try

  2. 否则统一抛出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;
   			}
}

==注意:枚举项必须写在最前面==

建议:通用异常类一般写在项目的共工模块中。

总结:

​ 方便管理、减少代码冗余、增强可读性。