@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)。解读这段代码:
类声明: class ApiError
是一个类的声明。
字段:
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
: 一个私有的字符串字段,用于存储错误消息。构造方法:
private ApiError()
: 私有的无参构造方法,用于在对象创建时初始化 timestamp
字段为当前时间。public ApiError(Integer status, String message)
: 公共的构造方法,接受状态码和错误消息作为参数,并调用无参构造方法初始化时间戳。初始化: 在无参构造方法中,通过调用 LocalDateTime.now()
初始化了时间戳字段。
总体来说,这个类的目的是表示一个 API 错误,包含了状态码、错误消息和发生错误的时间戳。@JsonFormat
注解表明,在将对象转换为 JSON 格式时,时间戳应该按指定的格式进行格式化。
封装了 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
的异常类。解读这段代码:
注解: @Getter
注解表示使用 Lombok 库自动生成 getter 方法。
类声明: public class BadRequestException extends RuntimeException
表示 BadRequestException
类继承自 RuntimeException
,即它是一个运行时异常类。
字段:
private Integer status = BAD_REQUEST.value()
: 一个私有的整数字段,用于表示错误的状态码。它被初始化为 HTTP 400(Bad Request)的状态码,使用了常量 BAD_REQUEST
的 value()
方法。构造方法:
public BadRequestException(String msg)
: 公共的构造方法,接受错误消息作为参数,并调用父类 RuntimeException
的构造方法,将错误消息传递给父类。public BadRequestException(HttpStatus status, String msg)
: 公共的构造方法,接受 HttpStatus
和错误消息作为参数。它调用父类 RuntimeException
的构造方法,并通过参数设置了状态码 status
。总体来说,这个异常类用于表示客户端发起的请求存在问题,其中包括了错误消息和状态码。使用 Lombok 的 @Getter
注解自动生成了 getter 方法。
(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
的异常类。解读这段代码:
导入语句: 代码中导入了 org.springframework.util.StringUtils
类,该类提供了一些字符串处理的实用方法。
类声明: public class EntityNotFoundException extends RuntimeException
表示 EntityNotFoundException
类继承自 RuntimeException
,即它是一个运行时异常类。
构造方法:
public EntityNotFoundException(Class clazz, String field, String val)
: 公共的构造方法,接受三个参数:Class clazz
表示实体的类,String field
表示字段名,String val
表示字段值。在构造方法中,调用了父类 RuntimeException
的构造方法,并传递了由静态方法 generateMessage
生成的错误消息。静态方法:
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
的异常类。解读这段代码:
导入语句: 代码中导入了 org.springframework.util.StringUtils
类,该类提供了一些字符串处理的实用方法。
类声明: public class EntityExistException extends RuntimeException
表示 EntityExistException
类继承自 RuntimeException
,即它是一个运行时异常类。
构造方法:
public EntityExistException(Class clazz, String field, String val)
: 公共的构造方法,接受三个参数:Class clazz
表示实体的类,String field
表示字段名,String val
表示字段值。在构造方法中,调用了父类 RuntimeException
的构造方法,并传递了由静态方法 generateMessage
生成的错误消息。静态方法:
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
注解。解读这段代码:
注解:
@RestControllerAdvice
: 声明该类是一个全局异常处理器,并且可以将处理的结果直接作为 JSON 响应返回。类声明: public class GlobalExceptionHandler
表示全局异常处理器的类。
异常处理方法:
@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)的响应。私有方法:
private ResponseEntity buildResponseEntity(ApiError apiError)
: 构建一个 ResponseEntity 对象,将 ApiError
对象和相应的 HTTP 状态码包装在响应中返回。总体来说,这个全局异常处理器捕获并处理了不同类型的异常,将它们转化为符合 API 规范的错误响应,并记录异常的堆栈信息。