一.概念
- Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括Handler 映射、数据绑定以及目标方法执行时发生的异常.
-
SpringMVC 提供的 HandlerExceptionResolver 的实现类
二.举例
- SpringMVCTestNew.java 控制器
/**
* 1. 在 @ExceptionHandler 方法的入参中可以加入 Exception 类型的参数, 该参数即对应发生的异常对象
* 2. @ExceptionHandler 方法的入参中不能传入 Map. 若希望把异常信息传导页面上, 需要使用 ModelAndView 作为返回值
* 3. @ExceptionHandler 方法标记的异常有优先级的问题. (优先会找与出现异常最接近的异常来处理)
* 4. @ControllerAdvice: 如果在当前 Handler 中找不到 @ExceptionHandler 方法来出来当前方法出现的异常,
* 则将去 @ControllerAdvice 标记的类中查找 @ExceptionHandler 标记的方法来处理异常.
*/
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handlerArithmeticException(Exception ex)
{
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
System.out.println("[出现了算数异常] : " + ex);
return mv;
}
/**
* 测试springMVC对于异常的处理
*/
@RequestMapping("/testExceptionHandlerReslover")
public String testExceptionHandlerReslover(@RequestParam(value="i") Integer i)
{
System.out.println("param i value = " + (10/i));
return "success";
}
- 新建
error.jsp
<h4>Error Page</h4>
<p>exception = ${requestScope.exception}</p>
- 访问: http://localhost:8081/spring-mvc-2/testExceptionHandlerReslover?i=0
因为目标方法被除数为0,出现算数异常,所以在java控制台输出:
[出现了算数异常] : java.lang.ArithmeticException: / by zero
前台页面输出:
Error Page
exception = java.lang.ArithmeticException: / by zero
- 此时如果想让所有控制器handler都需要处理异常,则需要自己定义类实现, 以下是自己定义的
HandlerException
, (注意: 如果在Handler控制器中能找到@ExceptionHandler
注释的方法,则优先执行该方法)
package com.atguigu.springmvc.tests;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
/**
* @ControllerAdvice: 如果在当前 Handler 中找不到 @ExceptionHandler 方法来出来当前方法出现的异常,
* 则将去 @ControllerAdvice 标记的类中查找 @ExceptionHandler 标记的方法来处理异常.
* 如果在Handler控制器中能找到@ExceptionHandler注释的方法,则优先执行该方法
* @author lxf
*/
@ControllerAdvice
public class HandlerException {
@ExceptionHandler({ArithmeticException.class})
public ModelAndView handlerArithmeticException(Exception ex)
{
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
System.out.println("--->[出现了算数异常] : " + ex);
return mv;
}
}
使用@ResponseStatus
注解
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
是HandlerExceptionResolver
接口的实现类, 负责使用@ResponseStatus
注解将HTTP状态码返回.
@ResponseStatus
注解可以作用在类和方法上
- 作用在类上, 新建异常类
UserNameNotMatchPasswordException
package com.atguigu.springmvc.tests;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* 自定义异常类
* @author lxf
*
*/
@ResponseStatus(value=HttpStatus.FORBIDDEN, reason=";用户名和密码不匹配")
public class UserNameNotMatchPasswordException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
- 在
SpringMVCTestNew
控制器中写方法
/**
* 测试 @ResponseStatus 注解, 将http状态码返回客户端
* @param i
* @return
*/
@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i)
{
if(i == 13)
{
throw new UserNameNotMatchPasswordException();
}else
{
System.out.println("testResponseStatusExceptionResolver...");
}
return "success";
}
测试访问 : http://localhost:8081/spring-mvc-2/testResponseStatusExceptionResolver?i=13
-
异常输出:
将注解作用在方法上, 修改控制器中的目标方法,新增
@ResponseStatus
注解
/**
* 测试 @ResponseStatus 注解, 将http状态码返回客户端
* @param i
* @return
*/
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="您访问的页面不存在!")
@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i)
{
if(i == 13)
{
throw new UserNameNotMatchPasswordException();
}else
{
System.out.println("testResponseStatusExceptionResolver...");
}
return "success";
}
-
访问测试:
DefaultHandlerExceptionResolver 处理springMVC指定的异常返回对应Http状态
- 在
springMVCTestNew
控制器中新增测试目标方法
/**
* 测试异常处理DefaultHandlerExceptionResolver处理springMVC指定的异常返回对应Http状态
* 该处理器必须是post方式请求,如果请求方式为get那么会通过DefaultHandlerExceptionResolver处理
* @return
*/
@RequestMapping(value="/testDefaultHandlerExceptionResolver", method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver()
{
System.out.println("testDefaultHandlerExceptionResolver");
return "success";
}
-
如果在浏览器中请求以上方法,则会抛出异常
SimpleMappingExceptionResolver
对所有异常进行统一处理, 可以使用
SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
- 配置
springmvc.xml
<!-- 配置SimpleMappingExceptionResolver类映射异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 可以在对应jsp访问的异常属性定义名称, 默认=exception -->
<property name="exceptionAttribute" value="ex"></property>
<!-- 将异常映射到对应的 error.jsp 页面中 -->
<property name="exceptionMappings">
<props>
<!-- 映射数组越界异常到 error.jsp 页面中 -->
<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
</props>
</property>
</bean>
- 在
SpringMVCTestNew
控制器中新增测试方法
/**
* 测试SimpleMappingExceptionResolver映射指定异常到对应页面
* 如果页面传递的参数是20 ,超出数组边界, 回抛出数组越界异常,
* 在springmvc.xml文件中配置映射关系
* @param i
* @return
*/
@RequestMapping("/testSimpleMappingExceptionResolver")
public String testSimpleMappingExceptionResolver(@RequestParam("i") int i)
{
String[] arr = new String[10];
String val = arr[i];
System.out.println("testSimpleMappingExceptionResolver val = " + val);
return "success";
}
- 在
error.jsp
页面中打印异常
<h4>Error Page</h4>
<p>exception = ${requestScope.ex}</p>
访问地址: http://localhost:8081/spring-mvc-2/testSimpleMappingExceptionResolver?i=20
error.jsp
页面输出:
Error Page
exception = java.lang.ArrayIndexOutOfBoundsException: 20