专栏首页Spring Boot 2.X 系列Spring Boot 2.X(十一):全局异常处理
原创

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

前言

在 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

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringMVC 主要组件说明

    1、前端控制器 DispatcherServlet(不需要开发,由框架提供【核心】)

    happyJared
  • InnoDB的MVCC机制

    事务可以通过start transaction语句开始一个事务,然后要么使用commit提交事务将所修改的数据持久保存,要么使用rollback撤销所有修改

    平凡的学生族
  • Spring Aware 接口

    有些时候,在 Bean 的初始化中,需要使用 Spring 框架自身的对象来执行一些操作,比如获取 ServletContext 的一些参数,获取 Applic...

    happyJared
  • Spring MVC 浅谈

    MVC这个词儿,最早的定义应该是作为一种软件架构设计模式出现在软工里面的,即使用model、view、controller 来设计及定义web软件的。

    邹志全
  • 优雅的处理你的Java异常

    本文仅按照业务系统开发角度描述异常的一些处理看法.不涉及java的异常基础知识,可以自行查阅 《Java核心技术 卷I》 和 《java编程思想》 可以得到更多...

    用户5397975
  • Spring 应用之适配器设计模式

    适配器模式 ( Adapter Pattern ) 可以将接口转换成期望的另一个接口,使得那些接口不兼容的类可以一起工作,别名又为包装器 ( Wrapper )...

    happyJared
  • Spring MVC 整体介绍

    Spring MVC 是以servlet 为核心进行实现的,统一入口进入拿到请求后,做一次路由,找到对应的controller及对应的RequestMappin...

    邹志全
  • java架构之路-(SpringMVC篇)SpringMVC主要流程源码解析(下)

      我们上次大致说完了执行流程,也只是说了大致的过程,还有中间会出错的情况我们来处理一下。

    小菜的不能再菜
  • [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [下篇]

    由于ASP.NET Core框架在本质上就是由服务器和中间件构建的消息处理管道,所以在它上面构建的应用开发框架都是建立在某种类型的中间件上,整个ASP.NET ...

    蒋金楠
  • 460道Java后端面试高频题答案版【模块十:SpringMVC】

    对于 SpringMVC 并没有太多的学习经验分享给大家,因为我是通过某培训机构的视频学习的 SpringMVC。我个人认为 SpringMVC 的高频面试点有...

    乔戈里

扫码关注云+社区

领取腾讯云代金券