一、异常处理概述
Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。
SpringMVC 提供的 HandlerExceptionResolver 的实现类
二、HandlerExceptionResolver
DispatcherServlet 默认装配的 HandlerExceptionResolver :
① 没有使用 <mvc:annotation-driven/>
配置:
- AnnotationMethodHandlerExceptionResolver
- ResponseStatusExceptionResolver
- DefaultHandlerExceptionResolver
②使用<mvc:annotation-driven/>
配置
- ExceptionHandlerExceptionResolver
- ResponseStatusExceptionResolver
- DefaultHandlerExceptionResolver
如果异常解析器都不能处理就直接抛出去;
三、异常处理_ExceptionHandlerExceptionResolver
1、主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
2、@ExceptionHandler 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
3、ExceptionHandlerMethodResolver 在Controller类中若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法
①页面链接
<a href="handle01?i=0">testExceptionHandlerExceptionResolver</a>
②控制器方法
@Controller
public class ExceptionTestController {
@RequestMapping("/handle01")
public String handle01(Integer i) {
System.out.println("handle01....");
System.out.println(10 / i);
return "success";
}
}
③测试当i=0时,出现异常情况,处理异常,跳转到error.jsp
④ 在控制器中增加处理该类异常的方法
@Controller
public class ExceptionTestController {
@RequestMapping("/handle01")
public String handle01(Integer i) {
System.out.println("handle01....");
System.out.println(10 / i);
return "success";
}
/**
* 告诉SpringMVC这个方法专门处理这个类发生的异常
* 1、给方法上随便写一个Exception,用来接受发生的异常
* 2、要携带异常信息不能给参数位置写Model;
* 3、返回ModelAndView就行了;
* 4、如果有多个@ExceptionHandler都能处理这个异常,精确优先
* 5、全局异常处理与本类(MyJiZhongException.java)同时存在,本类优先(即使全局的配置比本来的精确);
*/
@ExceptionHandler(value = { Exception.class })
public ModelAndView handleException01(Exception exception) {
System.out.println("本类的:handleException01..." + exception);
ModelAndView view = new ModelAndView("myerror");
view.addObject("ex", exception);
视图解析器拼串
return view;
}
}
⑤也可以定义公共的处理异常的类,要加上@ControllerAdvice
/**
* 集中处理所有异常
* @author lfy
*
* 1、集中处理所有异常的类加入到ioc容器中
* 2、@ControllerAdvice专门处理异常的类
*/
@ControllerAdvice
public class MyJiZhongException {
@ExceptionHandler(value={ArithmeticException.class})
public ModelAndView handleException01(Exception exception){
System.out.println("全局的:handleException01..."+exception);
//
ModelAndView view = new ModelAndView("myerror");
view.addObject("ex", exception);
//视图解析器拼串
return view;
}
// @ExceptionHandler(value={Exception.class})
// public ModelAndView handleException02(Exception exception){
// System.out.println("全局的:handleException02..."+exception);
// //
// ModelAndView view = new ModelAndView("myerror");
// view.addObject("ex", exception);
// //视图解析器拼串
// return view;
// }
}
四、异常处理_ResponseStatusExceptionResolver
五、异常处理_DefaultHandlerExceptionResolver
1、对一些特殊的异常进行处理,比如:
NoSuchRequestHandlingMethodException、
HttpRequestMethodNotSupportedException、
HttpMediaTypeNotSupportedException、
HttpMediaTypeNotAcceptableException等
若ExceptionHandlerExceptionResolver等没有进行处理,会调用spring默认的异常处理方式。
① 增加页面链接:GET请求
<a href="testDefaultHandlerExceptionResolver">testDefaultHandlerExceptionResolver</a>
②增加处理器方法
//不支持GET请求
@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver(){
System.out.println("testDefaultHandlerExceptionResolver...");
return "success";
}
③出现Spring的异常错误时交给DefaultHandlerExceptionResolver处理
④DefaultHandlerExceptionResolver能解决的默认的异常
@Override
protected ModelAndView doResolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
try {
if (ex instanceof NoSuchRequestHandlingMethodException) {
return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) ex, request, response,
handler);
}
else if (ex instanceof HttpRequestMethodNotSupportedException) {
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, request,
response, handler);
}
else if (ex instanceof HttpMediaTypeNotSupportedException) {
return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, request, response,
handler);
}
else if (ex instanceof HttpMediaTypeNotAcceptableException) {
return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, request, response,
handler);
}
else if (ex instanceof MissingServletRequestParameterException) {
return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, request,
response, handler);
}
else if (ex instanceof ServletRequestBindingException) {
return handleServletRequestBindingException((ServletRequestBindingException) ex, request, response,
handler);
}
else if (ex instanceof ConversionNotSupportedException) {
return handleConversionNotSupported((ConversionNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof TypeMismatchException) {
return handleTypeMismatch((TypeMismatchException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotReadableException) {
return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotWritableException) {
return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);
}
else if (ex instanceof MethodArgumentNotValidException) {
return handleMethodArgumentNotValidException((MethodArgumentNotValidException) ex, request, response, handler);
}
else if (ex instanceof MissingServletRequestPartException) {
return handleMissingServletRequestPartException((MissingServletRequestPartException) ex, request, response, handler);
}
else if (ex instanceof BindException) {
return handleBindException((BindException) ex, request, response, handler);
}
else if (ex instanceof NoHandlerFoundException) {
return handleNoHandlerFoundException((NoHandlerFoundException) ex, request, response, handler);
}
}
catch (Exception handlerException) {
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
}
return null;
}
六、异常处理_SimpleMappingExceptionResolver
SpringMVC默认有3个异常解析器,可以通过配置的方式定义一个添加异常解析器,在SpringMVC进行异常解析的时候多一个配置的异常解析。
SimpleMappingExceptionResolver:通过配置的方式进行异常处理
1、如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
<mvc:annotation-driven></mvc:annotation-driven>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- exceptionMappings:配置哪些异常去哪些页面 -->
<property name="exceptionMappings">
<props>
<!-- key:异常全类名;value:要去的页面视图名; -->
<prop key="java.lang.NullPointerException">myerror</prop>
</props>
</property>
<!--指定错误信息取出时使用的key,默认是exception,放在request域中,可在jsp页面取出 -->
<property name="exceptionAttribute" value="ex"></property>
</bean>
2、此时进行错误异常的时候,就多了 SimpleMappingExceptionResolver,前3个解析器若处理不了在SimpleMappingExceptionResolver中定义的异常,才会调用SimpleMappingExceptionResolver的解析器进行异常解析,然后返回ModulAndView对象出来,再调用render(mv,request,response)进行渲染。(也就是说,无论异常与否,都返回mv进行渲染)