springMVC提供的异常处理主要有两种方式,一种是直接实现本身的HandlerExceptionResolver,固然这也包括使用Spring已经为咱们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver,另外一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。和以前同样,前者至关于全局管理的异常,后者只针对当前controller有效javascript
首先定义一个全局异常类,能够看出这个类会把异常打印在控制台,而且放入model中,以即可以在jsp页面上展现出来css
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class MyExceptionResolver implements HandlerExceptionResolver{ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("==============异常开始============="); ex.printStackTrace(); System.out.println("==============异常结束============="); //设置返回页面为error.jsp ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex.toString().replaceAll("\n", "<br/>")); return mv; } }
而后在error.jsp中显示异常html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>应用程序异常 (500)</title> </head> <body> <div> <h1>应用程序异常</h1> <p>抱歉!您访问的页面出现异常,请稍后重试或联系管理员。</p> <p><a href="#">详 情</a> <a href="javascript:history.back(-1)">返 回</a> </p> <div style="display:none;text-align: left;" id="err">${exception }</div> </div> </body> </html>
接着在springMVC.xml中配置这个异常java
<!--配置全局异常类--> <bean id="exceptionResolver" class="main.java.controller.MyExceptionResolver"/>
在控制器里面模拟调用web
@RequestMapping(value = "/hello",method = RequestMethod.GET) public String hello(Model model){ String str = "asbd123"; //这里会报NumberFormatException异常,而后spring会自动捕捉这个异常 int a = Integer.parseInt(str); return "hello"; }
而后访问localhost:8888/hello,页面就会显示以下 面试
一样的再控制台会输出咱们的异常信息 spring
到此这就是一个全局异常.app
局部异常使用使用@ExceptionHandler进行处理,具体以下jsp
使用@ExceptionHandler进行处理有一个很差的地方是进行异常处理的方法必须与出错的方法在同一个Controller里面测试
//建立处理异常的类,这个类会处理当前控制器下的Myexception这个异常 @ExceptionHandler(Myexception.class) public String getError(Myexception myexception,Model model){ System.out.println("==============异常开始============="); myexception.printStackTrace(); System.out.println("==============异常结束============="); model.addAttribute("exception",myexception.getMessage()); return "error"; } //当前这个请求会抛出异常 @RequestMapping(value = "/hello",method = RequestMethod.GET) public String hello(Model model) throws Myexception { if (true){ throw new Myexception("出错了"); } return "hello"; }
对应的JSP视图中会显示出相应的错误信息
对应的控制台也会输出相应的信息
既然在SpringMVC中有两种处理异常的方式,那么就存在一个优先级的问题:
当发生异常的时候,SpringMVC会以下处理:
Spring实现了一个SimpleMappingExceptionResolver,这二者都是继承自抽象类AbstractHandlerExceptionResolver,而AbstractHandlerExceptionResolver是实现了HandlerExceptionResolver接口的resolveException方法的,并由此抽取出两个抽象方法,一个是在进行异常处理以前执行的方法prepareResponse(exception, response),一个是进行异常解析的doResolveException(request, response, handler, exception)方法。
SimpleMappingExceptionResolver,顾名思义就是经过简单的映射关系来决定由哪一个视图来处理当前的错误信息。SimpleMappingExceptionResolver提供了经过异常类型exceptionMappings来进行异常与视图之间的映射关系,提供了在发生异常时经过statusCodes来映射异常返回的视图名称和对应的HttpServletResponse的返回码。并且能够经过defaultErrorView和defaultErrorCode来指定默认值,defaultErrorView表示当没有在exceptionMappings里面找到对应的异常类型时就返回defaultErrorView定义的视图,defaultErrorCode表示在发生异常时当没有在视图与返回码的映射关系statusCodes里面找到对应的映射时默认返回的返回码。在使用SimpleMappingExceptionResolver时,当发生异常的时候,SimpleMappingExceptionResolver将会把当前的异常对象放到自身属性exceptionAttribute中,当没有指定exceptionAttribute时,exceptionAttribute就是用默认值exception。
下面试一个其xml代码的简单配置
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="NumberFormatException">number</prop><!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图 --> <prop key="NullPointerException">null</prop> </props> </property> <property name="defaultErrorView" value="exception"/><!-- 表示当抛出异常但没有在exceptionMappings里面找到对应的异常时 返回名叫exception的视图--> <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的对应关系 --> <props> <prop key="number">500</prop><!-- 表示在发生NumberFormatException时返回视图number,而后这里定义发生异常时视图number对应的HttpServletResponse的返回码是500 --> <prop key="null">503</prop> </props> </property> <property name="defaultStatusCode" value="404"/><!-- 表示在发生异常时默认的HttpServletResponse的返回码是多少,默认是200 --> </bean>
下面是引起这些异常的测试代码
@Controller @RequestMapping("/test") public class TestController { @RequestMapping("/null") public void testNullPointerException() { Blog blog = null; //这里就会发生空指针异常,而后就会返回定义在SpringMVC配置文件中的null视图 System.out.println(blog.getId()); } @RequestMapping("/number") public void testNumberFormatException() { //这里就会发生NumberFormatException,而后就会返回定义在SpringMVC配置文件中的number视图 Integer.parseInt("abc"); } @RequestMapping("/default") public void testDefaultException() { if (1==1) //因为该异常类型在SpringMVC的配置文件中没有指定,因此就会返回默认的exception视图 throw new RuntimeException("Error!"); } }
最后在jsp页面中能够访问这些异常
<%@ page language="java" import="java.util.*" pageEncoding="GB18030" isErrorPage="true"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'number.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> NumberFormatException. <br> <%=exception.getMessage() %><br/> <%=exception %><br/><span style="color: #3366ff;"><!-- 这是JSP中的内置对象exception --></span> <%=request.getAttribute("ex") %><br><span style="color: #3366ff;"><!-- 这是SpringMVC放在返回的Model中的异常对象 --></span> <%=request.getAttribute("javax.servlet.error.status_code") %><span style="color: #3366ff;"><!-- HttpServletResponse返回的错误码信息,由于前面已经配置了NumberFormatException的错误码返回值为888,因此这里应该显示888 --></span> </body> </html>
参考资料:http://www.makeru.com.cn/