分享
 
 
 

JSP/Servlet/JSF-Java异常框架设计

王朝java/jsp·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

什么是异常?

异常(exception)应该是异常事件(exceptional event)的缩写。

异常定义:异常是一个在程序执行期间发生的事件,它中断正在执行的程序的正常的指令流。

当在一个方法中发生错误的时候,这个方法创建一个对象,并且把它传递给运行时系统。这个对象被叫做异常对象,它包含了有关错误的信息,这些信息包括错误的类型和在程序发生错误时的状态。创建一个错误对象并把它传递给运行时系统被叫做抛出异常。

一个方法抛出异常后,运行时系统就会试着查找一些方法来处理它。这些处理异常的可能的方法的集合是被整理在一起的方法列表,这些方法能够被发生错误的方法调用。这个方法列表被叫做堆栈调用(callstack)

运行时系统搜寻包含能够处理异常的代码块的方法所请求的堆栈。这个代码块叫做异常处理器,搜寻首先从发生的方法开始,然后依次按着调用方法的倒序检索调用堆栈。当找到一个相应的处理器时,运行时系统就把异常传递给这个处理器。一个异常处理器要适当地考滤抛出的异常对象的类型和异常处理器所处理的异常的类型是否匹配。异常被捕获以后,异常处理器关闭。如果运行时系统搜寻了这个方法的所有的调用堆栈,而没有找到相应的异常处理器。

怎么设计异常框架

任何的异常都是Throwable类(为何不是接口??),并且在它之下包含两个字类Error / Exception,而Error仅在当在Java虚拟机中发生动态连接失败或其它的定位失败的时候,Java虚拟机抛出一个Error对象。典型的简易程序不捕获或抛出Errors对象,你可能永远不会遇到需要实例化Error的应用,那就让我们关心一下Exception

Exception中比较重要的就是RuntimeException-运行时异常(当然这个名字是存在争议的,因为任何的异常都只会发生在运行时),为什么说这个类时很重要的呢?因为它直接关系到你的异常框架的设计,仔细看RuntimeException

A method is not required to declare in its throws clause any subclasses of RuntimeException that might be thrown during the execution of the method but not caught.

-可能在执行方法期间抛出但未被捕获的 RuntimeException 的任何子类都无需在 throws 子句中进行声明。

也就是说你的应用应该不去“关心”(说不关心是不服责任的,但只是你不应该试图实例化它的字类)RuntimeException,就如同你不应该关心Error的产生与处理一样!RuntimeException描述的是程序的错误引起来的,因该由程序负担这个责任!(从责任这个角度看Error属于JVM需要负担的责任;RuntimeException是程序应该负担的责任;checked exception 是具体应用负担的责任)

那就有人会问,那我该关心什么!答案就是除了Error与RuntimeException,其他剩下的异常都是你需要关心的,而这些异常类统称为Checked Exception,至于Error与RuntimeException则被统称为Unchecked Exception.

异常的概念就这些了,即使你在网络上搜索也就不过如此,是不是感觉到有点清晰又有点模糊?那么怎么该如何在这样单薄而模糊的概念下设计J2EE的异常框架呢?

解决方案:J2EE异常框架

我们拿一个模拟的例子来说明异常框架的设计过程,比如我们要对外提供doBusiness()这个业务方法

public void doBusiness() throws xxxBusinessException

当客户端调用这样的方法的时候应该这样处理异常(包括处理RuntimeException , checked exception)

记住,无论如何我们都不希望或者确切的说是不应该将RuntimeException这样的异常暴露给客户的,因为他们没有解决这个问题的责任!

我们暂时将Struts中的某个Action看作时客户端,其中doExecute(....)要调用doBusiness()这个方法

public void doAction(......)

{

try

{

xxx.doBusiness();

}

catch(Exception e)

{

if(e instanceof RuntimeException)

{

// catch runtime exception

// 你可以在这里将捕获到的RuntimeException

// 将异常通知给某个负责此程序的程序员,让他知道他

// 自己犯了多么低级的错误!

}else

{

//checked exception such as xxxBusinessException

//将这样的异常暴露给客户显示

}

}

}

