异常处理规范doc.docx
- 文档编号:25814404
- 上传时间:2023-06-15
- 格式:DOCX
- 页数:28
- 大小:24.48KB
异常处理规范doc.docx
《异常处理规范doc.docx》由会员分享,可在线阅读,更多相关《异常处理规范doc.docx(28页珍藏版)》请在冰豆网上搜索。
异常处理规范doc
异常处理规范
目录
1.目标2
2.异常的分类2
3.框架异常处理模型3
4.定义异常3
5.抛出异常4
6.捕捉异常5
7.处理异常6
8.方法覆盖7
9.服务端/客户端异常8
1.目标
代码下载
瘦客户端
客户端运行环境
http/https
http/https调用
中间层
Web框架
客户端服务运行环境
中间件业务容器
J2EE服务器
数据库
财务总账物流IUFO…
客户层
DMO
数据层
客户端
财务总账物流IUFO…
瘦客户端
客户端运行环境
http/https调用
代码下载
http/https
Web容器
客户端服务运行环境
Web框架
EJB调用,本地协议
EJB调用,本地协议
BServiceEJB
BServiceEJB
BServiceEJB
BServiceEJB
EJB容器
适配
服务
定位器
BService
BP
BP
BP
BP
BP
BService
BP
BService
BService
模块部署器
事务处理器
组件管理器
公共服务
领域服务
数据服务
业务层
中间件框架抽象层
DMO
J2EE服务器
数据库
数据库层
WebContainer
Browser
BootStrapLiveUpdate
数据预单元
通信处理单元
LiveUpdateService
ClientInvokeService
http/https
通信处理单元
数据处理单元
NCClientClassLoader
NCLocator
System
企业应用
EJB
Web
中间件抽象框架
Domain
nc.ear
ejb.jar
web.war
web-inf
ncweb
classes
lib
lib
public
module.jar
classes
lib
private
lib
classes
商业中间件资源
商业中间件名服务
IOC组件名服务
查找
NCLocator
中间件抽象层名服务
远程
接入框架名服务
本地
IOC管理资源
VO
BP
BService
BP
UI
DMO
XML技术
Java技术
WebService技术…
业务规则集成开发环境
规则应用系统
规则系统集成框架
规则服务系统
规则管理系统
规则引擎
业务规则管理系统
规则持续
规则仓库
引擎核心对象
引擎服务API
引擎推理算法
规则执行引擎
规则引擎逻辑架构
事实区
规则集执行上下文3
事实区1
规则集执行上下文1
…
规则集…
事实区2
规则集执行上下文2
规则引擎运行划分
z
y
x
+
+
ActionA
+
z
y
+
x
ActionB
ActionA
决策表
规则引擎
规则执行
语言
业务规则
语言
…
规则语言框架
本文旨在介绍NCV5环境下,采用中间件抽象框架提供的开发模型,对异常定义、使用和捕捉等的处理规范。
2.异常的分类
从异常(错误)的紧要程度和通常反应的处理逻辑来讲,程序员所要关心的异常主要有四类:
ØJVM错误:
这种类型的错误由JVM抛出。
OutOfMemoryError就是JVM异常的一个常见示例。
对JVM异常您无能为力。
它们表明一种致命的情况。
唯一得体的退出办法是停止应用程序服务器(可能要增加硬件资源),然后重新启动系统。
Ø非JVM错误(Error):
表示对整个系统的处理具有严重影响的错误,如cache溢出,中间件框架启动失败等等。
这类异常一般需要中间件方面的参数调整或者重新启动系统。
Ø非受查异常:
在大多数情况下非受查异常由JVM作为RuntimeException的子类抛出。
例如,NullPointerException或ArrayOutOfBoundsException将因代码中的错误而被抛出。
另一种类型的非受查异常在系统碰到配置不当的资源时发生,在这种情况下,系统不能进行合适处理,因此作为非受查异常抛出颇有意义。
还有的规则是,如果您对某个异常无能为力,那么它应当重新封装为非受查异常抛出。
Ø受查异常:
受查异常是一种定制异常,由应用程序或第三方的库抛出,它们预示了处理逻辑中的某个条件尚未满足。
从中间件抽象框架和程序员使用的角度来看,程序员主要关心两类异常,一类为系统异常,一类为应用程序异常,这两类异常在中间件抽象框架和业务方法中都可能遇到,并且处理,因此我们对他们进行更加详细地说明:
Ø中间件框架非受查异常:
这类异常来自于FrameworkRuntimeException,对于这类异常程序员通常不需要特别的逻辑处理,需要通过配置中间件和框架进行解决
Ø业务模块的非受查异常:
业务处理模块如果对于一些处理上的逻辑没有处理能力,需要抛出业务模块的系统异常,该类异常来自BusinessRuntinmeException
Ø中间件抽象框架受查异常:
这类异常来自于FrameworkException,业务模块通常需要捕作他们处理,或者重新封装为业务模块的非受查异常,或者进行适当的处理,然后封装作为业务模块的受查异常抛出,或者完全处理恢复。
目前中间件这类异常主要是ComponentExcetion
Ø业务模块的受查异常:
这类异常来自于BusinessException,由各个业务模块抛出和处理。
为了简单起见,我们把中间件框架的非受查异常和业务模块的非受查异常统一称为系统异常,而中间件抽象框架的受查异常和业务模块的受查异常统一称为为应用异常,他们在中间件框架的异常处理模型中代表了两类不同的处理过程。
3.框架异常处理模型
NC的系统基于B/S结构,从Browser端发起的调用需要经过中间件抽象框架的接入框架进行远程接入,另一方面从效率考虑,服务端对服务端的调用请求没有经过远程的接入过程,而是直接按照引用的方式发起了调用。
无论哪种调用方式,中间件抽象框架都需达成如下的目标:
Ø中间件抽象框架对应用异常不进行任何包装,直接把异常抛给客户端(Browser或者本地客户程序)
Ø远程BService(带有事务)的业务方法抛出异常会导致当前事务回滚
Ø中间件系统异常(如TransactionRollbackException等)在抛出给Browser进行了会转化为BusinessRuntimeException抛出,转化之前中间件抽象框架对异常进行了日志
Ø中间件抽象框架的非受查异常抛出前都进行了日志
4.定义异常
程序员只能定义BusinessException和BusinessRuntimeException的子类,每个产品模块都有改模块内公共的基类异常,他们来自于BusinessException,和BusinessRuntimeException,异常的定义必须严格的按照这个异常的层次进行。
如系统管理框架:
packagenc.vo.sm.exception;
importnc.vo.pub.BusinessException;
publicclassSystemManagerExceptionextendsBusinessException{
…
}
该产品模块的异常都需要从这异常继承而来,如无效的用户异常:
packagenc.vo.sm.exception.sm;
publicclassInvalidUserExceptionextendsSystemManagerException{
…
}
总结起来异常定义的规则如下:
Ø产品模块定义两个基本异常(受查的和非受查的),该异常来自BusinessException或者BusinessRuntimException
Ø该产品模块的所有的子异常来自这两个异常
Ø异常包以
Ø所有的异常名称必须以Exception结尾
Ø所有的一异常定义都必须包含异常链,提供对原始异常的跟踪:
packagenc.vo.sm;
publicclassInvalidUserExceptionextendsSystemManagerException{
publicInvalidUserException(Stringmsg,Throwablethrowable){
super(msg,throwable);
}
publicInvalidUserException(Throwablethrowable){
super(throwable);
}
…
}
Ø
5.抛出异常
中间件抽象框架对异常进行了某些特别的处理,特别是针对远程的BService,因此异常抛出需要结合业务逻辑进行,总结规则如下:
Ø业务模块方法throws部分的受查异常都需要来自业务异常(BusinessException)和BusinessRuntimeException
Ø业务代码不能直接抛出没有任何业务意义的异常如thrownewException(“msg”)
Ø对于远程BService,如果你需要在BService方法中,不希望潜在的异常导致事务回滚,那么请不要在该Bserivce的对应方法throws语句中指定任何的异常,而且不要在实现中抛出任何非受查一场
例如定义BService接口时用下面的形式:
publicvoidservice();
而不是
publicvoidservice()throwsBusinessException
Ø如果受查异常由于调用中间件框架导致(FramworkException子类),但问题在于客户请求本身(如查找的名称不存在),首先进行业务日志,并对他封装为业务异常然后抛出,并且不要保持异常链。
Ø如果受查异常由于调用中间件框架(FramworkException子类)导致,但是不在程序员意料之内的异常,首先进行日志,然后封装为BusinessRuntimeException的子类异常,并且不要保持异常链。
Ø抛出的异常必须具备一定的描述该异常发生的原因的信息,以便定位错误
Ø除了上述描述中要求不要保持异常链的情况外,其他的异常重新抛出后最好保持异常链。
throws语句如何写如下面例子
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
Ø
packagenc.intf.sm;
publicinterfaceSMBService{
publicbooleanvalidUser(Stringuser);//不抛出任何异常,因此事务永远不会自动回滚
publicvoidvalidate(Stringuser)throwsInvalidUserExceptoion;//来自BusinessException
…
捕作到中间件的异常,抛出处理如下:
packagenc.bs.sm;
publicinterfaceSMBServiceImpl{
publicbooleanvalidUser(Stringuser){
try{
…}catch(ComponentExceptionexp){
//能够进行良好的逻辑处理
…
}
}
publicvoidvalidate(Stringuser)throwsInvalidUserExceptoion{
try{
…}catch(ComponentNotFoundExceptionexp){
//可以正常处理
thrownewInvalidUserException(“causedby:
”,exp);
}catch(FrameworkRuntimeExceptionaa){
//无法正常处理
thrownewInvalidUserRuntimeException(“Causedby:
“,aa);
}
…
6.捕捉异常
异常捕作需要考虑两个因素,一个是异常捕捉的粒度,一个敏感资源的释放,异常捕捉的粒度需要考虑该捕获什么样的异常,不该捕获什么样的异常等问题。
异常捕捉的使用规则主要描述如下:
Ø捕捉异常应该尽量的精确(代码逻辑范围内),精确包括异常的类和异常的出向区域
Ø控制try/catch的规模,通常代码中由多个位置抛出多种异常,针对不同的异常有不同的处理时try/catch可以细致一点,对每一类异常单独的进行捕捉。
Ø异常捕捉时,最一般的异常永远放在最后的catch部分
Ø如果代码中涉及到敏感的资源如Connection,Socket,文件等,一定要加上finally处理块,释放资源
Ø不要吃掉可能导致业务问题的异常
ØNullPointException,ArrayIndexOutofBOundException,SQLExceptin,DbException、IllegalArgumentException等异常,以及中间件框架中抛出的ComponentException通常是业务相关的,需要按照业务逻辑进行捕捉处理
Ø对于远程的BService,如果需要捕作非受查的异常,请捕作BusinessRuntimeException,非受查异常在中间件框架处理后,到达客户端的异常不一定是在原始代码中跑出的非受查异常,因此需要特别注意。
Ø如果异常需要抛出给前端应用(ui),出于安全的考虑可能不希望前端程序保留异常的链,这时候需要首先日志改异常,然后把该异常转化为业务异常,去掉异常链抛出
Ø如果异常已经在throws语句中抛出,一般不需要进行捕捉和处理
7.处理异常
异常捕捉后的处理为异常处理的一个关键部分,异常处理一方面需要恢复业务逻辑的得一致性,另外一方面还需要为系统提供良好的跟踪能力。
因此异常处理我们可以按照下面的原则进行:
Ø如果捕捉到异常后,不会再次把异常抛出(吃点异常),如果有跟踪的必要性对异常进行日志工作,日志的级别根据业务逻辑可以选用debug或者warn。
对于对系统的表现有一定影响的采用warn,而几乎没有影响的采用debug
Ø如果捕捉到的异常需要再次包装抛出,包装后的异常必须来自BusinessException或者BusinessRuntimeException
Ø如果捕捉了InvokeTragetException,不能把该异常直接抛出,而是需要对其中的目标异常进行处理(getTargetException())
Ø中间件抛出的SystemException,NamingException异常应用程序捕捉后首先进行日志,然后转化为BusinessException/BusinessRuntimeException的子类,不需要保持异常链
ØSQLException必须进行捕捉和处理,进行日志处理,并且转化为对应的BusinessException/BusinessRuntimeException的子类,不需要保持异常链
Ø如果捕捉到的异常,处理抛出后,去掉了异常链,对原始异常应该首先进行日志
Ø如果异常抛出后,保持了异常链,在抛出之前对原始的异常不需要进行日志工作
下面作为一个例子我们描述一下异常处理的基本过程
packagenc.bs.demo.finance;
importnc.bs.demo.hr.HRException;
importnc.bs.demo.hr.IHRService;
importnc.bs.demo.supply.ISupplyService;
importnc.bs.demo.supply.SupplyException;
importmon.NCLocator;
importnc.bs.framework.exception.ComponentException;
importnc.bs.logging.Log;
importnc.vo.pub.BusinessRuntimeException;
publicclassSampleBServiceImpl{
//根据需要选择适合的日志API,如果动态日志采用Logger
privatestaticfinalLoglog=Log.getInstance(SampleBServiceImpl.class);
publicvoidservice(Stringaccount)throwsFinanceException{
try{
ISupplyServicesupplyService=(ISupplyService)NCLocator.getInstance().lookup(ISupplyService.class.getName());
supplyService.service(account);
IFinanceServicefinService=(IFinanceService)NCLocator.getInstance().lookup(IFinanceService.class.getName());
finService.balance(account);
IHRServicehrService=(IHRService)NCLocator.getInstance().lookup(IHRService.class.getName());
hrService.service();
}catch(ComponentExceptione){
//该异常作为业务处理经常要面对的异常因此我们做一些包装,但是我们不希望抛出
//去的异常暴露我们的非业务的异常链,因此首先日志它,然后重新包装出去
log.error("处理账户:
"+account+"出现错误",e);
thrownewFinanceException("所要的服务没有安装,请购买该服务模块:
"+IFinanceService.class);
//e.printStackTrace();
}catch(FinanceExceptione){
//异常为本模块业务的异常,因此抛出,一般情况下不用捕捉该异常
throwe;
}catch(SupplyExceptione){
//其他模块的业务异常,包装抛出,保持异常链
thrownewFinanceException("服务失败",e);
}catch(NullPointerExceptione){
//特别的异常处理,预料之外的异常,包装抛出,保持异常链,也可以根据需要抛出为BusinessRuntimeExcepiton的模块子类异常
thrownewFinanceException("服务失败",e);
//thrownewFinanceRuntimeException("服务失败",e);
}catch(HRExceptione){
//该异常对业务没有任何影响,因此我们吃掉该异常,但是为了跟踪,我们需要日志
log.debug("通知人力资源失败:
"+e.getMessage());
//如果改行为比较要紧采用警告
//log.warn("通知人力资源失败",e);
}catch(BusinessRuntimeExceptione){
//最普通的异常放在最后面处理,这里我们需要对BusinessRunitmeException进行处理
//log.error("服务失败",e);
//thrownewFinanceException("服务失败",e);
}
}
}
8.方法覆盖
在类继承的时候,经常需要覆盖父类的方法,这时候应当按照约定的规则进行异常的处理,例如:
packagenc.bs.framework.connector.client;
publicclassNCCLassLoaderextendsClassLoader{
publicvoidloadClass(Stringname)throwsClassNotFoundException{
Classclazz=null;
try{
//基于网络的的列加载处理
}catch(IOExceptionioe){
}
returnclazz;
}
}
这样的处理是不符合ClassLoader的一般约定的,因为系统在没有加载到类的时候,根据协议应该抛出ClassNotFoundException,而这里返回为null。
一般的类似的处理出现在具有返回值和具有异常抛出的方法中,对于这样的方法我们要十分仔细的约定什么时候抛出异常,什么时候正常返回,避免不恰当的处理。
9.服务端/客户端异常
在客户服务器的体系下,客户端的逻辑需要服务端进行处理,这时候一些特定服务端的异常可能会被抛出给调用方。
NC的系统可以跨平台的运行在多种应用服务器之下,客户端的代码不应该看到特定服务端的异常,因此对这类异常必须经过处理才能抛给客户端。
如WEBSPHERE特定的异常。
对于服务端/客户端异常处理的要求在框架中,要求接入框架进行特定的异常处理,对于这些特别的服务端异常,系统以业务框架是别的BusinessRuntimeException的形式进行抛出。
应用程序抛出的Ru
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 异常 处理 规范 doc