使用枚举类优雅完成全局异常处理

437 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

基本概念

枚举是Java中的一种特殊的类,使用关键字enum来定义,用法与定义类(class)基本一样.

举例:

package com.zy.common.exception;

public enum CommonEnumException implements CommonExceptionWrapper {
    // 实例对象
    UN_AUTHORIZE(401),
    LOGIN_ERROR(500);

    // 属性
    final Integer code;

    // 构造方法
    private CommonEnumException(Integer code) {
        this.code = code;
    }
}

注意其中的实例对象,这就是枚举类的特点.

枚举类最主要的特点就是定义一些不变的对象,即常量.

本质与不同

枚举类的本质其实是继承了java.util.Enum类

所有的枚举类都是继承自Enum类.

枚举类与普通类的不同:

  1. 不能继承其他类,也不能被其他类继承

应用

使用枚举类可以将某一类相同的常量对象抽象到一个枚举类里,方便创建和管理.

在实际开发中,通常将自定义异常使用枚举类来定义.

定义自定义异常类

package com.zy.common.exception;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * @Author: Zy
 * @Date: 2023/1/5 19:14
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class CommonException extends RuntimeException{

    private Integer code;
    private String message;

    public CommonException(){}
    public CommonException(String msg){
        super(msg);
    }

    public CommonException(CommonExceptionWrapper commonExceptionWrapper){
        CommonEnumException var1 = (CommonEnumException) commonExceptionWrapper;
        this.code = var1.code;
        this.message = "未知异常,请联系管理员";
    }

    public CommonException(CommonExceptionWrapper commonExceptionWrapper, String msg){
        CommonEnumException var1 = (CommonEnumException) commonExceptionWrapper;
        this.code = var1.code;
        this.message = msg;
    }

    public static CommonException runtimeException(){
        return new CommonException();
    }
}

继承RuntimeException,表明这是一个自定义的运行时异常类.

定义异常接口

package com.zy.common.exception;

/**
 * @Author: Zy
 * @Date: 2023/1/31 15:31
 */
public interface CommonExceptionWrapper {
    default CommonException runtimeException(String msg){
        return new CommonException(this,msg);
    }
    
    default CommonException runtimeException(){
        return new CommonException(this);
    }
}

枚举类不能继承,但是可以实现接口,可以通过接口的方式来使枚举类拥有一些共同的方法.

方法的作用是返回自定义的运行时异常.

定义异常枚举类

package com.zy.common.exception;

/**
 * @Author: Zy
 * @Date: 2023/1/31 15:24
 */
public enum CommonEnumException implements CommonExceptionWrapper {
    UN_AUTHORIZE(401),

    LOGIN_ERROR(500);

    CommonEnumException(Integer code) {
        this.code = code;
    }

    final Integer code;

}

使用枚举类定义异常实例,只有一个参数,为异常码

如上,定义了两个异常实例常量: UN_AUTHORIZE/LOGIN_ERROR

使用

try {
    subject.login(usernamePasswordToken);
}catch (AuthenticationException e){
    throw CommonEnumException.LOGIN_ERROR.runtimeException("用户名或密码错误");
}

直接抛出自定义异常即可.

全局异常拦截

package com.zy.common.advice;

import com.zy.common.exception.CommonException;
import com.zy.common.model.response.ResponseResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: Zy
 * @Date: 2023/1/3 11:18
 */
@RestControllerAdvice
public class ExceptionHandlerAdvice {

    @ExceptionHandler(CommonException.class)
    public ResponseResult handleException(CommonException e) {
        e.printStackTrace();
        return ResponseResult.error(e.getCode(),e.getMessage());
    }
}

在全局异常拦截里,就可以针对自定义的CommonException进行拦截,同时获取我们枚举类中异常实例的异常码.

总结

在开发过程中,必然会用到常量,之前定义常量都是通过构建常量类,再使用

public static final CommonException common = new CommonException();

这种方式来构建常量类,不够优雅,通过枚举类的方式可以更加优雅的开发代码.