我们知道系统中的异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生
在SpringMVC处理异常的方式为:将系统的Dao、Service、Controller出现的异常都通过throws Excepton 向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理
如下图所示:
在SpringMVC中异常处理有三种方法:
**第一种:**Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver
**第二种:**实现Spring的异常处理接口HandlerExceptionResolver 自定义的异常处理器
①创建异常处理器类实现HandlerExceptionResolver
public class MyExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {//处理异常的代码实现//创建ModelAndView对象ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("exceptionPage");return modelAndView;}
}
②配置异常处理器
③编写异常页面:exceptionPage
**第三种方法:**使用@ExceptionHandler注解实现异常处理;
使用方法有两种:
1.在可能出现异常的Controller层进行异常处理,也就是在同一个类中进行异常处理:@Controller+@ExceptionHandler
@Controller
@RequestMapping("/testController")
public class TestController {@RequestMapping("/demo1")@ResponseBodypublic Object demo1(){int i = 1 / 0;return new Date();}@ExceptionHandler({RuntimeException.class})public ModelAndView fix(Exception ex){System.out.println("do This");return new ModelAndView("error",new ModelMap("ex",ex.getMessage()));}
}
注意事项:
1.一个Controller下多个@ExceptionHandler上的异常类型不能出现一样的,否则运行时抛异常.
Ambiguous @ExceptionHandler method mapped for;
2.@ExceptionHandler下方法返回值类型支持多种,常见的ModelAndView,@ResponseBody注解标注, ResponseEntity等类型都OK.
2.全局级别处理:@ControllerAdvice+@ExceptionHandler
@ControllerAdvice
public class GlobalController {@ExceptionHandler(RuntimeException.class)public ModelAndView fix1(Exception e){System.out.println("全局的异常处理器");ModelMap mmp=new ModelMap();mmp.addAttribute("ex",e);return new ModelAndView("error",mmp);}
}
用法说明: 与第一种方式用法相同,返回值支持ModelAndView,@ResponseBody等多种形式.
上面我们已经了解了SpringMVC的三种方法,下面我们分别用上面的方法来做几个案例吧!
第一步:创建一个maven项目:略
第二步:在pom.xml中添加以下的依赖或插件坐标:
org.apache.tomcat.maven tomcat7-maven-plugin 2.2 / UTF-8 org.springframework spring-webmvc 5.3.18 javax.servlet javax.servlet-api 4.0.1 provided javax.servlet.jsp jsp-api 2.2 provided war
第三步:在项目中添加webapp/WEB-INF结构:略
第四步:在resources中添加spring-mvc.xml文件,并在web.xml中加载spring-mvc.xml文件;
sping-mvc.xml文件:
web.xml文件:
/login.jsp spring-mvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring-mvc.xml spring-mvc /
第五步:在main/java包下创建com/Controller包,并在Controlle包下创建ExceptionTest类;
如果看不懂第五步说的是什么,那么请看下面的项目结构:
ExceptionTest类:
@Controller
@RequestMapping("/com")
public class ExceptionTest {@RequestMapping("/IOException")public void IOExceptionLocation() throws IOException {throw new IOException("抛出IO异常");}@RequestMapping("/NullPointerException")public void NullPointerExceptionLocation() throws NullPointerException {throw new NullPointerException("空指针异常,请检查");}@RequestMapping("/OutOfMemoryError")public void OutOfMemoryErrorLocation() throws OutOfMemoryError {throw new OutOfMemoryError("内存溢出,请检查");}@RequestMapping("/ClassCastException")public void ClassCastExceptionLocation() throws ClassCastException {throw new ClassCastException("类型转换异常,请检查");}
}
第六步:在webapp下创建login.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
首页:异常显示页
IO异常处理
空指针异常
内存溢出
类型转换异常
第七步:在WEB-INF包下创建一个page包,在page包下创建commonPage.jsp页面和spacialPage.jsp页面:
commonPage.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
普通处理页面
异常信息:${requestScope.ex.message}
spacialPage.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
特殊处理页面
特殊处理的异常信息:${requestScope.ex.message}
上面我们的第一个案例就做好了,下面我们来演示效果:
1.运行项目,开始页面:
2.点击IO异常处理:
3.点击空指针异常:
4.点击内存溢出:
5.点击类型转换异常:
效果讲解:细心的人会发现 点击空指针异常和类型转换异常的时候页面会跳转到特殊处理页面 ,点击IO异常处理和内存溢出的时候页面会跳转到普通处理页面这是为什么呢?
原因很简单:我们在配置mvc提供的默认异常处理器的时候指定的了空指针异常和类型转换异常回调到特殊处理页面,其他的异常没有指定的异常我们设置了默认跳转到普通处理页面,如下图:
第二个案例是在第一个案例的基础上进行修改的,说一很多步骤都和第一个案例相同;
第一步、第二步、第三步同第一个案例;
第四步:在resources中添加spring-mvc.xml文件,并在web.xml中加载spring-mvc.xml文件;
sping-mvc.xml文件:
web.xml文件:同第一个案例;
第五步:在第一个案例的第五步的基础上,在com包下添加一个ExceptionHadlele包,并在该ExceptionHadlele包下添加myHandleExecption类(重点)
项目包结构如下:
myHandleExecption类:
public class myHandleExecption implements HandlerExceptionResolver {public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {System.out.println("异常处理器正在执行中");//创建模型视图对象,用于方法放回ModelAndView result = new ModelAndView();result.addObject("msg",ex.getMessage());//根据异常类型返回不同的视图信息if(ex instanceof IOException){result.setViewName("spacialPage");}else if(ex instanceof NullPointerException){result.setViewName("spacialPage");}else {result.setViewName("commonPage");}return result;}
}
第六步:在spring-mvc.xml配置异常处理器
第七步:同第一个案例的第六步+第七步
演示效果:
首页跟案例一一样:
通过效果可以知道IO异常处理和空指针异常处理点击后会跳转到特殊处理页面,其他异常会跳转到普通处理页面,这个也是跟案例一的原理差不多的;我在myHandleExecption类中定义了IOException和NullPointerException的处理会调转到特殊处理页面
第三个案例也是在第一个案例的基础上的修改的,主要是让大家知道三种异常处理的用法
1.修改案例一中的spring-mvc.xml文件:将配置mvc提供的默认异常处理器删除;
2.在ExceptionTest类中添加配上@ExceptionHandler注解的方法,也就是@Controller+@ExceptionHandler;
@Controller
@RequestMapping("/com")
public class ExceptionTest {@RequestMapping("/IOException")public void IOExceptionLocation() throws IOException {throw new IOException("抛出IO异常");}@RequestMapping("/NullPointerException")public void NullPointerExceptionLocation() throws NullPointerException {throw new NullPointerException("空指针异常,请检查");}@RequestMapping("/OutOfMemoryError")public void OutOfMemoryErrorLocation() throws OutOfMemoryError {throw new OutOfMemoryError("内存溢出,请检查");}@RequestMapping("/ClassCastException")public void ClassCastExceptionLocation() throws ClassCastException {throw new ClassCastException("类型转换异常,请检查");}@ExceptionHandler({IOException.class,NullPointerException.class})public ModelAndView exception1(Exception ex){ModelAndView view=new ModelAndView();view.addObject("msg",ex.getMessage());view.setViewName("commonPage");return view;}}
3.在com包下添加ExecptionHandle包,并在ExecptionHandle包下添加GlobalController类–>@ControllerAdvice+@ExceptionHandler
包目录结构:
GlobalController类:
@ControllerAdvice
public class GlobalController {@ExceptionHandlerpublic ModelAndView exception1(Exception ex){ModelAndView view=new ModelAndView();view.addObject("msg",ex.getMessage());view.setViewName("commonPage");return view;}
}
以上就是案例三了,我们先测试一下效果;
首页同第一个案例: