首先跟前端商量好,用errMessage作为异常信息传输的关键字。
1. 创建一个公共异常类
如果要获取 "非法参数" 的错误消息,可以使用 CommonError.PARAMS_ERROR.getErrMessage()
方法来获取。这种方式使得代码更具可读性和维护性。
public enum CommonError {
//Java 的枚举类型(Enum)用于表示一组具有固定值的常量。枚举类型提供了一种更安全、更可读且更易维护的方式来处理一组相关的常量。
// 下面的常量通过CommonError( String errMessage)方法,将错误信息传递给私有成员变量private
UNKOWN_ERROR("执行过程异常,请重试。"),
PARAMS_ERROR("非法参数"),
OBJECT_NULL("对象为空"),
QUERY_NULL("查询结果为空"),
REQUEST_NULL("请求参数为空");
// 这一行定义了一个私有的成员变量 errMessage,用于存储枚举常量的错误消息。
private String errMessage;
/**返回对应的错误参数信息如:
* String errorMessage = CommonError.PARAMS_ERROR.getErrMessage();
* System.out.println(errorMessage); // 输出 "非法参数"
* 用于获取枚举常量的错误消息。这个方法允许你通过枚举常量来获取相应的错误消息。
*/
public String getErrMessage() {
return errMessage;
}
// 这是枚举的构造函数,它在创建每个枚举常量时被调用,并用传递的错误消息来初始化 errMessage 成员变量。
private CommonError( String errMessage) {
this.errMessage = errMessage;
}
}
2.创建一个返回给前端的RestErrorResponse对象
/*
通常情况下,当发生错误时,你可以创建一个 RestErrorResponse 对象,
将错误消息传递给构造函数,然后将这个对象作为响应的一部分返回给客户端,以便客户端能够获取错误信息。
*/
//它实现了 Serializable 接口,表示这个类可以序列化,通常用于对象的持久化和网络传输。
public class RestErrorResponse implements Serializable {
//这是一个私有成员变量 errMessage,用于存储错误消息。
private String errMessage;
//这是类的构造函数,它接受一个错误消息字符串作为参数,并用它来初始化 errMessage 成员变量。
public RestErrorResponse(String errMessage){
this.errMessage= errMessage;
}
//这是一个公共方法 getErrMessage(),用于获取错误消息的值。通常,这种方法被用来从对象中获取属性的值。
public String getErrMessage() {
return errMessage;
}
//用于设置错误消息的值。通常,这种方法被用来修改对象的属性值。
public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}
}
3.自定义运行时异常
public class XueChengPlusException extends RuntimeException {
//这是一个私有成员变量 errMessage,用于存储异常的错误消息。
private String errMessage;
//这是无参构造函数,它调用父类 RuntimeException 的无参构造函数。
public XueChengPlusException() {
super();
}
/*这是有参构造函数,它接受一个错误消息字符串作为参数。它首先调用父类 RuntimeException 的构造函数,
并传递错误消息,然后将错误消息存储到 errMessage 成员变量中。
*/
public XueChengPlusException(String errMessage) {
super(errMessage);
this.errMessage = errMessage;
}
//这是一个公共方法 getErrMessage(),用于获取异常的错误消息。
public String getErrMessage() {
return errMessage;
}
/*
这是一个静态方法 cast(),它接受一个 CommonError 枚举常量作为参数。它抛出一个 XueChengPlusException 异常,
异常的错误消息来自于传入的 CommonError 枚举常量的错误消息。
*/
public static void cast(CommonError commonError){
throw new XueChengPlusException(commonError.getErrMessage());
}
/*
是另一个静态方法 cast(),它接受一个字符串作为参数。
它也抛出一个 XueChengPlusException 异常,异常的错误消息来自于传入的字符串。
*/
public static void cast(String errMessage){
throw new XueChengPlusException(errMessage);
}
}
4.配置全局异常处理器
//这是 Lombok 提供的注解,用于自动生成日志记录器(logger)的代码。日志记录器通常用于记录应用程序的运行时信息。
@Slf4j
// 这是 Spring Framework 提供的注解,它标识这个类是一个全局异常处理器。全局异常处理器用于捕获应用程序中抛出的异常,并根据异常类型执行相应的处理逻辑。
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
/*
这是一个异常处理方法的注解,它指定了要处理的异常类型为 XueChengPlusException。
如果应用程序抛出了这种异常,将会调用这个方法来处理。
*/
@ExceptionHandler(XueChengPlusException.class)
/*
注解用于标识异常处理方法所处理的异常类型,并且可以指定返回的 HTTP 状态码以及可选的原因(reason)。
HttpStatus.INTERNAL_SERVER_ERROR是一个枚举值,表示 HTTP 响应状态码为 500 Internal Server Error(内部服务器错误)。
这个状态码通常用于表示服务器在处理请求时发生了未知的、不可预料的错误。表示会返回500状态码
*/
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse customException(XueChengPlusException e) {
log.error("【系统异常】{}",e.getErrMessage(),e);
return new RestErrorResponse(e.getErrMessage());
}
@ResponseBody
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse exception(Exception e) {
log.error("【系统异常】{}",e.getMessage(),e);
return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());
}
@ResponseBody
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
List<String> msgList = new ArrayList<>();
//将错误信息放在msgList
bindingResult.getFieldErrors().stream().forEach(item->msgList.add(item.getDefaultMessage()));
//拼接错误信息
String msg = StringUtils.join(msgList, ",");
log.error("【系统异常】{}",msg);
return new RestErrorResponse(msg);
}
}
5.异常示例
//向课程信息表插入数据新增对象
CourseBase courseBaseNew = new CourseBase();
//将填写的课程信息赋值给新增对象,属性一致就可以拷
BeanUtils.copyProperties(dto, courseBaseNew);
//设置审核状态
courseBaseNew.setAuditStatus("202002");
//设置发布状态
courseBaseNew.setStatus("203001");
//机构id
courseBaseNew.setCompanyId(companyId);
//添加时间
courseBaseNew.setCreateDate(LocalDateTime.now());
//插入课程基本信息表
int insert = courseBaseMapper.insert(courseBaseNew);
if (insert <= 0) {
throw new XueChengPlusException("新增课程基本信息失败");
}