目录
引言
- 将异常处理逻辑集中到一个地方,可以避免在每个控制器或业务逻辑中都编写相似的异常处理代码,这降低了代码的冗余,提高了代码的可维护性
- 统一的异常处理使得调试和维护变得更加容易,通过集中处理异常,开发人员可以更轻松地定位和解决应用程序中的问题,而不必在整个代码库中查找异常处理逻辑
- 自定义异常处理器能够提供更友好、可读性更强的错误信息,使用户更容易理解问题的本质,这对于客户端开发人员和最终用户都是有益的
统一异常处理
- 在程序运行时,难免会产生一些异常错误
- 当后端发生异常时,前端将无法正确获取到数据
实例理解
- 此处我们创建一个 UserController 类,并编写一个存在空指针异常的 test 方法
javapackage com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @RequestMapping("/test") public int test() { Object obj = null; obj.hashCode(); return 1; } }
- 在浏览器中输入对应的 URL ,来访问调用 UserController 类中的 test 方法
- 我们发现浏览器直接显示 500,表示服务器错误
- 此时前端是无法对该页面进行处理的
- 因此无论是否出现异常,后端都应该给前端返回约定格式的数据,这时候统一的异常处理就非常有必要了
javapackage com.example.demo.component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; @ControllerAdvice @ResponseBody public class MyExceptionAdvice { @ExceptionHandler(NullPointerException.class) public HashMap<String,Object> doNullPointerException(NullPointerException e) { // 自定义异常处理 HashMap<String,Object> result = new HashMap<>(); result.put("code",-1); result.put("msg","异常类型:" + e); result.put("data",null); return result; } }
- @ControllerAdvice 注解用于定义全局控制器通知,它允许将全局性的处理逻辑应用于整个应用程序中的多个控制器
- @ExceptionHandler 注解用于处理整个应用程序中发生的异常,即 当任何控制器抛出异常时,可以在这里定义统一的处理逻辑,而不需要在每个控制器中单独处理
- 通过对空指针异常的统一处理
- 我们实现了当 控制器 出现空指针异常时,后端将会返回一个包含错误信息的 JSON 对象,该对象包含 错误码、错误信息、数据
- 该JSON 对象有助于前端对其进行相应的处理
异常全部监测
- 在生产环境中,我们可能会无意识的写出一些错误代码而导致各种出现异常,这是很难预料到的
- 如 算数异常、数组越界异常、类型转换异常 等
- 但是我们有必要针对每一个异常都写一个单独的处理方法吗? 如上文对 空指针异常 处理的 doNullPointerException 一样
- 这显然是没必要的
- 因为 我们可以对所有异常进行统一处理,对个别有要求的异常进行特殊处理
实例理解
- 此处我们创建一个 UserController 类,并编写一个存在 数组越界异常的 arr 方法
javapackage com.example.demo.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { @RequestMapping("/arr") public int arr() { int[] array = new int[3]; for (int i = 0; i < 4; i++) { array[i] = i; } return 1; } }
- 此处我们直接对 Exception 进行异常统一处理
- Exception 是所有异常的父类
javapackage com.example.demo.component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; @ControllerAdvice @ResponseBody public class MyExceptionAdvice { @ExceptionHandler(Exception.class) public HashMap<String,Object> doException(Exception e) { // 自定义异常处理 HashMap<String,Object> result = new HashMap<>(); result.put("code",-2); result.put("msg","异常类型:" + e); result.put("data",null); return result; } }
- 在浏览器中输入对应的 URL ,来访问调用 UserController 类中的 arr 方法
- 成功返回了一个包含错误信息的 JSON 对象,且异常类型为 数组越界异常
实例理解二
- 此处我们对 Exception ,即所有异常的父类 进行了异常统一处理
- 此外我们还单独对 NullPointException ,即空指针异常 进行了异常统一处理
javapackage com.example.demo.component; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; @ControllerAdvice @ResponseBody public class MyExceptionAdvice { @ExceptionHandler(Exception.class) public HashMap<String,Object> doException(Exception e) { // 自定义异常处理 HashMap<String,Object> result = new HashMap<>(); result.put("code",-2); result.put("msg","异常类型:" + e); result.put("data",null); return result; } // 对 空指针异常进行特殊处理 @ExceptionHandler(NullPointerException.class) public HashMap<String,Object> doNullPointerException(NullPointerException e) { // 自定义异常处理 HashMap<String,Object> result = new HashMap<>(); result.put("code",-1); result.put("msg","异常类型:" + e); result.put("data",null); return result; } }
- 此时在浏览器中输入对应的 URL 对上文存在空指针异常的 test 方法进行访问调用
- 由上图可知,当 父类和子类异常 同时存在的情况下,优先子类自己的异常处理
- 从而可以实现 对所有异常进行统一处理,对个别有要求的异常进行单独的特殊处理