Spring全局异常处理

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<? extends Annotation>[] 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<String> 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容器中去!

<!--注入全局异常处理类-->  
<context:component-scan base-package="top.xcyxiaoxiang.ExceptionHandler" />

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值