spring mvc 异常处理(转)

标签: spring mvc 异常处理 | 发表时间:2014-03-24 10:25 | 作者:这些年
出处:http://www.iteye.com

链接:http://gaojiewyh.iteye.com/blog/1297746 (附源码)
链接:http://zywang.iteye.com/blog/983801 
链接:http://www.cnblogs.com/xguo/p/3163519.html 
链接:http://fuliang.iteye.com/blog/947191 
链接:http://blog.csdn.net/FansUnion/article/details/17038103

链接:http://cgs1999.iteye.com/blog/1547197(附源码)

 

      Spring3.0对异常的处理通过HandlerExceptionResolver来实现。HandlerExceptionResolver有4个实现类DefaultHandlerExceptionResolver、AnnotationMethodExceptionResolver、ResponseStatusExceptionResolver、SimpleMappingExceptionResolver。
      Spring3.0对异常的处理主要可通过这两种方式:一种是使用HandlerExceptionResolver接口;一种是在@Controller处理器内部使用@ExceptionHandler注解。使用第一种方式可以实现全局异常控制,并且Spring已经提供了一个默认的实现类SimpleMappingExceptionResolver;使用第二种方式可以在Controller内部实现更个性化异常处理方式。

 

---方式一:HandlerExceptionResolver接口,复写resolveException()方法
      springmvc通过HandlerExceptionResolver处理程序的异常,该接口仅有一个方法ModelAndView  resolveException(HttpServletRequest request,              HttpServletResponse response, Object handler, Exception ex)。我们可复写该方法实现全局异常的处理。
      当发生异常时,springmvc会调用resolveException()方法,并返回一个ModelAndView对象。如果该方法返回了null,Spring会搜索所有注册在其环境中的实现了HandlerExceptionResolver接口的Bean,逐个执行,直到返回一个ModelAndView对象,最后转到ModelAndView对应的视图作为一个异常报告页面!

 

  1. /** 
  2.  * 基于HandlerExceptionResolver接口的异常处理类 
  3.  * 这个类必须声明到Spring中去,让Spring管理它,你可以使用@Component标签: 
  4.  *   <context:component-scan base-package="test.*" /> 
  5.  * 或者使用在配置文件通过<bean/>节点配置: 
  6.  *   <bean id="exceptionResolver" class="test.CustomExceptionHandler "/> 
  7.  */  
  8. @Component  
  9. public class CustomExceptionHandler implements HandlerExceptionResolver {  
  10.     @Override  
  11.     public ModelAndView resolveException(HttpServletRequest request,  
  12.             HttpServletResponse response, Object object, Exception exception) {  
  13.         if(exception instanceof IOException){  
  14.             return new ModelAndView("ioexp");  
  15.         }else if(exception instanceof SQLException){  
  16.             return new ModelAndView("sqlexp");  
  17.         }  
  18.         return null;  
  19.     }  
  20. }  

---区分ajax请求和普通http请求进行异常处理返回:

 

  1. /** 
  2.  * 代码2: 
  3.  * 说明:当在系统应用中出现普通异常时,根据是系统异常还是应用异常,跳到相应的界面, 
  4.  * 当ajax异常时,在ajax的error中可直接获得异常。普通的异常我们都配置好了界面,系统会自动跳转。 
  5.  */  
  6. public class CustomSimpleMappingExceptionResolver extends SimpleMappingExceptionResolver {  
  7.     @Override  
  8.     protected ModelAndView doResolveException(HttpServletRequest request,  
  9.             HttpServletResponse response, Object handler, Exception ex) {  
  10.         // Expose ModelAndView for chosen error view.  
  11.         String viewName = determineViewName(ex, request);  
  12.         if (viewName != null) {// JSP格式返回  
  13.             if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request  
  14.                     .getHeader("X-Requested-With")!= null && request  
  15.                     .getHeader("X-Requested-With").indexOf("XMLHttpRequest") > -1))) {  
  16.                 // 如果不是异步请求  
  17.                 // Apply HTTP status code for error views, if specified.  
  18.                 // Only apply it if we're processing a top-level request.  
  19.                 Integer statusCode = determineStatusCode(request, viewName);  
  20.                 if (statusCode != null) {  
  21.                     applyStatusCodeIfPossible(request, response, statusCode);  
  22.                 }  
  23.                 return getModelAndView(viewName, ex, request);  
  24.             } else {// JSON格式返回  
  25.                 try {  
  26.                     PrintWriter writer = response.getWriter();  
  27.                     writer.write(ex.getMessage());  
  28.                     writer.flush();  
  29.                 } catch (IOException e) {  
  30.                     e.printStackTrace();  
  31.                 }  
  32.                 return null;  
  33.             }  
  34.         } else {  
  35.             return null;  
  36.         }  
  37.     }  
  38. }  


