首先来回忆一下,
struts2是如何得来处理异常的,在Action里面无需处理异常, 在配置文件中通过exception节点来配置,当Action里面抛出异常的时候,
根据配置文件中的配置来跳转到响应的页面,在页面上可以通过OGNL来打印异常信息。
那么springmvc是如何来处理异常的?
springmvc通过HandlerExceptionResolver处理程序的异常,包括Handler映射,数据绑定以及目标方法执行发生的异常。
springmvc提供的HandlerExceptionResolver的实现类
其中,
ExceptionHandlerExceptionResolver是用来处理@ExceptionHandler注解的方法
示例如下
/** * 1.在@ExceptionHandler标记的方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象 * 2.@ExceptionHandler方法的入参中不能传入Map,若希望把异常信息传入错误画面上,需要使用ModelAndView * 3.@ExceptionHandler方法标记的异常有优先级的问题, * 即如果此时还有一个标记了@ExceptionHandler的方法,捕获异常是RunTimeException的话,则更匹配的异常优先 * 4.如果在对应的Controller中找不到@ExceptionHandler标记的方法,则会去标记了@ControllerAdvice标记的类中查找@ExceptionHandler方法 * @param ex * @return */ @ExceptionHandler({ArithmeticException.class}) public ModelAndView exceptionHandler(Exception ex){ System.out.println("出异常了!!!!"); ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); return mv; } @RequestMapping("testExceptionHandler") public String testExceptionHandler(@RequestParam("i") Integer i){ int result = 10/i; System.out.println("testExceptionHandler result: " + result); return "success"; }
上面的@ExceptionHandler标记的方法只能处理当前的handler中的异常,如果需要处理所有的handler的某一类型异常应该怎么做呢?
答案就是定义一个标记了@ControllerAdvice的类来统一处理,代码如下:
@ControllerAdvice
public class MyExceptionHandler { @ExceptionHandler({ArithmeticException.class}) public ModelAndView exceptionHandler(Exception ex){ System.out.println("@ControllerAdvice[出异常了!!!]"); ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); return mv; } }
ResponseStatusExceptionResolver是用来处理@ResponseStatus注解的,错误页面自定义状态码和消息,
效果如下
是如何实现的呢,很简单,只要在自定义的异常的上面追加@ResponseStatus
@ResponseStatus(value=HttpStatus.BAD_REQUEST,reason="这是一个异常消息") public class MyException extends RuntimeException { private static final long serialVersionUID = 2880943887356567043L; }
DefaultHandlerExceptionResolver是用来处理springmvc特殊的异常进行处理,比如由于方式不同,导致找不到对应的方法,效果如下:
SimpleMappingExceptionResolver是,如果希望对所有异常进行统一处理,他将异常类名映射为试图名,
在springmvc的容器中,如下配置
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView" value="error"></property> <property name="exceptionAttribute" value="ex"></property> <property name="exceptionMappings"> <props> <prop key="MyException1的全类名">error1</prop> <prop key="MyException2的全类名">error2</prop> </props> </property> </bean>
自定义异常处理器
@Controller注解的类中,添加如下测试代码(如果参数kind是1,则抛出MyException1,如果参数kind是2,则抛出MyException2)
@RequestMapping("testException")
public String testException(@RequestParam("kind") Integer kind) throws MyException1, MyException2{
if(kind == 1){
throw new MyException1("this is Exception One!!");
}else if(kind == 2){
throw new MyException2("this is Exception two");
}
return "success";
}
自定义异常MyException1和MyException2
自定义MyExceptionHandler,代码如下
public class MyExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Map<String, Object> model = new HashMap<String, Object>(); model.put("ex", ex); if(ex instanceof MyException1){ return new ModelAndView("error1", model);
// 对应页面 error1.jsp }else if(ex instanceof MyException2){ return new ModelAndView("error2", model);
// 对应页面 error2.jsp } return new ModelAndView("error", model);
// 对应页面error } }
另外DispatcherSerlvet默认装配的HandlerExceptionResolver
(注意点:由于AnnotationMethodHandlerExceptionResolver已经过期了,所以开发中都需要配置<mvc:annotation-driven ></mvc:annotation-driven>)