springMVC对异常处理的支持

简介: springMVC对异常处理的支持博客分类: SpringMVCspringMVCException统一处理HandlerExceptionResolverSimpleMappingExceptionResolver 无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了。

无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了。跟其他MVC框架一样,springMVC也有自己的异常处理机制。
springMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,当然这也包括使用Spring已经为我们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。


1、实现自己的HandlerExceptionResolver,HandlerExceptionResolver是一个接口,springMVC本身已经对其有了一个自身的实现——DefaultHandlerExceptionResolver,该解析器只是对其中的一些比较典型的异常进行了拦截,然后返回对应的错误码,当然你也可以继承DefaultHandlerExceptionResolver类,然后重写其中的一些异常处理方法来实现自己的异常处理。

Java代码   收藏代码
  1. import javax.servlet.http.HttpServletRequest;  
  2. import javax.servlet.http.HttpServletResponse;  
  3.   
  4. import org.springframework.web.servlet.HandlerExceptionResolver;  
  5. import org.springframework.web.servlet.ModelAndView;  
  6.   
  7. public class ExceptionHandler implements HandlerExceptionResolver {  
  8.   
  9.     @Override  
  10.     public ModelAndView resolveException(HttpServletRequest request,  
  11.             HttpServletResponse response, Object handler, Exception ex) {  
  12.         // TODO Auto-generated method stub  
  13.         return new ModelAndView("exception");  
  14.     }  
  15.   
  16. }  

 上述的resolveException的第4个参数表示对哪种类型的异常进行处理。因为Exception类是所有异常类的基类,所以如果想根据异常类型的不同来进行不同的处理的话,可以在resolveException方法里面根据不同的异常类型进行不同的处理,返回不同的异常视图。如:

Java代码   收藏代码
  1. public class ExceptionHandler implements HandlerExceptionResolver {  
  2.   
  3.     @Override  
  4.     public ModelAndView resolveException(HttpServletRequest request,  
  5.             HttpServletResponse response, Object handler, Exception ex) {  
  6.         // TODO Auto-generated method stub  
  7.         if (ex instanceof NumberFormatException) {  
  8.             //doSomething...  
  9.             return new ModelAndView("number");  
  10.         } else if (ex instanceof NullPointerException) {  
  11.             //doSomething...  
  12.             return new ModelAndView("null");  
  13.         }  
  14.         return new ModelAndView("exception");  
  15.     }  
  16.   
  17. }  
 

 

定义了这样一个异常处理器之后就要在applicationContext中定义这样一个bean对象,如:

Xml代码   收藏代码
  1. <bean id="exceptionResolver" class="com.tiantian.xxx.web.handler.ExceptionHandler"/>  

Spring除了实现了一个DefaultHandlerExceptionResolver之外,还实现了一个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。

以下是一个简单的例子:

(1)SpringMVC的servlet配置文件中申明一个SimpleMappingExceptionResolver bean,并通过配置属性exceptionMappings和defaultExceptionView来指定异常和视图的对应关系。

Xml代码   收藏代码
  1. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
  2.     <property name="exceptionMappings">  
  3.         <props>  
  4.             <prop key="NumberFormatException">number</prop><!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图 -->  
  5.             <prop key="NullPointerException">null</prop>  
  6.         </props>  
  7.     </property>  
  8.     <property name="defaultErrorView" value="exception"/><!-- 表示当抛出异常但没有在exceptionMappings里面找到对应的异常时 返回名叫exception的视图-->  
  9.     <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的对应关系 -->  
  10.         <props>  
  11.             <prop key="number">500</prop><!-- 表示在发生NumberFormatException时返回视图number,然后这里定义发生异常时视图number对应的HttpServletResponse的返回码是500 -->  
  12.             <prop key="null">503</prop>  
  13.         </props>  
  14.     </property>  
  15.     <property name="defaultStatusCode" value="404"/><!-- 表示在发生异常时默认的HttpServletResponse的返回码是多少,默认是200 -->  
  16. </bean>  

(2)如下访问:

Java代码   收藏代码
  1. @Controller  
  2. @RequestMapping("/test")  
  3. public class TestController {  
  4.   
  5.     @RequestMapping("/null")  
  6.     public void testNullPointerException() {  
  7.         Blog blog = null;  
  8.         //这里就会发生空指针异常,然后就会返回定义在SpringMVC配置文件中的null视图  
  9.         System.out.println(blog.getId());  
  10.     }  
  11.       
  12.     @RequestMapping("/number")  
  13.     public void testNumberFormatException() {  
  14.         //这里就会发生NumberFormatException,然后就会返回定义在SpringMVC配置文件中的number视图  
  15.         Integer.parseInt("abc");  
  16.     }  
  17.       
  18.     @RequestMapping("/default")  
  19.     public void testDefaultException() {  
  20.         if (1==1)  
  21.             //由于该异常类型在SpringMVC的配置文件中没有指定,所以就会返回默认的exception视图  
  22.             throw new RuntimeException("Error!");  
  23.     }  
  24.       
  25. }  

 

