异常处理
- 异常处理
- 基本介绍
- 局部异常
- 应用实例
- Debug处理流程
- 全局异常
- 应用实例
- Debug处理流程
- 异常处理时: 局部异常 优先级高于 全局异常
- 自定义异常
- 应用实例
- Debug处理流程
- SimpleMappingExceptionresovler
- 基本说明
- 应用实例
- 对未知异常进行统一处理
- 异常处理的优先级梳理
上一讲, 我们学习的是 SpringMVC系列十一: 文件上传与自定义拦截器
现在打开springmvc项目
异常处理
基本介绍
1.Spring MVC 通过 HandlerExceptionResolver 处理程序的异常, 包括 Handler 映射, 数据绑定以及目标方法执行时发生的异常.
2.主要处理 Handler 中用 @ExceptionHandler 注解定义的方法
3.ExceptionHandlerMethodResolver 在 Handler 内部若找不到 @ExceptionHandler 注解的话, 会找 @ControllerAdvice 类的@ExceptionHandler 注解方法, 这样就相当于一个全局异常处理器.
局部异常
应用实例
应用实例需求
演示局部异常处理机制
-如果不处理异常, 非常的不友好
1.在com.zzw.web.exception
新建MyExceptionHandler
@Controller
public class MyExceptionHandler {//编写方法, 模拟异常, 算术异常@RequestMapping(value = "/testException01")public String test01(Integer num) {int i = 9 / num;return "success";}
}
2.web路径
新建exception.jsp
<head><title>异常信息</title>
</head>
<body>
<h1>测试异常</h1>
<a href="<%=request.getContextPath()%>/testException01?num=0">点击测试局部异常</a><br/><br/>
</body>
3.测试, 抛错
4.MyExceptionHandler
新增 localException ()
, 处理局部异常
/*** 解读* 1.localException 方法处理局部异常* 2.这里我们处理ArithmeticException.class, NullPointerException.class* 3.Exception ex: 生成的异常对象, 会传递给ex, 通过ex可以得到相关的信息* , 这里程序员可以加入自己的业务逻辑* @return*/
@ExceptionHandler({ArithmeticException.class, NullPointerException.class})
public String localException(Exception ex, HttpServletRequest request) {System.out.println("局部异常信息是=" + ex.getMessage());//如何将异常的信息都带到下一个页面request.setAttribute("reason", ex.getMessage());return "exception_mes";
}
5.新增web路径/excetion_mes.jsp
<head><title>异常信息提示</title>
</head>
<body>
<h1>朋友, 你程序出问题了!</h1>
异常信息 - ${requestScope.reason}
</body>
6.测试
Debug处理流程
打断点
测试
全局异常
应用实例
●应用实例需求
演示全局异常处理机制, ExceptionHandlerMethodResolver 内部若找不到 @ExceptionHandler 注解的话, 会找 @ControllerAdvice 类的 @ExceptionHandler 注解方法, 这样就相当于一个全局异常处理器
●代码实现
1.新建com.zzw.web.exception.MyGlobalException
/*** 如果类上标注了@ControllerAdvice, 就是一个全局异常处理类*/
@ControllerAdvice
public class MyGlobalException {/*** 解读* 1.全局异常就不管是哪个Handler抛出的异常, 即都可以捕获. 格式是 @ExceptionHandler({异常类型})* 2.这里我们处理的全局异常是 NumberFormatException.class, ClassCastException.class* 3.Exception ex, 接收抛出的异常对象* @return*/@ExceptionHandler({NumberFormatException.class, ClassCastException.class})public String globalException(Exception ex, HttpServletRequest request) {System.out.println("全局异常处理=" + ex.getMessage());//如何将异常信息带到下一个页面request.setAttribute("reason", ex.getMessage());return "exception_mes";}
}
2.MyExceptionHandler
新增 global()
方法
@RequestMapping(value = "/testGlobalException")
public String global() {//解读//1.这里我们模拟了一个异常 NumberFormatException//2.该异常没有在局部异常处理, 按照异常处理机制, 就会交给全局异常处理类处理int num = Integer.parseInt("hello");return "exception_mes";}
3.exception.jsp
新增代码
<a href="<%=request.getContextPath()%>/testGlobalException">点击测试全局异常</a><br/><br/>
4.测试
Debug处理流程
点击下一步
继续往下走
继续往下走
继续往下走
异常处理时: 局部异常 优先级高于 全局异常
假如我们把NumberFormatException异常也放进了局部异常处理, 那么在调用 global() 的时候, 优先去找本类的局部异常处理.
自定义异常
应用实例
●应用实例需求
通过 @ResponseStatus 注解, 可以自定义异常的说明
●应用实例-代码实现
1.新建com.zzw.web.exception.AgeException
@ResponseStatus(reason = "年龄需要在1-120之间", value = HttpStatus.BAD_REQUEST)
public class AgeException extends RuntimeException {}
2.修改MyExceptionHandler, 增加方法
@RequestMapping(value = "/testException02")
public String test02() {throw new AgeException("年龄必须在1-120之间~~~");
}
3.修改exception.jsp
, 增加超链接
<a href="<%=request.getContextPath()%>/testException02">点击测试自定义异常</a>
4.测试
5.在自定义异常中加两个构造器
@ResponseStatus(reason = "年龄需要在1-120之间", value = HttpStatus.BAD_REQUEST)
public class AgeException extends RuntimeException {public AgeException() {}public AgeException(String message) {super(message);}
}
被全局异常捕获
Debug处理流程
继续往下走
找到了globalException()方法
SimpleMappingExceptionresovler
基本说明
1.如果希望对所有异常进行统一处理, 可以使用 SimpleMappingExceptionResolver
2.它将异常类名映射为视图名, 即发生异常时使用对应的视图报告异常
3.需要在ioc容器中配置
应用实例
●应用实例 - 需求
对数组越界异常进行统一处理, 使用SimpleMappingExceptionResolver
●应用实例 - 代码实现
1.修改MyExceptionHandler.java
, 增加方法test03
@RequestMapping(value = "/testException03")
public String test03() {int[] arr = new int[]{1, 2, 3, 4, 5};//抛出一个数据越界的异常 ArrayOutOfBoundsExceptionSystem.out.println(arr[90]);return "success";
}
2.配置springDispatcherServlet-servlet.xml
<!--配置统一处理异常-->
<beanclass="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop></props></property>
</bean>
3.web路径/WEB-INF/pages/arrEx.jsp
<head><title>数组越界异常</title>
</head>
<body>
异常信息 - 数据越界
</body>
4.修改exception.jsp
, 增加代码
<a href="<%=request.getContextPath()%>/testException03">点击测试统一异常</a><br/><br/>
5,测试
对未知异常进行统一处理
⭐应用实例 - 需求
对未知异常进行统一处理, 使用SimpleMappingExceptionResolver
⭐应用实例 - 代码实现
1.修改myExceptionHandler.java, 增加方法test04()
//如果发生了没有归类的异常, 可以给出统一提示页面
@RequestMapping(value = "/testException04")
public String test04() {String str = "hello";//这里会抛出 StringIndexOutOfBoundsExceptionchar c = str.charAt(10);return "success";
}
2.继续配置
<!--配置统一处理异常-->
<beanclass="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop><prop key="java.lang.Exception">allEx</prop></props></property>
</bean>
3.web路径/WEB-INF/pages/allEx.jsp
<head><title>未知异常信息</title>
</head>
<body>
<h1>系统发生了异常, 联系网站管理员~</h1>
</body>
4.修改exception.jsp
, 增加代码
<a href="<%=request.getContextPath()%>/testException04">点击测试未知异常</a><br/><br/>
5.测试
异常处理的优先级梳理
局部异常 > 全局异常 > SimpleMappingExceptionResolver > tomcat默认机制
1.测试
局部异常 | 全局异常 | SimpleMappingExceptionResolver |
---|---|---|
ArrayIndexOutOfBoundsException.class | ArrayIndexOutOfBoundsException.class | <prop key=“java.lang.ArrayIndexOutOfBoundsException”>arrEx</prop> |
局部异常 | 全局异常 | SimpleMappingExceptionResolver |
---|---|---|
ArrayIndexOutOfBoundsException.class | <prop key=“java.lang.ArrayIndexOutOfBoundsException”>arrEx</prop> |
局部异常 | 全局异常 | SimpleMappingExceptionResolver |
---|---|---|
<prop key=“java.lang.ArrayIndexOutOfBoundsException”>arrEx</prop> |
局部异常 | 全局异常 | SimpleMappingExceptionResolver |
---|---|---|
<prop key=“ArrayIndexOutOfBoundsException”>arrEx</prop> |