常见异常
常见异常如下图
Error是系统级别的错误,程序代码无法处理的,比如OutOfMemoryError、ThreadDeath等。这些错误发生时,JVM一般会选择线程终止退出,它表示程序在运行期间出现了十分严重、不可恢复的错误,应用程序只能中止运行。程序中显示调用System.exit(1);也会退出虚拟机。
Exception分为两种,运行时异常和检查异常(CheckedException)。
运行时异常是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等。这些是非检查异常,一般由程序中的逻辑错误导致,程序可以不处理,建议不要捕获。检查异常必须捕获,因为编译器会进行检查,非运行时异常都是检查异常,比如上面的IOException、ClassCastException、SQLException。
对于不想处理或未知的异常一直往外抛直至到最上层集中处理,注意集中处理,处理时必须输出对应的日志。如:利用Spring mvc支持异常集中处理特性,不想处理或未知的异常从dao->service->controller往上抛,然后在controller统一集中处理,当然可按需集中处理,如不处理统一交给全局异常处理。
dubbo里为我们做了统一异常处理,即使dao、service不做任何处理,异常一直往上抛就会进入com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke()进行处理,如下图
可以看到,除了java和javax开头的异常和RPCException其余的都会包装成RuntimeException,所以我们在消费者工程中处理时就会发现我们自定义的异常被转换为RuntimeException了,怎么办?在service接口直接抛出自定义异常,不然在消费者工程中是无法用isAssignableFrom或instanceof捕获到的。
isAssignableFrom 与 instanceof
isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。 通常调用格式是
Class1.isAssignableFrom (Class2)
调用者和参数都是 java.lang.Class 类型。
而instanceof 是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。格式是:
oo instanceof TypeName
第一个参数是对象实例名,第二个参数是具体的类名或接口名
我们可以利用这两个方法随意的处理异常的输出(接口输出提示消息 或者 返回类型为ModelAndView时跳转到指定页面):
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public void resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) {
Map<String, Object> resultObject = new HashMap<>();
if (e.getClass().isAssignableFrom(ExceptionCode.SYS_EXCEPTION.getExceptionClass())) {
resultObject.put(KomectUtils.MOBILE_RECODE, ExceptionCode.SYS_EXCEPTION.getErrorCode());
resultObject.put(KomectUtils.MOBILE_MSG, ExceptionCode.SYS_EXCEPTION.getErrorMsg());
} else if (e.getClass().isAssignableFrom(ExceptionCode.RPC_EXCEPTION.getExceptionClass())) {
resultObject.put(KomectUtils.MOBILE_RECODE, ExceptionCode.RPC_EXCEPTION.getErrorCode());
resultObject.put(KomectUtils.MOBILE_MSG, ExceptionCode.RPC_EXCEPTION.getErrorMsg());
} else {
resultObject.put(KomectUtils.MOBILE_RECODE, ExceptionCode.ILLEGAL_ARGUMENT_EXCEPTION.getErrorCode());
resultObject.put(KomectUtils.MOBILE_MSG, ExceptionCode.ILLEGAL_ARGUMENT_EXCEPTION.getErrorMsg());
}
//TODO 将resultObject 输出
}
}
利用springmvc的API HandlerExceptionResolver统一处理异常,需要在springmvc.xml里配置以下
<!--全局异常处理-->
<bean id="globalExceptionResolver" class="com.*.interceptor.GlobalExceptionResolver" />
springboot提供的统一异常处理注解
@ControllerAdvice和@ExceptionHandler来定义一个GlobalExceptionHandler
@ControllerAdvice
@Slf4j
public class ControllerExceptionHandler {
/**
* 捕获自定义异常
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(ActivitiesCheckException.class)
public BaseResult customizeException(ActivitiesCheckException e) {
log.error("======>server catch exception:{}, exception:{}", e.getMessage(), e);
return BaseResult.fail(ILLEGAL_ARGUMENT.getCode(), e.getMessage());
}
}