我们可以这样设计xxxBusinessException

public class xxxBusinessException extends ApplicationException

{

public xxxBusinessException(String s){

super(s);

};

import java.io.PrintStream;

import java.io.PrintWriter;

public class ApplicationException extends Exception {

/** A wrapped Throwable */

protected Throwable cause;

public ApplicationException() {

super("Error occurred in application.");

}

public ApplicationException(String message) {

super(message);

}

public ApplicationException(String message, Throwable cause) {

super(message);

this.cause = cause;

}

// Created to match the JDK 1.4 Throwable method.

public Throwable initCause(Throwable cause) {

this.cause = cause;

return cause;

}

public String getMessage() {

// Get this exception's message.

String msg = super.getMessage();

Throwable parent = this;

Throwable child;

// Look for nested exceptions.

while((child = getNestedException(parent)) != null) {

// Get the child's message.

String msg2 = child.getMessage();

// If we found a message for the child exception,

// we append it.

if (msg2 != null) {

if (msg != null) {

msg += ": " + msg2;

} else {

msg = msg2;

}

}

// Any nested ApplicationException will append its own

// children, so we need to break out of here.

if (child instanceof ApplicationException) {

break;

}

parent = child;

}

// Return the completed message.

return msg;

}

public void printStackTrace() {

// Print the stack trace for this exception.

super.printStackTrace();

Throwable parent = this;

Throwable child;

// Print the stack trace for each nested exception.

while((child = getNestedException(parent)) != null) {

if (child != null) {

System.err.print("Caused by: ");

child.printStackTrace();

if (child instanceof ApplicationException) {

break;

}

parent = child;

}

}

}

public void printStackTrace(PrintStream s) {

// Print the stack trace for this exception.

super.printStackTrace(s);

Throwable parent = this;

Throwable child;

// Print the stack trace for each nested exception.

while((child = getNestedException(parent)) != null) {

if (child != null) {

s.print("Caused by: ");

child.printStackTrace(s);

if (child instanceof ApplicationException) {

break;

}

parent = child;

}

}

}

public void printStackTrace(PrintWriter w) {

// Print the stack trace for this exception.

super.printStackTrace(w);

Throwable parent = this;

Throwable child;

// Print the stack trace for each nested exception.

while((child = getNestedException(parent)) != null) {

if (child != null) {

w.print("Caused by: ");

child.printStackTrace(w);

if (child instanceof ApplicationException) {

break;

}

parent = child;

}

}

}

public Throwable getCause() {

return cause;

}

}

而"聪明"的读者肯定要问我那doBusiness()这个业务方法该如何包装异常呢?

public void doBusiness() throw xxxBusinessException

{

try

{

execute1(); // if it throw exception1

exexute2(); // if it throw exception 2

.... .....

}

catch (exception1 e1)

{

throw new xxxBusinessException(e1);

}

catch(exception2 e2)

{

throw new xxxBusinessException(e2);

}

........

}

也可以这样

public void doBusiness() throw xxxBusinessException

{

try

{

execute1(); // if it throw exception1

exexute2(); // if it throw exception 2

.... .....

}

catch (Exception e)

{

// 注意很多应用在这里根本不判断异常的类型而一股脑的采用

// throw new xxxBusinessException(e);

// 而这样带来的问题就是xxxBusinessException"吞掉了"RuntimeException

// 从而将checked excption 与unchecked exception混在了一起!

// 其实xxxBusinessException属于checked excpetion ,它根本不应该也不能够理睬RuntimeException

if(! e instanceof RuntimeException) throw new xxxBusinessException(e);

}

}

总结

1。JAVA的异常分为两类: checked exception & unchecked excpetion

2。应用开发中产生的异常都应该集成自Exception 但都属于checked excpetion类型

3。应用中的每一层在包装并传递异常的时候要过滤掉RuntimeException!

4。从责任这个角度看Error属于JVM需要负担的责任;RuntimeException是程序应该负担的责任;checked exception 是具体应用负担的责任

5。无论如何我们都不希望或者确切的说是不应该将RuntimeException这样的异常暴露给客户的,因为他们没有解决这个问题的责任!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有