(十)SpringMVC学习笔记-异常处理

Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射数据绑定以及目标方法执行时发生的异常

其中HandlerExceptionResolver的实现类如下图所示:
在这里插入图片描述
注意:AnnotationMethodHandlerExceptionResolver是过时的。

DispatcherServlet 默认装配的 HandlerExceptionResolver 包含如下子类:

  • 未配置<mvc:annotation-driven/>时:
    在这里插入图片描述
  • 配置了<mvc:annotation-driven/>时:
    在这里插入图片描述
    所以一般我们在使用HandlerExceptionResolver 处理异常时,需要配置<mvc:annotation-driven/>。

一、ExceptionHandlerExceptionResolver

@ExceptionHandler 注解

示例

ExceptionHandlerExceptionResolver主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。

下面简单演示一下@ExceptionHandler 注解的使用。

1.在控制器类中编写定义如下两个方法,具体代码如下所示:

/**
* 该方法用于处理@ExceptionHandler 中所指明的异常
 * @ExceptionHandler 中的值是一个class集合。
 * ArithmeticException.class表明该方法可以用于处理ArithmeticException
 */
@ExceptionHandler({ArithmeticException.class})
/**
 * 入参Exception ex 对应于发生的异常对象
 * @ExceptionHandler 作用的方法的入参不能传入Map。若希望把异常信息显示在错误页面上,
 * 则可以同时ModelAndView作为返回值
 */
public ModelAndView handleArithmeticException(Exception ex) {
	System.out.println("出异常了:" + ex);
	ModelAndView modelAndView = new ModelAndView("error");
	modelAndView.addObject("exception", ex);
	return modelAndView;
}

@RequestMapping("/testExceptionHandlerExceptionResolver")
public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i) {
	//测试除0异常
	System.out.println("result:" + (10/i));
	return "success";
}

2.当我们在请求测试传入的参数为0时,这时testExceptionHandlerExceptionResolver方法会发生除0异常并将异常交由@ExceptionHandler作用的handleArithmeticException进行处理。运行的结果如下图所示:
在这里插入图片描述

@ExceptionHandler 注解定义的方法优先级问题

例如发生的是NullPointerException,但是声明的异常有RuntimeException 和 Exception,此时会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler注解方法,即标记了 RuntimeException 的方法。

比如在上述的示例中,我在控制器中添加了另一个异常处理的方法,具体代码如下所示:

@ExceptionHandler({RuntimeException.class})
public ModelAndView handleException(Exception ex) {
	System.out.println("[出异常了]:" + ex);
	ModelAndView modelAndView = new ModelAndView("error");
	modelAndView.addObject("exception", ex);
	return modelAndView;
}

如果请求发生了除0异常时,该异常会由handleException处理而不是handleArithmeticException。运行结果如下所示:
在这里插入图片描述

@ControllerAdvice 注解

我们若在控制器类中使用@ExceptionHandler定义的方法来处理异常,其只适用于处理当前控制器类方法所发生的异常,SpringMVC还支持全局的异常处理类。

ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,也就是在当前的控制器类中找不到@ExceptionHandler 注解作用的异常处理方法的话,则会找@ControllerAdvice标注的类中的@ExceptionHandler 注解方法。

基于上述示例,将控制器类中的异常处理方法注释掉。并编写一个异常处理类,具体代码如下:

@ControllerAdvice
public class ExceptionHandleTest {

	@ExceptionHandler({ArithmeticException.class})
	public ModelAndView handleArithmeticException(Exception ex) {
		System.out.println("ExceptionHandleTest:出异常了:" + ex);
		ModelAndView modelAndView = new ModelAndView("error");
		modelAndView.addObject("exception", ex);
		return modelAndView;
	}
}

请求响应测试后,运行输出结果如下所示:

ExceptionHandleTest:出异常了:java.lang.ArithmeticException: / by zero

二、ResponseStatusExceptionResolver

我们也可以使用ResponseStatusExceptionResolver来解析自定义的异常类。

比如现在定义了如下一个异常类:

/**
 * 通过@ResponseStatus注解来新增异常映射,其中
 * code代表异常映射码,reason代表异常原因。
 *
 */
@ResponseStatus(code=HttpStatus.FORBIDDEN,reason="ID不匹配异常,权限不足!")
public class IDNotMatchException extends RuntimeException {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
}

我们在若在处理器方法中抛出了上述异常,代码如下:

@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("id") Integer id) {
	if (id == 13)
		throw new IDNotMatchException();
	System.out.println("testResponseStatusExceptionResolver...");
	return "success";
}

当请求参数传入的id值为13且ExceptionHandlerExceptionResolver 不解析述异常时,由于触发的异常 IDNotMatchException 带有@ResponseStatus注解。因此会ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。

出错的运行结果如下图所示:
在这里插入图片描述

三、DefaultHandlerExceptionResolver

DefaultHandlerExceptionResolver可以对一些特殊的异常进行处理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
在这里插入图片描述

四、SimpleMappingExceptionResolver

如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常

下面演示一下该类的使用。

1.首先需要在MVC配置文件中进行如下配置:

<!-- 配置使用SimpleMappingExceptionResolver来映射异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<!-- 配置 exceptionAttribute,value表示存储异常的对象,JSP页面上可以通过requestScope.ex来获取-->
	<property name="exceptionAttribute" value="ex"></property>
	<property name="exceptionMappings">
		<props>
			<!-- 当发生java.lang.ArrayIndexOutOfBoundsException时,由error.jsp错误页面进行显示 -->
			<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
		</props>
	</property>
</bean>

注意:<property name=“exceptionAttribute” value=“ex”></property>中的value的值默认为exception,SimpleMappingExceptionResolver有进行如下定义:
在这里插入图片描述
当我们没有配置exceptionAttribute时,我们依然可以在JSP页面通过${requestScope.exception}来获取异常数据。

2.在控制器类中编写如下目标方法:

@RequestMapping("/testSimpleMappingExceptionResolver")
public String testSimpleMappingExceptionResolver(@RequestParam("i") Integer i) {
	String[] strArr = new String[10];
	//可能会发生数组角标越界异常
	System.out.println(strArr[i]);
	return "success";
}

3.当请求传入的i值为15时,其运行结果如下图所示:
在这里插入图片描述
不同于使用@ExceptionHandler注解需要返回包含异常信息的ModelAndView对象才能将错误信息显示在页面上那么繁琐,显然使用SimpleMappingExceptionResolver更为方便一点。

猜你喜欢

转载自blog.csdn.net/weixin_40374341/article/details/87475130