💥 该系列属于【SpringBoot基础】专栏,如您需查看其他SpringBoot相关文章,请您点击左边的连接
目录
一、场景引入
SpringBoot程序在运行时可能会遇到不可预知的异常,这些异常信息通常不遵循后端返回给前端的统一消息格式。
下面来模拟一下这种异常的发生。
1. 项目结构
2. Result
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Result<T> implements Serializable {
Integer code;
String msg;
T data;
public static <T> Result<T> success() {
Result<T> result = new Result<>();
result.code = 1;
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.code = 1;
result.data = data;
return result;
}
public static <T> Result<T> error(String msg) {
Result<T> result = new Result<>();
result.code = 0;
result.msg = msg;
return result;
}
}
3. Controller
@RestController
public class TestController {
@RequestMapping("/exceptionTest")
public Result exceptionTest() { //异常测试
int i = 1 / 0;
return Result.success();
}
@RequestMapping("/errorTest")
public Result errorTest() {
return Result.error("这是一个错误"); //错误测试
}
}
exceptionTest这里是代表了服务器端程序运行时可能出现的异常,而实际开发中一些异常往往是不可预知的,这里仅仅用来模拟。
errorTest这里代表后端返回给前端的错误消息统一格式。
4. 接口测试
(1)errorTest
error返回格式遵循后端给前端的消息格式。
(2)exceptionTest
此时返回给前端的并不遵循消息格式,因此后端有必要全局捕获异常,以统一的格式返回给前端。
5. 异常处理方案
(1)方案一:try-catch
实际开发的三层架构中,Controller,Service,Mapper都可能抛出异常,由于三层架构的调用关系,最终会将异常返回给Controller。
此时可以在每个Controller的方法中都设置try-catch,如果这么做那么代码将变得非常臃肿,可阅读性也变差。因此这种方案并不可取。
(2)方案二:全局异常处理器
全局异常处理器是一种处理整个应用中抛出的异常的机制。其核心思想是集中管理异常处理逻辑,从而提供一种一致的方式来响应异常情况,而不是在每个controller方法中分别处理异常。
二、全局异常处理器
1. 代码
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result exceptionHandler(Exception ex) { //处理一切异常Exception
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
}
2. 接口测试
可以看出处理了异常,并按照统一格式返回给前端。
3. 其他
实际开发中,可以针对不同类型的异常进行分别处理。摘自黑马程序员《苍穹外卖》项目,代码示例如下:
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获业务异常
*/
@ExceptionHandler
public Result exceptionHandler(BaseException ex){ //自定义BaseException用来处理业务异常
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
/**
* 处理SQL异常
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
String message = ex.getMessage();
if(message.contains("Duplicate entry")){
String[] split = message.split(" ");
String username = split[2];
String msg = username + MessageConstant.ALREADY_EXISTS;
return Result.error(msg);
}else{
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}
}