George

人生就是一次旅行
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

异常处理的讨论

Posted on 2006-04-26 00:18  George  阅读(2066)  评论(8编辑  收藏  举报

最近在考虑以前做项目的时候,设计的异常处理方式是不是合理,这里共享出来给大家讨论,也想了解一下大家的异常处理的方法。异常处理主要包括2种,一种是系统的异常,另外一种是业务逻辑的不合法,这里称为业务逻辑异常可能不太确切,不过我还是把它当做业务逻辑的异常来处理。系统异常直接通过捕获给与友好的错误页面也好,直接报出来也好,我这里不做说明了,对于项目的开发存在大量的业务逻辑的判断合法性,然后给与提示,我主要说说这里。

我认为的业务逻辑的异常打个比方比如,用户输入了一张单据,在单据保存的时候来判断单据的编号是否重复(如果允许输入单据编号的话),给与提示比如“单据编号重复”,然后让用户重新输入。这里是用asp.net做的,在aspx.cs后台代码中,我是这样处理的,

try
{
    Bill bill 
= new Bill();
    
//给以单据实体类赋值.
    
//实例话一个实体操作类
    BillMng mng = new BillMng();
    
//然后保存
    mng.Save(bill);
}

catch(Exception ex)
{
    CommFunc.ShowErrorMessage(
this,ex.Message.ToString());
}

通过BillMng 管理类来管理保存业务单据代码:
/// <summary>
/// 保存业务单据
/// </summary>
/// <param name="bill">单据</param>

public void Save(Bill bill)
{    
    DB db
= new DB();
    
try
    
{    
        
//连接数据库,传递bill参数,调用存储过程
    }

    
catch(Exception e)
    
{
        
throw e;
    }

    
finally
    
{
        
if (db != null)
            db.Close();
    }


}

然后,具体的业务逻辑判断,比如保存前判断单据编号是否在数据库中已经存在。或者通过存储过程直接抛出我经过格式化以后的异常。以下是Oracle存储过程中的代码。
先自定义一个异常变量:
existedData EXCEPTION ;
编号重复判断:
SELECT COUNT(1INTO vCount FROM yourTable  WHERE billNo=vsYouinputBillNo;
if (vCount > 0)  then
    raise existedData ;
end if

--处理其他业务逻辑并保存

EXCEPTION
WHEN existedData THEN       
    RAISE_APPLICATION_ERROR(
-20000,'#单据编号重复!#');
WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR(
-20004'数据库错误:' || SQLERRM);

注意:这里的错误我是通过#号来做了区分,这样业务逻辑的中间层只负责有异常就抛出,在页面展示后台代码中统一捕获。我根据解析#号来判断业务逻辑的处理逻辑出现的异常,其他的异常在这里也直接抛出来,或者可以通过转向另外一个友好错误页面,我这里把所有异常都抛出来,业务逻辑抛出来的异常是自定义的。
/// <summary>
/// 解析数据库和页面中抛出的错误,无白屏
/// 1.页面的错误直接抛出
/// 2.数据库中报的用户定义的异常提示须加#,如提示:#没有数据!#
/// 3.数据库中系统报的错误.
/// </summary>
/// <param name="page">当前页面,可以直接在页面中用this</param>
/// <param name="ErrorMessage">异常的消息,如:ex.Message</param>

public static void ShowErrorMessage(Page page,string ErrorMessage)
{
    
char[] cha = new char[1];
    cha[
0]='#';  //自定义的业务逻辑异常规则
    Random Ram=new Random(unchecked((int)DateTime.Now.Ticks));
    
string vsName="Name" + Ram.NextDouble().ToString();   //生成不重复NAME
    string strRepString =ErrorMessage.Replace("\n","\\n");//替换回车符为空格
    strRepString =strRepString.Replace("\r","\\r");       //替换换行符为空格
    strRepString =strRepString.Replace("\"","");        //替换"符,为中文单引号
    
string[] mess = strRepString.Split(cha,3);            //解析#号,分3段取中间的段是用户提示
    int intErrorIndex = 1;
    
if(mess.Length ==1//如果是页面报错,直接显示,或者转向另外一个友好页面
        intErrorIndex =0;
    page.RegisterStartupScript(vsName,
"<script language='javascript'>alert(\""+mess[intErrorIndex]+"\");</script>");

}

ok.这就是我处理异常的方式,这样代码比较简洁,不用通过函数的返回值来判断是否错误编号,通过alert来显示提示信息。
当然还有很多好的方法,大家都是通过什么方式来处理业务逻辑异常和系统的异常的, 在系统的维护性,扩展性,和健壮性方面这样的做法是不是合理,欢迎回帖讨论。