SSH异常和日志处理方案
1.
数据库操作异常:
系统异常:这类异常(如 应用服务器异常)由系统本身的低级异常引起,例如数据库连接失败、内存溢出、空指针异常等等,这类异常不需要出现在前台,因为用户看不懂也没有必要看到这些异常信息。这类异常需要在日志中进行完整记录以供日后开发人员进行查看分析。
应用异常:即自定义异常(业务异常,(>可以把非务异常定义为系统异常)如 权限不够等),这类异常需要通过前台反馈给用户,友好提示用户当前操作异常。应用异常通过系统异常转换而来,例如新建用户时,发生“主键冲突异常”,则需要在UserinfoDao中将“主键冲突异常”捕获,并转换为应用异常,异常提示信息设为“该用户名XXX已存在,请使用其它用户名”,并将该异常信息反馈给前台。只要系统异常影响到的用户的当前操作,就必须给用户提示信息,比如“系统后台发生错误,请稍后再试”等。应用异常应按照提示方式的异常进行分类,对应不同的提示页面。
2.
3.
1、避免过大的try块,不要把不会出现异常的代码放到try块里面,尽量保持一个try块对应一个或多个异常。
2、细化异常的类型,不要不管什么类型的异常都写成Excetpion。catch语句表示我们预期会出现某种异常,而且希望能够处理该异常。异常类的作用就是告诉Java编译器我们想要处理的是哪一种异常,然后针对具体的异常类进行不同的处理。例如在DAO层中我们应该只捕获SQLException或DataAccessException(Spring自定义的数据访问异常类)这些数据库异常类,其他的异常NullPointException、NumberFormatException等应通过检测代码增加其健壮性来解决,而不应该通过try..catch(Exception e)…语句捕获所有的异常。
3、不要把自己能处理的异常抛给别人,不要忽略捕获的异常,捕获到后要么处理,要么转译,要么重新抛出新类型的异常。。处理方式包括:
Ø
Ø
Ø
4、如果对catch块尽量保持一个块捕获一类异常,在catch语句中尽可能指定具体的异常类型,必要时使用多个catch。
例:
}
这段代码捕获了异常,但实际上对异常并没有进行处理,可以算得上Java编程中的杀手。按照这个方式,在DAO层发生异常被忽略,Service层就认为DAO层运行正确,就不会回滚,事务控制就没有任何作用!!!
Ø
Ø
Ø
所以该处的处理原则应是:如果该处异常需要能转化为业务异常反馈给用户,则需要捕捉低级异常并转换成业务异常上抛,否则不做任何处理!!!
6、不要用try...catch参与控制程序流程,异常控制的根本目的是处理程序的非正常情况。
4.
本系统使用SSH框架,DAO+Service+Action三层架构,捕获原则是只有将低级系统异常转化为应用异常的需要才进行捕捉。
各层的处理方式如下:
DAO层:引发DAO异常的问题往往是不可恢复的,如数据连接失败,SQL语句存在语法错误,强制捕捉的检查型异常除了限制开发人员的自由度以外,并没有提供什么有意义的作用。因此,Spring的异常体系都是建立在运行期异常的基础上,这些异常都继承于DataAccessException(RuntimeException异常子类),所以,除了出于将低级系统异常转化为(>自定义,业务异常)应用异常的需要,没有必要捕获异常,让DAO类自动上抛异常即可。
Service层:只捕获自定义(>业务异常)应用异常,其他异常上抛。
Action:只捕获自定义应用异常(>根据异常类型转到对应视图,返回对应业务异常信息给用户),(>可以Action这里把自定义的异常处理,把自定义的异常信息返回给客户端)其他异常上抛。Struts2提供了异常拦截器,拦截器会将定义的异常捕获,记录日志,然后根据配置的异常的类型顺序跳转到相应的页面。配置如下:
struts.xml配置文件
<interceptor-ref
</interceptor-ref>
<global-exception-mappings><!—异常类和跳转页面配置
</global-exception-mappings>
com.***.***.exception.BasicException为自定义应用异常,如果客户端的请求执行过过程中产生com.***.***.exception.BasicException异常,则会自动转到basicerror页面,从而给用户相应的提示。
basicerror页面
<%@
异常名称 | 说明 |
com.***.***.exception.BasicException | 基础异常类,本系统中所有的自定义异常类均需继承本类 |
com.***.***.exception. DuplicateKeyException | 主键冲突异常,继承BasicException |
例:(>DAO)
Userinfo save方法异常处理
@Override
6.
系统中目前配置了三个日志记录器,一个为异常记录器,专门记录异常信息,日志文件到达一定大小后将产生新的日志文件,文件名称为exception.log,另一个为系统运行记录器,按照日期记录所有的日志信息。
小结:如果DAO层和Service不捕获异常而在web层捕获异常,web成功捕获异常,spring事务管理成功!
小结:如果Service捕获异常并处理而不向外抛出,web层捕获不到异常,spring事务管理失败!
DAO的每一个方法自己捕获异常并处理而不向外抛出,Service层捕获不到异常,Web层同样捕获不到异常,spring事务管理失败!
小结: 如果DAO的每一个方法不捕获异常,Service层捕获DataAccessException异常并抛出自己定义异常(自定义异常为DataAccessException的子类),
Web层可以捕获到异常,spring事务管理成功!
1.spring在进行声明时事务管理时,通过捕获Service层方法的DataAccessException来提交和回滚事务的,而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常.
2.我们一般在写DAO层代码时,如果继承JdbcDaoSupport 类,并使用此类所实现的JdbcTemplate来执行数据库操作, 此类会自动把低层的SQLException转化成DataAccessException以及DataAccessException 的子类.
3.一般在Service层我们可以自己捕获DAO方法所产成的DataAccessException,然后再抛出一个业务方法有意义的异常(ps:此异常最好继承DataAccessException),
然后在Web层(struts)捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.