java中异常机制的总体设计
1 前言
2 输入异常
输入异常,即验证输入值时发生的异常。此种异常往往由于以下几种情况导致:
- 系统数据异常。
- 非法的调用。
当此种异常发生时,不需要直接调用者做任何事情,因此可以使用非受验异常。
按照抛出异常代码所在层的不同,设置两种异常:
- 对外层(如controller层)ConrollerIllegalArgumentExceptio
- 内层(如service、dao层等) ServiceIllegalArguemtnException
2.1 抛出
2.1.1 对外层(如controller层)ConrollerIllegalArgumentException
对外层发生输入异常时,设置要返回给外层的提示信息并直接抛出对外层异常。
2.1.2 内层(如service、dao层等) ServiceIllegalArguemtnException
内层发生输入异常时,抛出内层异常。
2.2 处理
2.2.1 对外层(如controller层)ConrollerIllegalArgumentException
统一在调用栈的顶端拦截此异常,拦截对外层异常后,把对外层中的提示信息返回给外部。
2.2.2 内层(如service、dao层等) ServiceIllegalArguemtnException
拦截所有内层异常,执行以下流程:
- 保存错误跟踪信息。
- 设置要返回给外层的信息,设置要返回给外部的提示信息,包装并抛出对外层异常。
3 执行中异常 BusinessProcssRuntimeException
执行过程中如果发生了异常(注意,异常指的不是不同的程序分支),是由于以下几点原因导致的:
- 编程错误导致的运行时异常。
- 不可预知的外部(硬件故障,配置错误,文件丢失,服务器无法使用). 当这些情况发生时,并不需要直接调用者做任何事情(当然也不阻止它做一些处理工作),因此也同样使用非受验异常。
3.1 抛出
直接抛出执行中异常。
3.2 处理
在调用栈的顶部拦截执行中异常,执行以下流程:
- 保存错误跟踪信息。
- 向外层返回统一的提示信息。
4 输出异常 BusinessOutPutException
输出异常指的是,在程序流程执行完之后,没有得到预期的结果。 举例来说: 以用户登录为例。当使用输入的ID和PS在数据库中进行查询后,没能得到一个用户,那么这就是没有得到一个预期的结果。 而这种情况也分几种:
- 用户名是存在的,但是密码是错误的。
- 用户名不存在。
以上这些情况具有以下特点:
- 是可以预期的。
- 应该是设计中的一部分。
- 是异常,是程序流程中利用输入值得到的一种结果,并不是错误。
- 应该保证能够通知到直接调用者。
因此使用受验异常。
4.1 抛出
在得到的结果不是预期结果时,直接抛出输出异常。
4.2 处理
直接调用者需要拦截,并进行处理。
异常分为两种。
4.3 业务异常
程序执行流程中,除正常流程意外的其他流程发生时,称其为业务异常。
4.3.1 特点
- 业务异常是整个程序流程中的一部分,不是错误。因此如果出现业务异常,说明程序运行是没有问题的,并不需要进行修复。
- 需要保证调用者对其进行处理。(因此它是完整业务流程中的一部分)
4.4 程序错误
除了业务异常以外的情况。如果发生,那么就说明需要对程序进行修复。
4.4.1 特点
- 需要通知适合的人员。
- 需要保留错误信息,包括放生的时间、地点、事件。
- 程序能够体面地退出。
h + 如果有客户端,应该保证客户端操作者只能看到为他定制的信息,而不要把内部的详细错误信息露出(出于安全及用户体验的考虑)。
4.5 他们的比较
异常条件 | 意外事件 | 错误 |
---|---|---|
认为是(Is considered to be) | 设计的一部分 | 难以应付的意外 |
预期发生(Is expected to happen) | 有规律但很少发生 | 从不 |
谁来处理(Who cares about it) | 调用方法的上游代码 | 需要修复此问题的人员 |
实例(Examples) | 另一种返回模式 | 编程缺陷,硬件故障, |
配置错误,文件丢失,服务器无法使用 | ||
最佳映射(Best Mapping) | 已检查异常 | 未检查异常 |