java异常封装(ELADMIN代码解读)

JAVA异常封装

异常实体

@Data
class ApiError {
    private Integer status;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime timestamp;
    private String message;

    private ApiError() {
        timestamp = LocalDateTime.now();
    }

    public ApiError(Integer status,String message) {
        this();
        this.status = status;
        this.message = message;
    }
}

上面的代码是一个Java类,定义了一个名为 ApiError 的数据类 (Data Class)。解读这段代码:

  1. 类声明: class ApiError 是一个类的声明。

  2. 字段:

    • private Integer status: 一个私有的整数字段,用于表示错误的状态码。
    • @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime timestamp: 一个私有的 LocalDateTime 类型的字段,用于表示错误发生的时间戳,并使用 @JsonFormat 注解指定了时间戳的格式为 "yyyy-MM-dd HH:mm:ss"。
    • private String message: 一个私有的字符串字段,用于存储错误消息。
  3. 构造方法:

    • private ApiError(): 私有的无参构造方法,用于在对象创建时初始化 timestamp 字段为当前时间。
    • public ApiError(Integer status, String message): 公共的构造方法,接受状态码和错误消息作为参数,并调用无参构造方法初始化时间戳。
  4. 初始化: 在无参构造方法中,通过调用 LocalDateTime.now() 初始化了时间戳字段。

总体来说,这个类的目的是表示一个 API 错误,包含了状态码、错误消息和发生错误的时间戳。@JsonFormat 注解表明,在将对象转换为 JSON 格式时,时间戳应该按指定的格式进行格式化。

自定义异常

1、通用异常

封装了 BadRequestException,用于处理通用的异常

@Getter
public class BadRequestException extends RuntimeException{

    private Integer status = BAD_REQUEST.value();

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

    public BadRequestException(HttpStatus status,String msg){
        super(msg);
        this.status = status.value();
    }
}

上面的代码是一个 Java 类,定义了一个名为 BadRequestException 的异常类。解读这段代码:

  1. 注解: @Getter 注解表示使用 Lombok 库自动生成 getter 方法。

  2. 类声明: public class BadRequestException extends RuntimeException 表示 BadRequestException 类继承自 RuntimeException,即它是一个运行时异常类。

  3. 字段:

    • private Integer status = BAD_REQUEST.value(): 一个私有的整数字段,用于表示错误的状态码。它被初始化为 HTTP 400(Bad Request)的状态码,使用了常量 BAD_REQUESTvalue() 方法。
  4. 构造方法:

    • public BadRequestException(String msg): 公共的构造方法,接受错误消息作为参数,并调用父类 RuntimeException 的构造方法,将错误消息传递给父类。
    • public BadRequestException(HttpStatus status, String msg): 公共的构造方法,接受 HttpStatus 和错误消息作为参数。它调用父类 RuntimeException 的构造方法,并通过参数设置了状态码 status

总体来说,这个异常类用于表示客户端发起的请求存在问题,其中包括了错误消息和状态码。使用 Lombok 的 @Getter 注解自动生成了 getter 方法。

2、实体相关异常

(1) 实体不存在: EntityNotFoundException

import org.springframework.util.StringUtils;


public class EntityNotFoundException extends RuntimeException {

    public EntityNotFoundException(Class clazz, String field, String val) {
        super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
    }

    private static String generateMessage(String entity, String field, String val) {
        return StringUtils.capitalize(entity)
                + " with " + field + " "+ val + " does not exist";
    }
}

上面的代码是一个 Java 类,定义了一个名为 EntityNotFoundException 的异常类。解读这段代码:

  1. 导入语句: 代码中导入了 org.springframework.util.StringUtils 类,该类提供了一些字符串处理的实用方法。

  2. 类声明: public class EntityNotFoundException extends RuntimeException 表示 EntityNotFoundException 类继承自 RuntimeException,即它是一个运行时异常类。

  3. 构造方法:

    • public EntityNotFoundException(Class clazz, String field, String val): 公共的构造方法,接受三个参数:Class clazz 表示实体的类,String field 表示字段名,String val 表示字段值。在构造方法中,调用了父类 RuntimeException 的构造方法,并传递了由静态方法 generateMessage 生成的错误消息。
  4. 静态方法:

    • private static String generateMessage(String entity, String field, String val): 一个私有的静态方法,用于生成错误消息。该方法接受实体名称 entity、字段名 field 和字段值 val 作为参数,并返回一个格式化后的错误消息。在这里,使用了 StringUtils.capitalize(entity) 将实体名称首字母大写,然后拼接了其他信息,形成最终的错误消息。

总体来说,这个异常类用于表示在查找实体时未找到相应的记录,提供了一个带有实体类、字段名和字段值的构造方法,并通过静态方法生成友好的错误消息。

(2) 实体已存在:EntityExistException

import org.springframework.util.StringUtils;


public class EntityExistException extends RuntimeException {

    public EntityExistException(Class clazz, String field, String val) {
        super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
    }

    private static String generateMessage(String entity, String field, String val) {
        return StringUtils.capitalize(entity)
                + " with " + field + " "+ val + " existed";
    }
}

