Spring Boot 2.X(十一):全局异常处理

简介: 前言 在 Java Web 系统开发中,不管是 Controller 层、Service 层还是 Dao 层,都有可能抛出异常。如果在每个方法中加上各种 try catch 的异常处理代码,那样会使代码非常繁琐。

前言

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

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

1.使用 @ControllerAdvice + @ExceptionHandler 注解进行全局的 Controller 层异常处理。

2.实现 org.springframework.webb.servlet.HandlerExceptionResolver 接口中的 resolveException 方法。

使用 @ControllerAdvice + @ExceptionHandler 注解

1.定义统一异常处理类

@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) {
        log.error("ExceptionHandler ===>" + e.getMessage());
        e.printStackTrace();
        // 这里可根据不同异常引起的类做不同处理方式
        String exceptionName = ClassUtils.getShortName(e.getClass());
        log.error("ExceptionHandler ===>" + exceptionName);
        ModelAndView mav = new ModelAndView();
        mav.addObject("stackTrace", e.getStackTrace());
        mav.addObject("errorMessage", e.getMessage());
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("forward:/error/500");
        return mav;
    }
}

其中 @ExceptionHandler(value = Exception.class) 中的捕获异常 value 可以自定义,如下:

类型 描述
NullPointerException 当应用程序试图访问空对象时,则抛出该异常
SQLException 提供关于数据库访问错误或其他错误信息的异常
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出
NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常
FileNotFoundException 当试图打开指定路径名表示的文件失败时,抛出此异常
IOException 当发生某种I/O异常时,抛出此异常。此类是失败或中断的I/O操作生成的异常的通用类
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例
NegativeArraySizeException 如果应用程序试图创建大小为负的数组,则抛出该异常
NoSuchMethodException 无法找到某一特定方法时,抛出该异常
SecurityException 由安全管理器抛出的异常,指示存在安全侵犯
UnsupportedOperationException 当不支持请求的操作时,抛出该异常
RuntimeException 是那些可能在Java虚拟机正常运行期间抛出的异常的超类

当捕获到响应的异常类型时,会进入 defaultErrorHandler() 方法中的逻辑:把异常信息放入 model,跳转至 /error/500 请求URL。

2.异常信息展现

视图控制器配置

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    /**
     * 视图控制器配置
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {    
        registry.addViewController("/").setViewName("/index");//设置默认跳转视图为 /index
        registry.addViewController("/error/500").setViewName("/error/500");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
        super.addViewControllers(registry);
        
    }
    
}

视图模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Exception</h1>
<h3 th:text="${url}"></h3>
<h3 th:text="${errorMessage}"></h3>
<p  th:each="line : ${stackTrace}" th:text="${line}">  </p>
</body>
</html>

3.测试异常类

@Controller
public class TestController {

    @GetMapping("/index")
    public String hello() {
        int x = 1 / 0;
        return "hello";
    }
}

4.运行测试

浏览器访问:http://127.0.0.1:8080/index

@ControllerAdvice 还能结合 @ModelAttribute 、@InitBinder 注解一起使用,实现全局数据绑定和全局数据预处理等功能。

实现 HandlerExceptionResolver 接口

1.定义统一异常处理类

@Component
public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {

    private Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception ex) {
        Exception e = new Exception();
        //处理 UndeclaredThrowableException
        if (ex instanceof UndeclaredThrowableException) {
            e = (Exception) ((UndeclaredThrowableException) ex).getUndeclaredThrowable();
        } else {
            e = ex;
        }
        e.printStackTrace();
        //这里可以根据不同异常引起的类做不同处理方式
        String exceptionName = ClassUtils.getShortName(e.getClass());
        if(exceptionName.equals("ArrayIndexOutOfBoundsException")) {
            log.error("GlobalHandlerExceptionResolver resolveException ===>" + exceptionName);
            ModelAndView mav = new ModelAndView();
            mav.addObject("stackTrace", e.getStackTrace());
            mav.addObject("exceptionName", exceptionName);
            mav.addObject("errorMessage", e.getMessage());
            mav.addObject("url", request.getRequestURL());
            mav.setViewName("forward:/error/500");
            return mav;
        }
        return null;
    }

}

UndeclaredThrowableException 异常通常是在 RPC 接口调用场景或者使用 JDK 动态代理的场景时发生。如果不预先处理转换,测试捕获到的异常则为 UndeclaredThrowableException,而不是真实的异常对象。

2.异常信息展现 同上

3.测试异常类

@Controller
public class TestController {

    @GetMapping("/test")
    public String test() {
        String[] ss = new String[] { "1", "2" };
        System.out.print(ss[2]);
        return "hello";
    }

}

4.测试运行

测试前先把 @ControllerAdvice 注释了。
浏览器访问:http://127.0.0.1:8080/test

示例代码

github

码云

非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

原文标题:Spring Boot 2.X(十一):全局异常处理

原文地址: https://www.zwqh.top/article/info/20

如果文章对您有帮助,请扫码关注下我的公众号,文章持续更新中...

相关文章
|
4月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
122 0
|
4月前
SpringBoot+Mybatis-Plus+PageHelper分页+多条件查询
SpringBoot+Mybatis-Plus+PageHelper分页+多条件查询
111 0
|
21天前
|
Java Spring UED
Spring框架的异常处理秘籍:打造不败之身的应用!
【8月更文挑战第31天】在软件开发中,异常处理对应用的稳定性和健壮性至关重要。Spring框架提供了一套完善的异常处理机制,包括使用`@ExceptionHandler`注解和配置`@ControllerAdvice`。本文将详细介绍这两种方式,并通过示例代码展示其具体应用。`@ExceptionHandler`可用于控制器类中的方法,处理特定异常;而`@ControllerAdvice`则允许定义全局异常处理器,捕获多个控制器中的异常。
35 0
|
23天前
|
Java API 开发者
【开发者福音】Spring Boot 异常处理:优雅应对错误,提升应用健壮性,让调试不再是噩梦!
【8月更文挑战第29天】本文通过对比传统错误处理方式与Spring Boot推荐的最佳实践,展示了如何在Spring Boot应用中实现统一且优雅的异常处理。传统方法需在每个可能出错的地方显式处理异常,导致代码冗余且不一致。而Spring Boot的全局异常处理机制则能集中处理所有异常,简化代码并确保错误响应格式统一,提高应用程序的健壮性和可维护性。文中提供了具体的示例代码以帮助读者更好地理解和应用这一机制。
59 0
|
2月前
|
JSON Java 数据库
Spring Boot中的全局异常处理
主要讲解了Spring Boot 的全局异常处理,包括异常信息的封装、异常信息的捕获和处理,以及在实际项目中,我们用到的自定义异常枚举类和业务异常的捕获与处理,在项目中运用的非常广泛,基本上每个项目中都需要做全局异常处理。
|
3月前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
43 2
|
3月前
|
存储 运维 Java
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
51 2
|
3月前
|
Java Maven
springboot项目打jar包后,如何部署到服务器
springboot项目打jar包后,如何部署到服务器
247 1
|
3月前
|
XML 运维 Java
Spring运维之boot项目打包jar和插件运行并且设置启动时临时属性和自定义配置文件
Spring运维之boot项目打包jar和插件运行并且设置启动时临时属性和自定义配置文件
40 1
|
2月前
|
JSON Java API
Spring Boot中的异常处理策略
Spring Boot中的异常处理策略