---方式二:@ExceptionHandler

 

AnnotationMethodExceptionResolver:springmvc也默认配置了AnnotationMethodExceptionResolver,它允许通过@ExceptionHandler指定处理特定异常的方法。@ExceptionHandler:处理同一个类内触发的局部异常(如果要让其处理多个需拦截异常的处理器,则可另其他类继承此类!)

 

  1. @Controller  
  2. //可以被其他处理器继承  
  3. public class MyExceptionFilter {  
  4.     ...  
  5.     //该处理器类中的所有方法抛出的异常都可由此方法捕获并处理  
  6.     //该注解也可制定多个异常类,如@ExceptionHandler(value={IOException.class,SQLException.class})    
  7.     @ExceptionHandler(Exception.class)  
  8.     public String handleException(Exception e, HttpServletRequest req) {          
  9.   
  10.         System.out.println("exception name: " + e.getClass().toString());//异常名  
  11.         System.out.println("exception cause: " + e.getCause());  
  12.         System.out.println("exception msg: " + e.getLocalizedMessage());  
  13.         //e.printStackTrace();   
  14.         StackTraceElement[] ste = e.getStackTrace();  
  15.         StringBuffer sb_e = new StringBuffer();  
  16.         for(int j=0;j<ste.length;j++){  
  17.             if(ste[j].toString().contains("xxxx")) {  
  18.                 sb_e.append(ste[j].toString()+",  ");  
  19.             }  
  20.         }     
  21.         System.out.println("Exception detail: ");//异常详细信息  
  22.         System.out.println(sb_e.toString());  
  23.           
  24.         StringBuffer sbUrl = new StringBuffer();//拼url  
  25.         System.out.println("request method: "+req.getMethod());//get,post  
  26.         System.out.println("request encode: " + req.getCharacterEncoding());//编码  
  27.         System.out.println("request mapping: "+req.getRequestURL().toString());//请求url方法  
  28.         sbUrl.append(req.getRequestURL().toString());  
  29.         Enumeration en = req.getParameterNames();//请求参数-值  
  30.         for(int i=0; en.hasMoreElements(); i++){  
  31.             String arg = en.nextElement().toString();  
  32.             if(i==0){  
  33.                 sbUrl.append("?");  
  34.             }else{  
  35.                 sbUrl.append("&");  
  36.             }  
  37.             sbUrl.append(arg + "=" + req.getParameterValues(arg)[0]);  
  38.         }  
  39.         System.out.println("request url: " + sbUrl.toString());       
  40.           
  41. //      if(ex instanceof BusinessException) {    
  42. //          return "error-business";    
  43. //      }else if(ex instanceof ParameterException) {    
  44. //          return "error-parameter";    
  45. //      } else {    
  46. //          return "error";    
  47. //      }    
  48.         return "forward:error.jsp";  
  49.     }  
  50. }  

 

 

 


---方式三:SimpleMappingExceptionResolver

 

