首页IT科技异常处理步骤有哪些(day14-异常处理)

异常处理步骤有哪些(day14-异常处理)

时间2025-05-02 17:32:50分类IT科技浏览3563
导读:异常处理 1.基本介绍...

异常处理

1.基本介绍

SpringMVC 通过 HandlerExceptionResolver 处理程序的异常           ,包括 Handler映射          、数据绑定以及目标方法执行时发生的异常

有两种方案来进行异常处理:

a.在本类编写处理异常的方法               ,将抛出的异常视为局部异常处理

b.额外编写处理异常的类     ,将抛出的异常视为全局异常处理

主要处理的是 Handler 中使用了 @ExceptionHandler 注解修饰的方法(局部异常处理)

ExceptionHandlerMethodResolver 内部若找不到上述 @ExceptionHandler 注解修饰的方法           ,就会去找有 @ControllerAdvice 注解修饰的类中含有 @ExceptionHandler 注解的方法                ,被 @ControllerAdvice 修饰的类称为全局处理器(全局异常处理)

异常处理时     ,局部异常优先级高于全局异常

2.局部异常

2.1应用实例

(1)创建 MyExceptionHandler.java     ,在这个 Handler 中模拟各种出现的异常                ,并在本类添加处理可能出现的异常的方法(局部异常)

局部异常的处理方法只能处理本类中出现的异常          。

package com.li.web.exception; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; /** * @author 李 * @version 1.0 */ @Controller public class MyExceptionHandler { /** * 1.localException()方法处理局部异常 * 2.指定处理 算术异常                、空指针异常 * 3. Exception ex 本类生成的异常对象          ,会传递给ex     ,通过ex可以拿到相关信息                , * 在这里可以加入业务逻辑 * @param ex * @param request * @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"; } /** * 1.编写方法          ,模拟异常-算术异常 * 2.如果我们不做异常处理,是由tomcat默认页面处理 * @param num * @return */ @RequestMapping(value = "/testException01") public String test01(Integer num) { int i = 9 / num; return "success"; } }

(2)exception_mes.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>异常信息</title> </head> <body> <h1>异常信息提示</h1> <h4>${requestScope.reason}</h4> </body> </html>

(3)测试                ,直接访问 http://localhost:8080/springmvc/testException01?num=0               ,显示结果如下:

捕获到了异常,SpringMVC 底层反射调用了 localException 方法进行异常处理           ,跳转到了 exception_mes.jsp 页面提示异常信息                。

如果我们没有处理异常               ,默认是由 tomcat 进行异常处理

2.2执行流程

从发生异常到捕获异常并调用处理方法     ,局部异常处理的整个执行流程是怎样的呢?

第一步:浏览器访问目标方法           ,如果出现异常                ,会到 ExceptionHandlerMethodResolver 类中执行 resolveMethodByExceptionType() 方法

第二步:执行resolveMethodByExceptionType() 方法     ,得到处理异常的方法     。

