springMVC对异常处理的支持

不管作什么项目,进行异常处理都是很是有必要的,并且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,因此这时候进行统一的异常处理,展示一个比较友好的错误页面就显得颇有必要了。跟其余MVC框架同样,springMVC也有本身的异常处理机制。
springMVC提供的异常处理主要有两种方式,一种是直接实现本身的HandlerExceptionResolver,固然这也包括使用Spring已经为咱们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver,另外一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。
css


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

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

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对象,如: 程序员

<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。 web

如下是一个简单的例子: spring

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

<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)以下访问: 框架

@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

<%@ 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视图,返回结果以下: ide


 

二、使用@ExceptionHandler进行处理

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

如:

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中也没有定义的话,那么该异常就会被抛出来。

相关文章
相关标签/搜索