java的异常种类很多,而且同一种异常,会在不同的方法中出现。如果完全按照,那里出异常,那里就给详细提示信息,编写程序就会非常的痛苦,而且不是那么实用。就如同数据库的五范式,实际中,做到3范式就够了。
java web项目中处理异常的方式主要有两种:异常拦截器和truts2的全局异常处理机制。
java中的异常有checked和unchecked两种,两者关系:
checked unchecked
对应Exception类 对应RuntimeException类
Exception类必须处理 RuntimeException类可不处理
Exception类出现的时候,用户可以纠正,然后程序继续正常运行 RuntimeException类出现的时候,表明程序有问题,只有开发人员才能处理
对于RuntimeException类,如果我们什么都不做,一旦出现,系统会打印出堆栈信息,告诉开发人员,什么异常,在那里。这个在开发的时候,非常有用,而且非常的方便,深受开发人员喜欢。再加上程序会经过测试,交付的代码很难再出现这种异常,于是大家更是爱之有加。如果真是这么做,就好比给系统装了一个隐形地雷,地雷爆炸了,我们还不知道在那里炸开的。原因很简单,开发的时候,有堆栈信息,运行的时候,什么都没有。基于RuntimeException类的特征,如果我们多做一点点,在异常拦截器中拦截(留意:我们虽然只编写拦截RuntimeException这句代码,但是,拦截的是其所有的、具体的子类。),保存到日志上,而后以页面友好的方式告诉用户:系统出问题,赶快打电话给开发商吧。虽然,客户可能会抱怨,但是,我们还是可以通过日志找到问题,解决问题。再说,用户也知道“航天飞机有可能爆炸”的道理。但是,有问题,不解决,那绝对是不可原谅的。呵呵,真是多一点,海阔天空;少一点,天崩地裂。
总结:对于RuntimeException类,我们只在异常拦截器中拦截,记录异常日志,并以统一的形式告诉用户。
附注:并不是unchecked就一定只有开发人员才能处理,比如InetSocketAddress类的构造方法public InetSocketAddress(String hostname, int port),IllegalArgumentException - 如果 port 参数超出有效端口值的范围,或者主机名参数为 null。如果程序一定要传大于65535或小于0的port值,也是可以提醒用户改成介于 0 和 65535 之间的有效值。但是,如果程序真的写成这样,我想开发人员应该好好思考思考,review代码,并再仔细测试。实际情况应该是,用户故意要输入一个大于65535或小于0的值,而你提示用户不能这样做。
对于Exception类,系统是没有问题的,用户是可以纠正的。这时候,就一定要以简单明了的方式告诉用户去改正这个异常。比如,InputStream类 public FileReader(String fileName) throws FileNotFoundException方法,FileNotFoundException - 如果指定文件不存在,或者它是一个目录,而不是一个常规文件,抑或因为其他某些原因而无法打开进行读取。这么做虽然可以给用户一个清晰的提示,但是作为开发人员就要写很多提示,如果dao层,service层,action层都写的话,不但很多,而且有些可能是重复的。我们反思一下,我们这么做符不符合实际情况。如果,我们有足够的人力,物力,时间。开发这样稳健的程序,再好不过了。我想,大部分的领导都是想多块好省的做完项目,特别对于那些非技术出生的领导,更是像催命鬼一样,崔得开发人员自己写完代码,都不忍心再看第二遍,太烂。我想,可以借鉴RuntimeException类的处理方式,在异常拦截器中拦截,保存到日志上,而后以页面友好的方式告诉用户:socket通讯端口30000被占用,请去配置页面修改成其它端口号。这里稍微不同的是,必须对常用的异常分类捕获, ClassNotFoundException,DataFormatException,IOException,NoSuchFieldException,NoSuchMethodException等等异常进行捕获说明。这样,我们在dao层,service层,action层就可以不管三七二十一,都往上throws Exception,而且只需要拷贝这两个单词到任何方法后面就可以了,方法内部就不需要烦人的try...catch..finally。美观又实用。这么做,虽然可以解决通用问题,但是,对于一些特别重要的异常,需要精确的描述,就如上面例子中的端口被占用,我们需要另想办法解决。这时候,我们就需要自定义一个异常并放于异常拦截器中(即异常拦截器也拦截自定义异常),把这些特殊异常全部转成自定义异常;或是就用truts2的全局异常处理机制,让它帮我们去拦截。两种都一样,为了统一起见,还是用异常拦截器好一点。
总结:对于Exception类,我们在异常拦截器中分类拦截,记录异常日志,并以统一的形式告诉用户;对于需要特殊说明的异常,转换成自定义异常。
以下有几篇非常好的文章:
项目中异常设计及处理总结:http://ljh2008.iteye.com/blog/832629
项目中的异常处理:http://hi.baidu.com/javagarden/item/cb345142bc8eed14896d1092
java web项目整体异常处理机制:http://www.iteye.com/topic/1073599
Java异常处理:http://blog.csdn.net/SamNewer/article/details/5187650
Java异常与错误的区别及异常体系:http://www.233.com/Java/zhuanye/20110219/154033310.html
粗浅理解,还望同学们指正。