SimpleMappingExceptionResolver:可对全局异常进行统一处理。

 

  1. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
  2.     <!--设置日志输出级别,不定义则默认不输出警告等错误日志信息。链接:http://elf8848.iteye.com/blog/875830 -->      
  3.     <property name="warnLogCategory" value="WARN" />    
  4.     <!-- 默认错误页面,就是不在exceptionMappings指定范围内 -->  
  5.     <property name="defaultErrorView" value="error"></property>  
  6.     <!-- 定义需要特殊处理的异常,如当发生IOException异常时跳转到error/ioexp视图-->  
  7.     <property name="exceptionMappings"><span style="font-family: Arial, Helvetica, sans-serif;"><!—key为异常类,可以是全路径,错误页面或Controller路径!会自动跳转到对应url --></span>        
  8.         <props>  
  9.             <prop key="IOException">redirect:/login</prop>  
  10.             <prop key="java.sql.SQLException">error/sqlexp</prop>  
  11.         </props>  
  12.     </property>  
  13. </bean>  


---方式四:<error-page>
DefaultHandlerExceptionResolver:Springmvc默认装配了DefaultHandlerExceptionResolver,它会将springmvc的异常转换成对应的响应状态码(500,404等)。对于Unchecked Exception而言,由于代码不强制捕获,往往被忽略,如果运行期产生了Unchecked Exception,而代码中又没有进行相应的捕获和处理,则我们可能不得不面对尴尬的404、500……等服务器内部错误提示页面。 
      我们需要一个全面而有效的异常处理机制。目前大多数服务器也都支持在web.xml中通过<error-page>(Websphere/Weblogic)或者<error-code>(Tomcat)节点配置特定异常情况的显示页面。(springmvc)操作如下:
1.在web.xml中配置响应状态码对应的页面,如:

  1. <error-page>    
  2.     <error-code>500</error-code>    
  3.     <location>/WEB-INF/pages/error/500.jsp</location>    
  4. </error-page>   
  5. <!-- 未捕获的错误,同样可指定其它异常类,或自定义异常类 -->  
  6. <error-page>  
  7.     <exception-type>java.lang.Exception</exception-type>  
  8.     <location>/uncaughtException</location>  
  9. </error-page>  

2. applicationContext.xml中配置

 

  1. <!-- 错误路径和错误页面,注意指定viewResolver -->  
  2. <mvc:view-controller path="/404" view-name="404"/>  
  3. <mvc:view-controller path="/500" view-name="500"/>  
  4. <mvc:view-controller path="/uncaughtException" view-name="uncaughtException"/>  

附:https://www.google.com.hk/search?newwindow=1&safe=strict&espv=210&es_sm=93&q=error+page%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8&revid=601630396&sa=X&ei=ORwOU7K_INKbiQeTjIG4BA&ved=0CIcBENUCKAE&biw=1440&bih=737 

---方式五:Spring3.2新注解@ControllerAdvice
链接:http://jinnianshilongnian.iteye.com/blog/1866350  
        @ControllerAdvice,是spring3.2提供的新注解。会把@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法(全局的)

      有一次发现springmvc3.2.x的@ControllerAdvice注解不起作用,参考链接http://www.07net01.com/linux/spring3_2_mvc__ControllerAdvice_buqizuoyong_554229_1375786240.html加上@EnableWebMvc后就可以了。但是,后来又发现会导致这个原因是因为项目的springmvc配置文件中没有配置<mvc:annotation-driven />,于是将其配置上。但是配置上<mvc:annotation-driven />后问题就来了,启动的时候就报异常,看了下原因,感觉是@EnableWebMvc注解导致的,于是将该注解删除掉,果然就正常启动了。不过,至于其中的原理还是理解不深刻,不知道内部是怎么调用的,只是发现当配置上<mvc:annotation-driven />的时候不应该用@EnableWebMvc修饰@ControllerAdvice。(待研究)附链接:http://hahalq.iteye.com/blog/1738599。http://www.yulezhandian.com/?p=196。

      测试后发现,当全局异常和局部异常都存在时,全局异常处理会被局部异常处理覆盖。

 

  1. /** 
  2.  * 全局异常 
  3.  */  
  4. //@EnableWebMvc  
  5. @ControllerAdvice  
  6. public class MyExceptionHandler {  
  7.       
  8.     @ExceptionHandler(Exception.class)  
  9.     public String handleException(Exception re, HttpServletRequest request) {  
  10.         System.out.println("error.......");  
  11.         return "forward:error.jsp";  
  12.     }  
  13. }  


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [spring mvc 异常处理] 推荐:

