处理规范(标准)
我们在处理异常的过程中通常要遵循一定的设计规范,例如:
- 捕获异常时与抛出的异常必须完全匹配,或者捕获异常是抛出异常的父类类型。
- 避免直接抛出RuntimeException,更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常(例如ServiceException)。
- 捕获异常后必须进行处理(例如记录日志)。如果不想处理它,需要将异常抛给它的调用者。
- 最外层的逻辑必须处理异常,将其转化成用户可以理解的内容。
- 避免出现重复的代码(Don’t Repeat Yourself),即DAY原则。
springboot工程中的异常处理方式
一、自行处理异常:在控制层中,添加try{}catch(){}(也称之为 异常处理的模板代码),具体代码如下:
@RequestMapping("doCompute/{n1}/{n2}")
@ResponseBody
public String doCompute(@PathVariable Integer n1,
@PathVariable Integer n2){
try{
需要处理异常的部分代码
return "Result is "+result;
}catch(ArithmeticException e){
return "exception is "+e.getMessage();
}
}
or throwable(不推荐)
二、在Controller类中添加异常处理方法:
这种处理异常的方式通常用于较少的Controller类的异常处理
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public String doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
return "计算过程中出现了异常,异常信息为"+e.getMessage();
}
其中@ExceptionHandler(ArithmeticException.class),注解描述的方法为异常处理方法(注解中的异常类型为可处理的异常类型)
三、控制层中全局异常处理方法:
当项目由多个控制层类中有多个共性异常的处理方法定义时,我们可以将这些方法提取到公共的父类对象中,但是这种方式是一种强耦合的实现,不利于代码的维护。
借助spring框架中web模块定义的全局异常处理规范进行实现,例如定义全局异常处理类,代码如下:
package com.cy.pj.common.web;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//@ControllerAdvice
//@ResponseBody
@RestControllerAdvice//==@ControllerAdvice+@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public String doHandleArithmeticException(ArithmeticException e){
return "the exception msg is"+e.getMessage();
}}
@RestControllerAdvice 注解描述的类为全局异常处理类,当控制层方法中的异常没有自己捕获,也没有定义其内部的异常处理方法,底层默认会查找全局异常处理类,调用对应的异常处理方法进行异常处理。
异常处理的优先级顺序:系统会有限查找有没有自行捕获异常的方法,如果控制层方法中的异常没有自己捕获,再找定义的控制层内的异常处理方法,如果也没有定义其内部的异常处理方法,底层默认会查找全局异常处理类。
异常处理的目的:
有效提高其用户体验,加强系统的容错能力!
注意:
将来在处理各种异常时(如ServiceException、GlobalException、ArithmeticException),因处理异常过程中要遵循一定的设计规范,且以上各种小异常都继承与RuntimeException(底层RuntimeException又继承自Exception),且规范中也规定避免直接抛出RuntimeException,但是我们在处理异常时对未来可能会产生的异常无法进行预测,所以一般在处理小异常之后会再捕获异常的父类类型异常RuntimeException!同样的,异常处理的优先级顺序也是按照日常生活中的“连带责任”方式,先找“儿子”再找“父亲”(方便理解与记忆)。
没有处理不了的异常
能够匹配上的异常处理方案优先级比较高,一级一级往上查找,最后实在处理不了的异常(包括RuntimeException和Exception),那么都可以交给Throwable来处理!代码如下:
待补充...