Spring全局异常处理
创始人
2024-04-04 06:18:50

Spring全局异常处理


1. 概述

在 Java Web 系统开发中,不管是 Controller 层、Service 层还是 Dao 层,都有可能抛出异常。如果在每个方法中加上各种 try catch 的异常处理代码,那样会使代码非常繁琐。在Spring中,我们可以将所有类型的异常处理从各个单独的方法中解耦出来,进行异常信息的统一处理和维护。

在 Spring MVC 中全局异常捕获处理的解决方案通常有两种方式:

  1. 使用 @ControllerAdvice + @ExceptionHandler 注解进行 Controller 层异常处理。
    使用注解方式,只能处理控制器中的异常 。
  2. 实现org.springframework.webb.servlet.HandlerExceptionResolver 接口中的 resolveException 方法。

由于HandlerExceptionResolver很少使用,因此这里只介绍第一种实现方式。

2. 使用 @ControllerAdvice + @ExceptionHandler 注解

这种方式的好处是简单统一,但是需要在每一层都要抛出异常,保证异常能够被controller层接收。

2.1 @ControllerAdvice注解

@ControllerAdivce的组成如下:

public @interface ControllerAdvice {  @AliasFor("basePackages")  String[] value() default {};  @AliasFor("value")  String[] basePackages() default {};  Class[] basePackageClasses() default {};  Class[] assignableTypes() default {};  Class[] annotations() default {};

@ControllerAdvice 注解用于定义全局异常处理类。类中可定义多个异常处理函数,可分别处理不同的异常情况。其参数用于指定生效的范围。形式可以是包、class、注解等,默认是对全部的controller生效

2.2 @ExceptionHandler注解

@ExceptionHandler()注解用于定义当前方法捕获处理的异常类型。当在 controller 中捕获到相应的异常类型时,就会触发当前方法的执行,进行异常处理。
@ExceptionHandler()注解修饰的方法,一般会将该异常类型作为参数传入到方法中,从而在方法中获取异常信息并进一步处理。

@ExceptionHandler(CustomException.class)  
public Result exception(CustomException e){  return new Result(false,"全局异常处理");  
}

如果@ExceptionHandler所在的类是@Controller,则此方法只作用在此类。如果@ExceptionHandler所在的类带有@ControllerAdvice注解,则此方法会作用在全局。

2.3 特点

使用@ControllerAdvice@ExceptionHandler注解,能够细粒度的控制该异常处理器针对哪些 Controller 有效:

  1. 一个系统里就能够存在不同的异常处理器,Controller 也可以有选择的决定使用哪个,更加灵活。
  2. 不同的业务模块可能对异常处理的方式不同,通过该机制就能做到。
  3. 设想一个一开始并未使用全局异常处理的系统,如果直接引入全局范围内生效的全局异常处理,势必可能会改变已有 Controller 的行为,有侵入性。
  4. 也就是说,如果不控制生效范围,即默认对所有 Controller 生效。如果控制生效范围,则默认对所有 Controller 不生效,降低侵入性。

一个小案例如下:

package top.xcyxiaoxiang.common;  /**  * @Description: 全局异常处理案例 * @date: 2022/6/30  下午9:49  * @author: xcy.小相  * @ClassName : GlobalExceptionHandler  */  
// 指定要拦截的位置
@ControllerAdvice(annotations = {RestController.class, Controller.class}) 
// 设置以json的形式返回数据
@ResponseBody  
// 日志记录
@Slf4j  
public class GlobalExceptionHandler {  /**  * 帐号存在异常  * @param ex  * @return  */  @ExceptionHandler(SQLIntegrityConstraintViolationException.class)  public R exceptionHandler(SQLIntegrityConstraintViolationException ex){  // 获取异常信息  String exMessage = ex.getMessage();  log.error("捕获到异常:{}",exMessage);  // 处理异常信息  if(exMessage.contains("Duplicate entry")){  String[] msg = exMessage.split(" ");  return R.error("帐号 "+msg[2]+" 已存在!");  }  return R.error("未知错误!");  }  }

3. 注意事项

若项目结构为 ssm 结构,那么记得将异常处理类注入到spring容器中去!

  

参考:
Spring Boot 全局异常处理整理!开发必会! - 知乎 (zhihu.com)
springBoot 全局异常处理 - 知乎 (zhihu.com)
SpringMVC 异常处理 SimpleMappingExceptionResolver 类 博客园 (cnblogs.com)

相关内容

热门资讯

华测导航股价涨5.1%,诺德基... 1月9日,华测导航涨5.1%,截至发稿,报43.69元/股,成交5.89亿元,换手率2.17%,总市...
华测导航股价涨5.1%,景顺长... 1月9日,华测导航涨5.1%,截至发稿,报43.69元/股,成交5.90亿元,换手率2.17%,总市...
汇添富中证细分有色金属产业主题... 数据显示,1月8日,汇添富中证细分有色金属产业主题ETF(159652)获净申购1.23亿元,位居当...
华测导航股价涨5.1%,嘉实基... 1月9日,华测导航涨5.1%,截至发稿,报43.69元/股,成交5.96亿元,换手率2.19%,总市...
300价值A(562320)已... 数据显示,1月8日,300价值A(562320)遭净赎回828.09万元,位居当日股票ETF净流出排...