@Nullable public Method resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) { //获取目标方法出现的异常类型 exceptionType //然后通过map去找有没有一个默认的方法去处理这个异常 Method method = this.exceptionLookupCache.get(exceptionType); if (method == null) {//如果没有默认方法 //getMappedMethod 得到该异常映射的处理方法     ,如例子中的 localException() 方法 method = getMappedMethod(exceptionType); //将找到的这个方法作为 该异常的处理方法                ,放入到map中 this.exceptionLookupCache.put(exceptionType, method); } //返回这个方法 return (method != NO_MATCHING_EXCEPTION_HANDLER_METHOD ? method : null); }

第三步:将得到的异常数据放入到该方法的参数中          ,底层反射调用处理异常的该方法

第四步:根据处理异常方法     ,执行自定义的业务逻辑     。如例子中跳到某个页面并提示异常信息                。

3.全局异常

3.1应用实例

演示全局异常处理机制           。

ExceptionHandlerMethodResolver 内部若找不到 @ExceptionHandler 注解的方法                ,就会找 @ControllerAdvice 类的 @ExceptionHandler 注解方法          ,这样就相当于一个全局处理器,全局处理器可以处理不同的 Handler 出现的异常     。

(1)自定义一个全局处理器 MyGlobalException.java

package com.li.web.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import javax.servlet.http.HttpServletRequest; /** * @author 李 * @version 1.0 * 如果一个类上标注了 @ControllerAdvice                ,那么这个类就是一个全局异常处理器 */ @ControllerAdvice public class MyGlobalException { /** * 1.不管是哪个 Handler抛出的异常               ,全局异常都可以捕获 * 2.@ExceptionHandler({这里是可以捕获的异常类型}) * @param 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)在 Handler 的目标方法中模拟异常

package com.li.web.exception; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; /** * @author 李 * @version 1.0 */ @Controller public class MyExceptionHandler { //局部异常处理方法 @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"; } //目标方法 @RequestMapping(value = "testGlobalException") public String global() { //模拟一个 NumberFormatException异常,若该异常不能在局部异常方法处理           , //就会被交到全局异常处理器中处理 int num = Integer.parseInt("hello"); return "success"; } }

(3)exception_mes.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>异常信息</title> </head> <body> <h1>异常信息提示</h1> <h4>${requestScope.reason}</h4> </body> </html>

(3)在浏览器中访问目标方法 http://localhost:8080/springmvc/testGlobalException               ,可以看到页面提示了异常信息     ,同时后台输出为 全局异常处理=For input string: "hello"           ,这说明是全局异常处理器捕获到的异常                ,局部异常方法没有捕获到               。

3.2执行流程

从发生异常到捕获异常并调用处理方法     ,全局异常处理的流程如下:

(1)浏览器访问目标方法     ,若出现异常                ,会到 ExceptionHandlerExceptionResolver 类的 ServletInvocableHandlerMethod() 方法进行处理:

(2)上述方法首先会到 ExceptionHandlerMethodResolver 类中执行 resolveMethod 方法

(3)resolveMethod 方法又调用本类的 resolveMethodByThrowable 方法

(4)resolveMethodByThrowable 继续调用本类的 resolveMethodByExceptionType() 方法:

@Nullable public Method resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) { //获取目标方法的异常类型 exceptionType //通过map去找处理该异常的默认的方法 Method method = this.exceptionLookupCache.get(exceptionType); if (method == null) {//若没有默认方法 //得到该异常映射的处理方法          ,这一步如果没有在Handler类中找到处理方法     , //如局部异常方法不匹配该异常                ,就会返回一个 noMatchingExceptionHandler() 的方法 method = getMappedMethod(exceptionType); //将找到的这个方法作为 该异常的处理方法          ,放入到map中 this.exceptionLookupCache.put(exceptionType, method); } //若 method为 noMatchingExceptionHandler(),则返回一个 null return (method != NO_MATCHING_EXCEPTION_HANDLER_METHOD ? method : null); }

(5)如果 resolveMethodByExceptionType() 方法没有在本类 Handler 中匹配到可以解决出现的异常的方法                ,就返回 null

@Nullable public Method resolveMethodByThrowable(Throwable exception) { //如果 mothod 返回 null Method method = resolveMethodByExceptionType(exception.getClass()); if (method == null) { //获取出现异常的原因 Throwable cause = exception.getCause(); if (cause != null) { //根据异常找匹配的方法 method = resolveMethodByThrowable(cause); } } //如果返回null return method; }

(6)一路返回到 ExceptionHandlerExceptionResolver 类的 ServletInvocableHandlerMethod() 方法               ,如果获取到的 method 仍为 null,就会去遍历带有 @ControllerAdvice 注解修饰的类(全局处理器)           ,然后全局处理器中根据 @ExceptionHandler 注解               ,获取可以处理异常的方法           。

这里的 entry.getKey() 就是 @ControllerAdvice 注解修饰的类对象。

(7)最后反射调用找到的全局处理器中的方法               。

4.自定义异常

可以通过 @ResponseStatus 注解     ,来自定义异常的说明

4.1应用实例

(1)自定义异常

package com.li.web.exception; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; /** * @author 李 * @version 1.0 */ @ResponseStatus(reason = "年龄需要在1-120之间",value = HttpStatus.BAD_REQUEST) public class AgeException extends RuntimeException{ }

(2)修改 MyExceptionHandler.java           ,增加方法进行测试

package com.li.web.exception; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 李 * @version 1.0 */ @Controller public class MyExceptionHandler { @RequestMapping(value = "/testException02") public String test02() { throw new AgeException(); } }

(3)浏览器访问 http://localhost:8080/springmvc/testException02                ,测试显示如下:

访问目标方法     ,抛出异常     ,异常的信息就是你指定的信息                ,状态码也是你指定的数据

4.2拓展

自定义异常可以被局部异常处理和全局异常处理接管          ,只需要在 @ExceptionHandler 注解中添加自定义异常的.class即可

1.当然     ,如果想要拿到 ex.getMessage() 信息                ,需要在自定义的异常类创建带有 message 参数的构造器

自定义异常的 reason          ,value 属性是给 tomcat 的默认页面显示的,而构造器的 messgae 属性是传入对象的

2.然后在创建异常类对象的时候放入提示信息:

自定义异常本质就是异常                ,它的处理流程由 它被局部异常还是全局异常接管 而定                。如果两者都没有接管               ,就会被 tomcat 来处理,然后 tomcat 显示一个默认的页面。

5.SimpleMappingExceptionResolver

5.1基本说明

如果希望对所有异常进行统一处理           ,可以使用 SimpleMappingExceptionResolver 它将异常类名映射为视图名               ,即发生异常时使用对应的视图报告异常 需要在 spring 的容器文件中配置

5.2应用实例

需求:使用 SimpleMappingExceptionResolver 对数据越界异常进行统一处理

(1)修改 MyExceptionHandler.java     ,增加方法 test03

//模拟数据下标越界异常 @RequestMapping(value = "/testException03") public String test03() { int[] arr = {3, 8, 18, 20}; System.out.println(arr[99]); return "success"; }

(2)在 spring 容器文件配置

<!--配置统一异常处理的bean--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!--key为处理的异常的全路径           , arrEx为出现异常后要跳转的页面(页面所在的目录要和你的视图解析器的前后缀匹配)--> <prop key="java.lang.ArrayIndexOutOfBoundsException">arrEx</prop> </props> </property> </bean>

(3)arrEx.jsp                ,该页面显示异常信息

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>数组下标越界异常</title> </head> <body> 异常信息:数组下标越界异常 </body> </html>

(4)浏览器访问目标方法     ,返回的页面显示:跳转到了 arrEx.jsp 页面          。

目标方法发生异常--->先去局部异常方法处理--->如果不行     ,到全局异常处理器处理--->如果不行                ,到容器文件配置统一异常处理的 bean 处理--->都不行          ,最后由 tomcat 处理

5.3对未知异常进行统一处理

在实际开发中     ,异常的种类非常多                ,我们的异常处理方法可能不能捕获到所有的异常                。

如何处理没有归类(未知的)的异常?

仍然可以使用 SimpleMappingExceptionResolver 进行处理     。只需要在配置的时候          ,将捕获的异常范围扩大,如Exception          。

例子

(1)修改 MyExceptionHandler.java                ,增加方法 test04

//如果发生了没有归类的异常               ,可以给出统一的提示页面 @RequestMapping(value = "/testException04") public String test04() { String str = "hello"; //StringIndexOutOfBoundsException char c = str.charAt(10); return "success"; }

(2)容器文件配置处理异常的bean时,扩大捕获范围

<!--配置统一异常处理的bean--> <bean class="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)allEx.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>异常通知</title> </head> <body> <h1>系统发生了未知异常..</h1> </body> </html>

(4)浏览器访问目标方法           ,访问结果如下:

5.4异常处理的优先级

局部异常处理 > 全局异常处理 > SimpleMappingExceptionResolver 处理 > tomcat 默认机制处理

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
rdrobust命令(rdate命令 – 显示其他主机的日期与时间) vue点击弹出组件界面(Vue如何给组件添加点击事件 @click.native)