常用的SpringMVC异常处理方式主要是三种:
1.使用系统定义好的异常处理器 SimpleMappingExceptionResolver
2.使用自定义异常处理器
3.使用异常处理注解
SimpleMappingExecptionResolver 异常处理器
该方式只需要在SpringMVC配置文件中注册该异常处理器Bean即可。该Bean比较特殊,没有id属性
无需显示调用或被注入给其他<bean/>,当异常发生时 会自动执行该类
1.自定义异常类
1 public class NameException extends Exception { 2 public NameException() { 3 super(); 4 } 5 6 public NameException(String message) { 7 super(message); 8 } 9 }
2.修改Controller
1 @Controller 2 @RequestMapping("/test") 3 public class MyController { 4 5 @RequestMapping(value = "/exception.do") 6 public ModelAndView method(String name,int age) throws NameException, AgeException { 7 //int i = 3 / 0; 8 9 if(!"beijing".equals(name)){ 10 //当异常抛出时,会自动执行异常处理器类 11 throw new NameException("用户名不准确!"); 12 } 13 14 if(age > 65){ 15 throw new AgeException("年龄过大!"); 16 } 17 18 ModelAndView mv = new ModelAndView(); 19 mv.addObject("name", name); 20 mv.addObject("age",age); 21 //需在setViewName() 指定的视图前添加 redirect,(默认添加的 forword)才能重定向到 指定资源 22 //重定向 后,是一个新的request,当把数据添加到Model中 时,会自动往路径后面添加上参数(a.jsp?name=&age=) 23 mv.setViewName("redirect:/a.jsp"); 24 25 return mv; 26 } 27 28 }
3.注册异常处理器
1 <!-- 注册 SimpleMappingExceptionResolver 这个异常处理器(系统定义好的), 当异常发生时自动执行该类 --> 2 <bean 3 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> 4 5 <!-- 默认的错误页面 --> 6 <property name="defaultErrorView" value="/WEB-INF/errors/defaultErrorPage.jsp"></property> 7 8 <!-- 用于指定不同类型的异常对应的 处理页面 --> 9 <property name="exceptionMappings"> 10 <props> 11 <prop key="com.springmvc.exceptions.NameException">/WEB-INF/errors/nameErrorPage.jsp</prop> 12 <prop key="com.springmvc.exceptions.AgeException">/WEB-INF/errors/ageErrorPage.jsp</prop> 13 </props> 14 </property> 15 16 <!-- 得到exceptionAttribute属性 , 得到捕获到的异常对象ex ,可以用ex得到一些异常信息 --> 17 <!-- 应该是将ex对象放到 request 域中了,前台页面可以取出显示 --> 18 <property name="exceptionAttribute" value="ex"></property> 19 </bean>
exceptionMappings:Properties 类型属性,用于指定具体的不同类型的异常所对应的异 常响应页面。Key 为异常类的全限定性类名,value 则为响应页面路径
defaultErrorView:指定默认的异常响应页面。若发生的异常不是 exceptionMappings 中 指定的异常,则使用默认异常响应页面。
exceptionAttribute:捕获到的异常对象。一般异常响应页面中使用。
4.定义异常响应页面
1 <body> 2 3 <!-- 4 param.name 的 底层执行的 是 request.getParameter("name"); 5 requestScope.name 的底层执行的 是 request.getAttribute(); 6 --> 7 8 Age Error Page 9 ${ex.message } 10 </body>
自定义异常处理器
使用SpringMVC 定义好的SimpleMappingExeceptionResolver异常处理器,可以发生指定异常后的跳转
但若要实现 在捕获指定异常时,执行一些操作的目的,它是完成不了的。此时,就需要自定义异常处理器
自定义异常处理器,需要实现HandlerExeceptionResolver接口,并且该类需要在SpringMVC配置文件中配置
a)定义异常处理器
当一个类实现了HandlerExeceptionResolver接口后,只要有异常发生,
无论什么异常,都会自动执行接口方法 resolveExeception()
1 //设置自定义 异常处理器的好处:在捕获到指定异常后,可以完成一些操作,SimpleMappingExceptionResolver 只能完成页面的跳转,无法执行更多 2 public class MyExceptionResolver implements HandlerExceptionResolver { 3 4 //当一个类实现了 HandlerExceptionResolver 接口后,只要有异常发生,无论什么异常,都会执行resolveException方法 (在该异常处理器 注册了的前提下) 5 @Override 6 public ModelAndView resolveException(HttpServletRequest request, 7 HttpServletResponse response, Object handler, Exception ex) { 8 ModelAndView mv = new ModelAndView(); 9 //将异常对象加入 数据模型中 10 mv.addObject("ex",ex); 11 12 13 //设置默认的错误处理页面 (需要放在自定义异常的前面,不然自定义异常的页面路径可能会被覆盖) 14 mv.setViewName("/WEB-INF/errors/defaultErrorPage.jsp"); 15 16 //设置 NameException的 错误处理页面 17 if(ex instanceof NameException) { 18 System.out.println("执行一些操作 NameException"); 19 mv.setViewName("/WEB-INF/errors/nameErrorPage.jsp"); 20 } 21 //设置 AgeException的 错误处理页面 22 if(ex instanceof AgeException) { 23 System.out.println("执行一些操作 AgeException"); 24 mv.setViewName("/WEB-INF/errors/ageErrorPage.jsp"); 25 } 26 27 28 return mv; 29 } 30 31 }
b)注册异常处理器
1 <!-- 注册 MyExceptionResolver 自定义异常处理器, 当异常发生时自动执行该类 (只需要注册就好,其他都已经到 该处理器里面设置好了)--> 2 <bean class="com.springmvc.ExceptionResolver.MyExceptionResolver"/>
异常处理注解
使用注解 @ExceptionHandler 可以将一个方法指定为异常处理方法。该注解只有一个可选属性 value,
是一个Class<?> 数组,用于指定该注解的方法所要处理的异常类,即所要匹配的异常
而被注解的方法,其返回值可以是ModelAndView、String或void,方法名随意,方法参数可以是Exeception及其子类对象
HttpServletRequest、HttpServletResponse等。系统会自动为这些方法参数赋值
a) 定义异常处理的Controller
1 //构造这样一个 父类,让需要用到 这些 异常处理 的 Controller 继承这个父类即可 2 //如果不抽取出来,只写在某个 Controller 中,那么这些 异常处理方法 只会在该处理器生效时生效 3 //注意,这里加上 @Controller ,不然里面 方法是不会加载的 4 @Controller 5 public class BaseController { 6 7 // 使用 ExceptionHandler ,将一个方法声明为 异常处理方法,可以使用 value 属性,指定该异常处理方法用于处理哪个异常 8 // 指明 用于处理 NameException 9 @ExceptionHandler(value = AgeException.class) 10 public ModelAndView handlerAgeException(Exception ex) { 11 ModelAndView mv = new ModelAndView(); 12 mv.addObject("ex", ex); 13 System.out.println("执行一些操作 AgeException"); 14 mv.setViewName("/WEB-INF/errors/ageErrorPage.jsp"); 15 16 return mv; 17 } 18 19 // 指明 用于处理 AgeException 20 @ExceptionHandler(value = NameException.class) 21 public ModelAndView handlerNameException(Exception ex) { 22 ModelAndView mv = new ModelAndView(); 23 mv.addObject("ex", ex); 24 System.out.println("执行一些操作 NameException"); 25 mv.setViewName("/WEB-INF/errors/nameErrorPage.jsp"); 26 27 return mv; 28 } 29 30 // 默认异常处理 31 @ExceptionHandler 32 public ModelAndView handlerdefaultException(Exception ex) { 33 ModelAndView mv = new ModelAndView(); 34 mv.addObject("ex", ex); 35 mv.setViewName("/WEB-INF/errors/defaultErrorPage.jsp"); 36 return mv; 37 } 38 39 }
b) 修改Controller,让普通Controller继承自定义好的异常处理 Controller
1 //当MyController 出现异常时,会去找BaseController 是否定义了这个异常 2 public class MyController extends BaseController {