上面的代码是一个 Java 类,定义了一个名为 EntityExistException 的异常类。解读这段代码:

  1. 导入语句: 代码中导入了 org.springframework.util.StringUtils 类,该类提供了一些字符串处理的实用方法。

  2. 类声明: public class EntityExistException extends RuntimeException 表示 EntityExistException 类继承自 RuntimeException,即它是一个运行时异常类。

  3. 构造方法:

    • public EntityExistException(Class clazz, String field, String val): 公共的构造方法,接受三个参数:Class clazz 表示实体的类,String field 表示字段名,String val 表示字段值。在构造方法中,调用了父类 RuntimeException 的构造方法,并传递了由静态方法 generateMessage 生成的错误消息。
  4. 静态方法:

    • private static String generateMessage(String entity, String field, String val): 一个私有的静态方法,用于生成错误消息。该方法接受实体名称 entity、字段名 field 和字段值 val 作为参数,并返回一个格式化后的错误消息。在这里,使用了 StringUtils.capitalize(entity) 将实体名称首字母大写,然后拼接了其他信息,形成最终的错误消息。

总体来说,这个异常类用于表示在尝试创建或保存实体时,已经存在具有相同字段值的记录。它提供了一个带有实体类、字段名和字段值的构造方法,并通过静态方法生成友好的错误消息。

使用场景,删除用户的时候是根据ID删除的,可判断ID是否存在,抛出异常

新增用户的时候用户名是唯一的,可判断用户是否存在,抛出异常

全局异常拦截

使用全局异常处理器 @RestControllerAdvice 处理请求发送的异常

  • @RestControllerAdvice:默认会扫描指定包中所有@RequestMapping注解

  • @ExceptionHandler:通过@ExceptionHandler的 value 属性可过滤拦截的条件

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理所有不可知的异常
     * @param e
     * @return
     */
    @ExceptionHandler(Throwable.class)
    public ResponseEntity handleException(Throwable e){
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
        return buildResponseEntity(apiError);
    }
    /**
     * 处理自定义异常
     * @param e
     * @return
     */
	@ExceptionHandler(value = BadRequestException.class)
	public ResponseEntity badRequestException(BadRequestException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ApiError apiError = new ApiError(e.getStatus(),e.getMessage());
        return buildResponseEntity(apiError);
	}

    /**
     * 处理 EntityExist
     * @param e
     * @return
     */
    @ExceptionHandler(value = EntityExistException.class)
    public ResponseEntity entityExistException(EntityExistException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
        return buildResponseEntity(apiError);
    }

    /**
     * 处理 EntityNotFound
     * @param e
     * @return
     */
    @ExceptionHandler(value = EntityNotFoundException.class)
    public ResponseEntity entityNotFoundException(EntityNotFoundException e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
        ApiError apiError = new ApiError(NOT_FOUND.value(),e.getMessage());
        return buildResponseEntity(apiError);
    }
    /**
     * 统一返回
     * @param apiError
     * @return
     */
    private ResponseEntity buildResponseEntity(ApiError apiError) {
        return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
    }
}

上面的代码是一个 Spring Boot 应用中的全局异常处理器,使用 @RestControllerAdvice 注解。解读这段代码:

  1. 注解:

    • @RestControllerAdvice: 声明该类是一个全局异常处理器,并且可以将处理的结果直接作为 JSON 响应返回。
  2. 类声明: public class GlobalExceptionHandler 表示全局异常处理器的类。

  3. 异常处理方法:

    • @ExceptionHandler(Throwable.class): 处理所有不可知的异常。接受一个 Throwable 类型的参数,打印异常堆栈信息,然后构建一个 ApiError 对象,并返回一个 HTTP 400(Bad Request)的响应。
    • @ExceptionHandler(value = BadRequestException.class): 处理自定义的 BadRequestException 异常。接受一个 BadRequestException 类型的参数,打印异常堆栈信息,然后构建一个 ApiError 对象,并返回一个响应,其中包含异常的状态码和消息。
    • @ExceptionHandler(value = EntityExistException.class): 处理自定义的 EntityExistException 异常。接受一个 EntityExistException 类型的参数,打印异常堆栈信息,然后构建一个 ApiError 对象,并返回一个 HTTP 400(Bad Request)的响应。
    • @ExceptionHandler(value = EntityNotFoundException.class): 处理自定义的 EntityNotFoundException 异常。接受一个 EntityNotFoundException 类型的参数,打印异常堆栈信息,然后构建一个 ApiError 对象,并返回一个 HTTP 404(Not Found)的响应。
  4. 私有方法:

    • private ResponseEntity buildResponseEntity(ApiError apiError): 构建一个 ResponseEntity 对象,将 ApiError 对象和相应的 HTTP 状态码包装在响应中返回。

总体来说,这个全局异常处理器捕获并处理了不同类型的异常,将它们转化为符合 API 规范的错误响应,并记录异常的堆栈信息。

你可能感兴趣的:(java,开发语言,spring,boot)