`

springMVC对异常处理的支持

 
阅读更多

来源:http://haohaoxuexi.iteye.com/blog/1188161

 

无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了。跟其他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. }  
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class ExceptionHandler implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		// TODO Auto-generated method stub
		return new ModelAndView("exception");
	}

}

 上述的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. }  
public class ExceptionHandler implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		// TODO Auto-generated method stub
		if (ex instanceof NumberFormatException) {
			//doSomething...
			return new ModelAndView("number");
		} else if (ex instanceof NullPointerException) {
			//doSomething...
			return new ModelAndView("null");
		}
		return new ModelAndView("exception");
	}

}

 

 

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

Xml代码 复制代码 收藏代码
  1. <bean id="exceptionResolver" class="com.tiantian.xxx.web.handler.ExceptionHandler"/>  
<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>  
	<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>

(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. }  
@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!");
	}
	
}

 

(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>  
<%@ 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/><!-- 这是JSP中的内置对象exception -->



    <%=request.getAttribute("ex") %><br><!-- 这是SpringMVC放在返回的Model中的异常对象 -->



    <%=request.getAttribute("javax.servlet.error.status_code") %><!-- HttpServletResponse返回的错误码信息,因为前面已经配置了NumberFormatException的错误码返回值为888,所以这里应该显示888 -->



  </body>
</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. }  
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tiantian.blog.web.servlet.MyException;

@Controller
public class GlobalController {

	
	/**
	 * 用于处理异常的
	 * @return
	 */
	@ExceptionHandler({MyException.class})
	public String exception(MyException e) {
		System.out.println(e.getMessage());
		e.printStackTrace();
		return "exception";
	}
	
	@RequestMapping("test")
	public void test() {
		throw new MyException("出错了!");
	}
	
	
}

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

 

 

 

 

 

优先级

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

 

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

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

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

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

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

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

 

另:http://gaojiewyh.iteye.com/blog/1297746

 

在controller里面捕获异常,抛出异常

 

分享到:
评论

相关推荐

    SpringMVC统一异常处理三种方法详解

    这篇文章主要介绍了SpringMVC-统一异常处理三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在 Spring MVC 应用的开发中,不管是对底层数据库操作...

    SpringMVC学习笔记整合搭建框架

    4、SpringMVC中异常处理 5、图片上传处理 6、Json数据交互 7、SpringMVC实现RESTful 8、拦截器 2.Spring入门 2.1.Springmvc是什么 3.3.jdbc编程步骤: 1、加载数据库驱动 2、创建并获取数据库链接 3、创建jdbc ...

    springMVC教学视频详解(包括spring和mybatis的整合)

    此视频包含:springmvc入门教程(原理分析、环境搭建、前端控制器配置、Handler编写调试、非注解映射器和...springmvc异常处理;springmvc上传图片;springmvc实现json交互;springmvc对RESTful支持;springmvc拦截器

    2020年SpringMVC面试题,看这篇就足够了

    它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。 2.什么是MVC模式? 对请求参数进行重新编码,ISO8859-1是tomcat默认编码,需要将tomcat编码...

    Java异常分类及统一处理详解

    主要为大家详细介绍了Java异常分类及统一处理,SpringMVC处理异常支持ajax,web.xml配置异常,感兴趣的小伙伴们可以参考一下

    springmvc+hibernate 日志管理工具

    功能包括:功能日志记录(访问、参数、异常、返回结果集)、数据日志记录、日志查询对比。配置灵活扩展性强。通过接口注入解藕业务系统,形成独立可插拔的日志管理工具。 功能日志:基于java aop思想设计,通过...

    04.SpringMVC.md

    同时,Java还提供了自动内存管理和异常处理机制,使开发人员能够更轻松地编写高质量的代码。 总之,Java是一种功能强大、易学易用、具有广泛应用和强大跨平台特性的编程语言。它的设计目标是提供一种高效的开发工具...

    JAVA制造装备物联及生产管理(ERP)系统源码

    统一的异常处理 JSP JSTL JavaScript kindeditor富文本编辑器,处理图片上传和富文本编辑 项目框架: 后台框架:spring+ springMVC + shiro + MyBatis + jsp 前台框架:easyui+ jquery + javascript

    springmvc-showcase

    Spring MVC 展示通过小... 在此展示中,您将看到以下内容: 最简单的@Controller 映射请求获取请求数据生成响应消息转换器渲染视图类型转换验证形式上传文件异常处理获取代码: 克隆存储库: $ git clone git://github....

    基于SSM框架的生产管理ERP系统源码+数据库+项目文档,含计划进度、设备管理、工艺监控、物料监控、人员监控、质量监控、系统管理

    一个生产管理ERP系统。主要包括:计划进度、设备管理、工艺监控、物料监控、人员监控、质量监控、系统管理7大模块 ...统一的异常处理 JSP JSTL JavaScript kindeditor富文本编辑器,处理图片上传和富文本编辑

    "优雅的SSM框架"进行完善(页面分离+nginx负载均衡+tomcat集群)

    统一的异常处理 Redis缓存(ProtoStuff序列化) Redis Sentinel主从高可用方案 Redis Cluster集群高可用方案 Druid(数据源配置 sql防注入 sql性能监控) 前后端分离(Html替代Jsp) Nginx静态加载、负载均衡 基于...

    erp源码-ssm+easyUI+mysql+maven+shiro

    erp项目 基于ssm+easyUI+mysql+maven+shiro开发 本系统实现目标如下: ## 项目技术架构(Spring+SpringMVC+Mybatis) ## - Maven - Spring(IOC DI AOP 声明式事务处理) - SpringMVC(支持Restful风格) - Hibernate...

    qh-erp-ssm

    erp项目 基于ssm+easyUI+mysql+maven+shiro开发 本系统实现目标如下: ## 项目技术架构(Spring+SpringMVC+Mybatis) ##...- 统一的异常处理 - JSP JSTL JavaScript - kindeditor富文本编辑器,处理图片上传和富文本编辑

    erp完整源码-ssm+easyUI+mysql+maven+shiro

    erp项目 基于ssm+easyUI+mysql+maven+shiro开发 本系统实现目标如下: ## 项目技术架构(Spring+SpringMVC+Mybatis) ## - Maven - Spring(IOC DI AOP 声明式事务处理) - SpringMVC(支持Restful风格) - Hibernate...

    java ssm开发的生产管理ERP系统

    这是一个生产管理ERP系统。依托科技计划重点项目“制造装备物联及生产管理系统研发”,主要包括:计划进度...- 统一的异常处理 - JSP JSTL JavaScript - kindeditor富文本编辑器,处理图片上传和富文本编辑&lt;!--more--&gt;

    [计算机Java毕业设计]ssm框架基于web的物流配送管理系统的设计与实现+vue+程序源代码+论文.rar

    4. 异常处理:系统支持对配送过程中出现的异常情况进行记录和处理,如订单取消、地址变更等。 5. 统计报表:系统提供丰富的统计报表功能,帮助企业分析业务数据,优化配送流程。 本系统具有良好的扩展性和可定制性...

    MF00331-JAVA制造装备物联生产管理(ERP)源码.zip

    统一的异常处理 JSP JSTL JavaScript kindeditor富文本编辑器,处理图片上传和富文本编辑 项目框架: 后台框架:spring+ springMVC + shiro + MyBatis + jsp 前台框架:easyui+ jquery + javascript 基于SSM...

    积分管理系统java源码-ERP-ssm:这是一个SSM(Spring+SpringMVC+Mybatis)+jQueryEasyUI开发的E

    积分管理系统java源码 ...统一的异常处理 JSP JSTL JavaScript kindeditor富文本编辑器,处理图片上传和富文本编辑 系统架构 数据库设计(详见sql文件) 软件运行截图 登录界面 登录可使用账号:22

    微信小程序项目源码-订餐系统设计与实现+ssm框架+论文.rar

    系统还具备日志记录、异常处理等功能,确保系统稳定运行。 数据库存储方面,系统采用MySQL数据库进行数据存储和管理,保证了数据的可靠性和安全性。同时,系统对数据库进行了优化设计,提高了查询性能和扩展性。

    springboot框架整合SSM案例-图书管理系统 源码分享

    SpringBoot整合Spring+SpringMVC+MyBatisPlus案例:图书管理系统 ...- 项目异常处理 - 按条件查询 —— 页面功能调整、Controller修正功能、Service修正功能 完整源码分享,喜欢的可以酌情下载,感谢下载者的支持!

Global site tag (gtag.js) - Google Analytics