• 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 {};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    2.2 @ExceptionHandler注解

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

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

    如果@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("未知错误!");  
        }  
      
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    3. 注意事项

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

      
    <context:component-scan base-package="top.xcyxiaoxiang.ExceptionHandler" />
    
    • 1
    • 2

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

  • 相关阅读:
    JavaWeb基础之Servlet
    VulnHub Metasploitable-2
    一款适用于.Net的高性能文件上传项目
    电脑如何激活windows
    分布式ID生成服务的技术原理和项目实战
    【鸿蒙软件开发】ArkTS基础组件之Marquee(文字跑马灯)、QRCode(二维码生成)
    epoll与socket缓冲区的恩恩怨怨
    KdMapper扩展实现之AVG(aswArPot.sys)
    在内存分配时,使用 4096-1 的常见做法是为了实现对齐的目的
    代码行统计工具---cloc(Count Lines of Code)
  • 原文地址:https://blog.csdn.net/qq_45807032/article/details/127707115