springMVC对异常处理的支持
无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了。跟其他MVC框架一样,springMVC也有自己的异常处理机制。
springMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,当然这也包括使用 Spring已经为我们提供好的SimpleMappingExceptionResolver和 DefaultHandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异常的Controller—— ExceptionHandler。
1、实现自己的 HandlerExceptionResolver,HandlerExceptionResolver是一个接口,springMVC本身已经对其有了 一个自身的实现——DefaultHandlerExceptionResolver,该解析器只是对其中的一些比较典型的异常进行了拦截,然后返回对应 的错误码,当然你也可以继承DefaultHandlerExceptionResolver类,然后重写其中的一些异常处理方法来实现自己的异常处理。
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方法 里面根据不同的异常类型进行不同的处理,返回不同的异常视图。如:
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对象,如:
@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作为示例:
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中也没有定义的话,那么该异常就会被抛出来。