SpringMVC中的异常处理
来源:互联网 发布:淘宝卖空军一号真的吗 编辑:程序博客网 时间:2024/05/22 06:55
Spring MVC通过HandlerExceptionResolver处理程序的异常,包括Handler 映射、数据绑定以及目标方法执行时发生的异常。在Eclipse中可以查看到HandleExceptionResolver接口的实现类:
如果我们没有在springmvc配置文件中配置<mvc:annotation-driven/>,那么DispatcherServlet会默认装配AnnotationMethodHandlerExceptionResolver、DefaultHandlerExceptionResolver和ResponseStatusException三种解析器,但是其中AnnotationMethodHandlerExceptionResolver已经过期了。所以我们配置<mvc:annotation-driven/>,将会把AnnotationMethodHandlerExceptionResolver替换为ExceptionHandlerExceptionResolver。
下面的例子中,我们都默认已经在spring配置文件中配置了<mvc:annotation-driven/>。
ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver主要用于处理Handler 中用@ExceptionHandler注解标记的方法,示例如下:
页面
index.jsp
<a href="testExceptionHandlerExceptionResolver?i=0">Test ExceptionHandlerExceptionResolver</a>
error.jsp
<h4>Error Page</h4>${exception }
控制器
private final static String ERROR = "error"; //异常处理器 //value = ArithmeticException.class声明捕获数学异常 @ExceptionHandler(value = ArithmeticException.class) public ModelAndView handleArithmeticException(Exception ex) { ModelAndView mv = new ModelAndView(ERROR); System.out.println("出异常了:" + ex); mv.addObject("exception", ex); return mv; } //定义一个可以抛出ArithmeticException异常的方法 @RequestMapping("/testExceptionHandlerExceptionResolver") public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i) { System.out.println("result:" + 10 / i); return SUCCESS; }
运行程序:
点击index.jsp中的超链接,异常处理器会捕获到异常,在控制台输出:
并跳转到error.jsp,且在该页面打印了异常信息:
需要注意的是:
- @ExceptionHandler标记的方法的入参中不能传入Map。 若希望把异常信息传导页面上, 需要使用 ModelAndView 作为返回值。
- @ExceptionHandler 方法标记的异常有优先级的问题。如果我们在上面的例子中同时声明了可以捕获ArithmeticException异常和RuntimeException异常的两个异常处理器,那么会使用匹配度更高的,即捕获ArithmeticException异常的异常处理器。
- 通过以上方式创建的异常处理器只能处理该控制器类内部的异常,若需要统一配置可以捕获所有控制器类抛出的异常,可以新建一个异常处理器类,在类的声明处用@ControllerAdvice注解标记即可。如果在当前 控制器类 中找不到 @ExceptionHandler 方法来处理当前方法出现的异常, 则将去 @ControllerAdvice 标记的类中查找 @ExceptionHandler 标记的方法来处理异常。例如,我们现在创建一个异常处理器类,并在其中定义一个可以处理数学异常的方法:
@ControllerAdvicepublic class SpringMVCTestExceptionHandler { private static final String ERROR = "error"; @ExceptionHandler(value=ArithmeticException.class) public ModelAndView handleArithmeticException1(Exception ex){ ModelAndView mv = new ModelAndView(ERROR); System.out.println("[出异常了]:"+ex); mv.addObject("exception",ex); return mv; }}
注释掉之前定义的handleArithmeticException方法,运行程序,与之前的例子类似,仍然跳转到error.jsp,但是在控制台输出:
表示执行的是我们新定义的handleArithmeticException1方法,注意,如果不注释掉handleArithmeticException方法,那么会优先执行handleArithmeticException方法,因为handleArithmeticException方法和抛出异常的testExceptionHandlerExceptionResolver方法定义在同一个控制器类中,testExceptionHandlerExceptionResolver方法抛出异常后会先在当前 控制器类 中找 @ExceptionHandler方法来处理当前方法出现的异常,如果找不到,才会去 @ControllerAdvice 标记的类中查找 @ExceptionHandler 标记的方法来处理异常。
ResponseStatusExceptionResolver
ResponseStatusExceptionResolver的作用是在异常及异常父类中找到@ResponseStatus注解,然后使用这个注解的属性进行处理。下面举例说明:
页面
<a href="testResponseStatusExceptionResolver?i=13">Test ResponseStatusExceptionResolver</a>
定义一个异常类
@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名和密码不匹配")public class UserNameNotMatchPasswordException extends RuntimeException{ /** * */ private static final long serialVersionUID = 1L;}
模拟一个可以抛出上述异常的方法
//定义一个可以抛出UserNameNotMatchPasswordException异常的方法 @RequestMapping("/testResponseStatusExceptionResolver") public String testResponseStatusExceptionResolver(@RequestParam("i") int i) { if(i==13) throw new UserNameNotMatchPasswordException(); return SUCCESS; }
运行程序,由于抛出了异常,并且我们没有定义任何异常处理器对该异常进行处理,那么会出现我们定制的异常页面:
此外,@ResponseStatus注解还可以用来标记方法:
@ResponseStatus(reason="测试",value=HttpStatus.NOT_FOUND) @RequestMapping("/testResponseStatusExceptionResolver") public String testResponseStatusExceptionResolver(@RequestParam("i") int i) { if(i==13) throw new UserNameNotMatchPasswordException(); System.out.println("testResponseStatusExceptionResolver..."); return SUCCESS; }
现在,我们在浏览器中令i=10,这样方法是不会抛出UserNameNotMatchPasswordException异常的,结果程序跳转到了如下页面:
但是控制台上输出了如下信息,说明这个方法被正常地执行了:
DefaultHandlerExceptionResolver
对一些特殊的异常进行处理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException等,具体处理哪些异常可以在DefaultHandlerExceptionResolver源码中查看doResolveException()方法。
SimpleMappingExceptionResolver
SimpleMappingExceptionResolver可以将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。下面进行测试:
页面
index.jsp
<a href="testSimpleMappingExceptionResolver?i=21">Test SimpleMappingExceptionResolver</a>
error.jsp
<h4>Error Page</h4>${exception }
控制器
// 定义一个可以抛出ArrayIndexOutOfBoundsException异常的方法 @RequestMapping("/testSimpleMappingExceptionResolver") public String testSimpleMappingExceptionResolver(@RequestParam("i") int i) { int[] values = new int[20]; System.out.println(values[i]); return SUCCESS; }
spring配置文件
<!-- 配置使用 SimpleMappingExceptionResolver 来映射异常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean>
运行程序:
由于目标方法抛出了数组下标越界异常,程序跳转到了error.jsp页面,并且在页面上打印了异常信息,这是因为在SimpleMappingExceptionResolver中有一个String类型的属性exceptionAttribute,其默认值为exception,所以我们在error.jsp中通过${exception }可以获取到。也可以在配置文件中配置exceptionAttribute的值,例如:
<!-- 配置使用 SimpleMappingExceptionResolver 来映射异常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionAttribute" value="ex"></property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean>
那么,此时需要在error.jsp中通过如下方式在可以获取到异常信息:
<h4>Error Page</h4>${ex }
- SpringMVC中的异常处理
- SpringMVC中的异常处理
- SpringMVC中的异常处理
- SpringMVC 中的异常处理
- SpringMVC中的异常处理
- SpringMVC中的异常处理
- SpringMVC中的异常处理
- SpringMVC中的统一异常处理
- SpringMvc中的异常处理ExceptionHandlerExceptionResolver的使用
- Springmvc异常处理【Springmvc】
- 【SpringMVC学习07】SpringMVC中的统一异常处理
- 【SpringMVC学习07】SpringMVC中的统一异常处理
- springMVC异常处理
- springmvc 异常处理
- springMVC 全局异常处理
- springMVC之异常处理
- SpringMVC的异常处理
- SpringMVC异常处理
- Generate Parentheses
- gcc -M 参数详解
- 深入理解Java:类加载机制及反射
- 安卓海报轮播
- 数据结构中的七种排序算法介绍
- SpringMVC中的异常处理
- 【bzoj1010】玩具装箱toy 斜率优化dp
- 使用文件输出hello
- java之yield(),sleep(),wait()区别详解-备忘笔记
- hbase集群搭建
- JZOJ4893【NOIP2016提高A组集训第15场11.14】过河
- java8内置函数式接口
- PTA 4-3 二叉树的遍历
- web服务端和游戏服务端的区别