Spring 全局与局部异常处理解析 + 实战案例
在 Java 开发中,异常处理是非常重要的一环。它不仅能够提升代码的健壮性,还能为用户提供有意义的错误提示。在 Spring Framework 中,我们可以通过全局和局部异常处理来优雅地管理异常。本文将结合 CommonControllerAdvice
与 SeckillControllerAdvice
的示例,深入解析全局和局部异常处理的工作原理。
1. 全局异常处理:CommonControllerAdvice
全局异常处理允许我们将所有控制器中的异常统一捕获和处理。在 Spring 中,这通常通过 @ControllerAdvice
和 @ExceptionHandler
注解来实现。
/**
* 全局异常处理
*/
public class CommonControllerAdvice {
@ExceptionHandler(GlobalException.class) // 当抛出GlobalException时,调用该方法处理异常
@ResponseBody // 将返回的NewResult对象直接序列化为JSON并返回给前端
public NewResult handleBusinessException(GlobalException ex){
return NewResult.error(ex.getCodeMsg()); // 根据捕获的GlobalException返回对应的错误信息
}
@ExceptionHandler(Exception.class) // 当抛出任何其他Exception时,调用该方法处理异常
@ResponseBody // 将返回的NewResult对象直接序列化为JSON并返回给前端
public NewResult handleDefaultException(Exception ex){
ex.printStackTrace(); // 在控制台打印异常的堆栈信息
return NewResult.defaultError(); // 返回一个默认的错误响应
}
}
@Setter
@Getter
public class GlobalException extends RuntimeException {
private CodeMsg codeMsg;
public GlobalException(CodeMsg codeMsg){
this.codeMsg = codeMsg;
}
}
1.1 全局异常处理的作用
- 集中管理异常:通过
CommonControllerAdvice
类,我们可以统一处理系统中的各种异常,而不需要在每个控制器中重复编写异常处理代码。 @ExceptionHandler
:该注解指定了具体的异常类型,一旦系统中抛出指定类型的异常,Spring 会调用相应的方法来处理。@ResponseBody
:确保返回值会被序列化为 JSON 格式,并直接作为 HTTP 响应返回给前端。
在 CommonControllerAdvice
中,我们定义了两个异常处理方法:
handleBusinessException()
:用于处理自定义的GlobalException
,并根据异常的内容返回相应的错误信息。handleDefaultException()
:用于处理所有其他类型的异常,输出异常堆栈信息,并返回默认的错误响应。
1.2 优点
- 可复用性:一个全局的异常处理类可以用于系统的所有控制器。
- 简化代码:开发人员只需在一个地方处理常见的异常逻辑,简化了每个控制器中的异常处理。
2. 局部异常处理:SeckillControllerAdvice
在某些情况下,可能需要对特定的控制器进行单独的异常处理。这时可以使用局部异常处理机制,即通过继承全局异常处理类,并扩展或覆盖其中的逻辑。
/**
* 局部异常处理
*/
@ControllerAdvice
public class SeckillControllerAdvice extends CommonControllerAdvice {
// 处理针对秒杀相关的特定异常逻辑
@ExceptionHandler(SeckillException.class)
@ResponseBody
public NewResult handleSeckillException(SeckillException ex) {
return NewResult.error("秒杀异常:" + ex.getMessage());
}
}
/**
* 秒杀业务的自定义异常类,继承自 GlobalException
*/
public class SeckillException extends GlobalException {
// 使用父类的构造方法
public SeckillException(CodeMsg codeMsg) {
super(codeMsg);
}
}
2.1 局部异常处理的场景
虽然 CommonControllerAdvice
统一处理了大多数异常,但在一些特定业务场景中(比如秒杀系统),我们可能需要对某些特殊异常进行个性化处理。SeckillControllerAdvice
通过继承 CommonControllerAdvice
,不仅能够复用全局异常处理的逻辑,还能针对秒杀系统中的异常(比如 SeckillException
)进行专门的处理。
2.2 优点
- 灵活性:在保证全局异常处理能力的同时,能够为特定模块或业务逻辑定制化异常处理方案。
- 层级化异常处理:局部异常处理可以覆盖全局的处理逻辑,允许为某些控制器提供更加细粒度的异常处理。
3. 全局与局部异常处理的优先级
当系统同时存在全局异常处理和局部异常处理时,Spring 会优先调用局部异常处理方法。如果局部异常处理方法未能匹配相应的异常类型,Spring 才会回退到全局异常处理类。因此,局部异常处理能够在特定场景中实现个性化定制,而全局异常处理则负责通用的异常场景。
4. 总结
通过全局和局部异常处理机制,我们可以在 Spring 应用中构建一个高效、灵活且可维护的异常处理框架。全局异常处理 (CommonControllerAdvice
) 提供了基础的异常捕获和处理能力,而局部异常处理 (SeckillControllerAdvice
) 则允许针对特定场景进行更加细致的异常处理。
这种设计既能减少重复代码,又能提高系统的健壮性和可维护性。在实际项目中,开发者可以根据不同业务需求,灵活应用全局和局部异常处理的组合方案,以确保异常处理逻辑既通用又灵活。