spring mvc 异常处理(转)

- - 编程语言 - ITeye博客
链接:http://gaojiewyh.iteye.com/blog/1297746 (附源码). 链接:http://zywang.iteye.com/blog/983801 . 链接:http://www.cnblogs.com/xguo/p/3163519.html . 链接:http://fuliang.iteye.com/blog/947191 .

使用Spring MVC统一异常处理实战

- - 互联网 - ITeye博客
源:http://cgs1999.iteye.com/blog/1547197. 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理. 每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大.

Spring MVC异常处理详解 - 程序员赵鑫

- - 博客园_首页
Spring MVC中异常处理的类体系结构. 下图中,我画出了Spring MVC中,跟异常处理相关的主要类和接口. 在Spring MVC中,所有用于处理在请求映射和请求处理过程中抛出的异常的类,都要实现HandlerExceptionResolver接口. AbstractHandlerExceptionResolver实现该接口和Orderd接口,是HandlerExceptionResolver类的实现的基类.

Spring MVC 和 Struts2

- - CSDN博客架构设计推荐文章
Web层面的框架学习了三个Struts1和2,SpringMVC,那他们之间肯定存在一个优劣和适用的环境,Struts1和2的异同点我已经做过对比《 Struts1和Struts2》,这篇将对比下Struts2和SpringMVC的异同,下面数据基本来源于网络,本人是搜集整理所得,供大家参考. 一个项目使用什么样的技术,决定的因素很多,我所能想到的有:对系统的性能、开发的效率、团队学习的成本、业务场景等,下面尽量从这几个方面入手,来分析比较下他们之间存在的优劣.

Spring Boot异常处理详解

- - ImportNew
在《 Spring MVC异常处理详解 》中,介绍了Spring MVC的异常处理体系,本文将讲解在此基础上Spring Boot为我们做了哪些工作. 下图列出了Spring Boot中跟MVC异常处理相关的类. Spring Boot在启动过程中会根据当前环境进行AutoConfiguration,其中跟MVC错误处理相关的配置内容,在ErrorMvcAutoConfiguration这个类中.

Spring MVC 3 深入总结

- - 企业架构 - ITeye博客
大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了. Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀. 官方的下载网址是: http://www.springsource.org/download   (本文使用是的Spring 3.0.5版本).

Spring MVC 与 web开发

- - 码蜂笔记
项目组用了 Spring MVC 进行开发,觉得对里面的使用方式不是很满意,就想,如果是我来搭建开发环境,我会怎么做. 下面就是我的想法,只关注于 MVC 的 View 层. 现在基本上都是用 ajax 来调用后台接口,拿到 json格式的数据再展示,有的人直接返回数据,却没有考虑异常的情况,我觉得返回的报文里必须包含表示可能的异常信息的数据和业务响应数据.

Spring MVC的常见错误

- - Java译站
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准. 然而多年过后,我发现Spring MVC已经越来越流行了. 对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性. 从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误.

Spring MVC 入门实例

- - CSDN博客推荐文章
springmvc 框架围绕DispatcherServlet这个核心展开,DispatcherServlet是Spring MVC的总控制,它负责截获请求并将其分派给相应的处理器处理. SpringMVC框架包括注解驱动控制器、请求及响应的信息处理、视图解析、本地化解析、上传文件解析、异常处理以及表单标签绑定等内容.

Spring MVC Controller单例陷阱

- - 企业架构 - ITeye博客
Spring MVC Controller单例陷阱. 标签:Spring mvc. 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明. Spring MVC Controller默认是单例的:. 1、这个不用废话了,单例不用每次都new,当然快了. 2、不需要实例会让很多人迷惑,因为spring mvc官方也没明确说不可以多例.