目录
1:异常处理
1.1:异常问题分析
1.2:统一异常处理实现
1.2.1:全局异常处理器
1.2.2:自定义异常类
1.2.3:统一响应前端异常信息封装类
1.2.4:通用的异常信息枚举类
1.2.5:测试
1:异常处理
1.1:异常问题分析
在service方法中有很多的参数合法性校验,当参数不合法则抛出异常,下边我们测试下异常处理。
请求创建课程基本信息,故意将必填项设置为空。
测试发现报500异常,如下:
返回这样错误的信息的在客户端展示显然是不行的。
问题:并没有输出我们抛出异常时指定的异常信息。
所以,现在我们的需求是当正常操作时按接口要求返回数据,当非正常流程时要获取异常信息进行记录,并提示给用户。
异常处理除了输出在日志中,还需要提示给用户,前端和后端需要作一些约定:
1、错误提示信息统一以json格式返回给前端。
2、以HTTP状态码决定当前是否出错,非200为操作异常。
如何规范异常信息?
代码中统一抛出项目的自定义异常类型,这样可以统一去捕获这一类或几类的异常。
规范了异常类型就可以去获取异常信息。
如果捕获了非项目自定义的异常类型统一向用户提示“执行过程异常,请重试”的错误信息。
如何捕获异常?
代码统一用try/catch方式去捕获代码比较臃肿,可以通过SpringMVC提供的控制器增强类统一由一个类去完成异常的捕获。
如下图:
1.2:统一异常处理实现
根据上边分析的方案,统一在base基础工程实现统一异常处理,各模块依赖了base基础工程都 可以使用。
首先在base基础工程添加需要依赖的包:
Java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
1.2.1:全局异常处理器
从 Spring 3.0 - Spring 3.2 版本之间,对 Spring 架构和 SpringMVC 的Controller 的异常捕获提供了相应的异常处理。
- @ExceptionHandler
- Spring3.0提供的标识在方法上或类上的注解,用来表明方法的处理异常类型。
- @ControllerAdvice
- Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强, 在项目中来增强SpringMVC中的Controller。通常和@ExceptionHandler 结合使用,来处理SpringMVC的异常信息。
- @ResponseStatus
- Spring3.0提供的标识在方法上或类上的注解,用状态代码和应返回的原因标记方法或异常类。
调用处理程序方法时,状态代码将应用于HTTP响应。
/**
* @author 爱吃豆的土豆
* @version 1.0
* @description TODO
* @date 2023/2/12 17:01
*/
@Slf4j
@ControllerAdvice
//@RestControllerAdvice
public class GlobalExceptionHandler {
//对项目的自定义异常类型进行处理
@ResponseBody
@ExceptionHandler(XueChengPlusException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse customException(XueChengPlusException e){
//记录异常
log.error("系统异常{}",e.getErrMessage(),e);
//..
//解析出异常信息
String errMessage = e.getErrMessage();
RestErrorResponse restErrorResponse = new RestErrorResponse(errMessage);
return restErrorResponse;
}
@ResponseBody
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RestErrorResponse exception(Exception e){
//记录异常
log.error("系统异常{}",e.getMessage(),e);
//解析出异常信息
RestErrorResponse restErrorResponse = new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrorMessage());
return restErrorResponse;
}
}
1.2.2:自定义异常类
/**
* @author 爱吃豆的土豆
* @description 本项目自定义异常类型
*/
public class XueChengPlusException extends RuntimeException {
private String errMessage;
public XueChengPlusException() {
}
public XueChengPlusException(String message) {
super(message);
this.errMessage = message;
}
public String getErrMessage() {
return errMessage;
}
public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}
/**
* 传入自定义异常信息
* @param message
*/
public static void cast(String message){
throw new XueChengPlusException(message);
}
/**
* 重载了一下方法,调用规定好的枚举异常类中的信息
* @param error
*/
public static void cast(CommonError error){
throw new XueChengPlusException(error.getErrorMessage());
}
}
1.2.3:统一响应前端异常信息封装类
/**
* @author 爱吃豆的土豆
* @version 1.0
* @description 和前端约定返回的异常信息模型
* @date 2023/2/12 16:55
*/
public class RestErrorResponse implements Serializable {
private String errMessage;
public RestErrorResponse(String errMessage){
this.errMessage= errMessage;
}
public String getErrMessage() {
return errMessage;
}
public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}
}
1.2.4:通用的异常信息枚举类
/**
* @Author 爱吃豆的土豆、
* @Date 2023/4/22 15:44
* @desc 系统执行过程中出现的异常信息
*/
public enum CommonError {
UNKOWN_ERROR("执行过程异常,请重试。"),
PARAMS_ERROR("非法参数"),
OBJECT_NULL("对象为空"),
QUERY_NULL("查询结果为空"),
REQUEST_NULL("请求参数为空");
private String errorMessage;
CommonError(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}