(3)Jsp页面中可以访问到的异常对象,这里以NumberFormatException的返回视图number.jsp作为示例:

Jsp代码   收藏代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="GB18030" isErrorPage="true"%>  
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6.   
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  8. <html>  
  9.   <head>  
  10.     <base href="<%=basePath%>">  
  11.       
  12.     <title>My JSP 'number.jsp' starting page</title>  
  13.       
  14.     <meta http-equiv="pragma" content="no-cache">  
  15.     <meta http-equiv="cache-control" content="no-cache">  
  16.     <meta http-equiv="expires" content="0">      
  17.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  18.     <meta http-equiv="description" content="This is my page">  
  19.     <!--  
  20.     <link rel="stylesheet" type="text/css" href="styles.css">  
  21.     -->  
  22.   
  23.   </head>  
  24.     
  25.   <body>  
  26.     NumberFormatException. <br>  
  27.     <%=exception.getMessage() %><br/>  
  28.     <%=exception %><br/><span style="color: #3366ff;"><!-- 这是JSP中的内置对象exception --></span>  
  29.   
  30.   
  31.   
  32.     <%=request.getAttribute("ex") %><br><span style="color: #3366ff;"><!-- 这是SpringMVC放在返回的Model中的异常对象 --></span>  
  33.   
  34.   
  35.   
  36.     <%=request.getAttribute("javax.servlet.error.status_code") %><span style="color: #3366ff;"><!-- HttpServletResponse返回的错误码信息,因为前面已经配置了NumberFormatException的错误码返回值为888,所以这里应该显示888 --></span>  
  37.   
  38.   
  39.   
  40.   </body>  
  41. </html>  
   

(4)当请求/test/number.do的时候会返回定义好的number视图,返回结果如下:


 

2、使用@ExceptionHandler进行处理

使用@ExceptionHandler进行处理有一个不好的地方是进行异常处理的方法必须与出错的方法在同一个Controller里面

如:

Java代码   收藏代码
  1. import org.springframework.stereotype.Controller;  
  2. import org.springframework.web.bind.annotation.ExceptionHandler;  
  3. import org.springframework.web.bind.annotation.RequestMapping;  
  4.   
  5. import com.tiantian.blog.web.servlet.MyException;  
  6.   
  7. @Controller  
  8. public class GlobalController {  
  9.   
  10.       
  11.     /** 
  12.      * 用于处理异常的 
  13.      * @return 
  14.      */  
  15.     @ExceptionHandler({MyException.class})  
  16.     public String exception(MyException e) {  
  17.         System.out.println(e.getMessage());  
  18.         e.printStackTrace();  
  19.         return "exception";  
  20.     }  
  21.       
  22.     @RequestMapping("test")  
  23.     public void test() {  
  24.         throw new MyException("出错了!");  
  25.     }  
  26.       
  27.       
  28. }  

 这里在页面上访问test方法的时候就会报错,而拥有该test方法的Controller又拥有一个处理该异常的方法,这个时候处理异常的方法就会被调用



优先级

既然在SpringMVC中有两种处理异常的方式,那么就存在一个优先级的问题:

当发生异常的时候,SpringMVC会如下处理:

(1)SpringMVC会先从配置文件找异常解析器HandlerExceptionResolver

(2)如果找到了异常异常解析器,那么接下来就会判断该异常解析器能否处理当前发生的异常

(3)如果可以处理的话,那么就进行处理,然后给前台返回对应的异常视图

(4)如果没有找到对应的异常解析器或者是找到的异常解析器不能处理当前的异常的时候,就看当前的Controller中有没有提供对应的异常处理器,如果提供了就由Controller自己进行处理并返回对应的视图

(5)如果配置文件里面没有定义对应的异常解析器,而当前Controller中也没有定义的话,那么该异常就会被抛出来。

相关文章
|
28天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
123 29
|
2月前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
71 4
|
3月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
261 2
|
4月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
5月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
4月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
83 2
|
4月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
344 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
5月前
|
XML 缓存 前端开发
springMVC02,restful风格,请求转发和重定向
文章介绍了RESTful风格的基本概念和特点,并展示了如何使用SpringMVC实现RESTful风格的请求处理。同时,文章还讨论了SpringMVC中的请求转发和重定向的实现方式,并通过具体代码示例进行了说明。
springMVC02,restful风格,请求转发和重定向
|
6月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
6月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)