工业级应用中关于异常封装的一些感悟

        Java的异常体系想必大家都熟记于心的,那么在日常的编码过程中,大家又是如何实施的呢?针对checked和unchecked exception大家的理解又有多少呢?

        几乎所有的书本上都给出了一个conclusion,如果日常事务能从异常中恢复,那么建议用checked exception,如果不能recover from,那么就是unchecked的了.

        大家想过没有,这里的恢复指的是什么?真的不能恢复吗?堆栈,Thread又是如何表现的呢?

        This exception That bug,静观皆自得.好了,开场白过后,这里,主要总结一下自己对Java Exception的理解,也欢迎大家留言,发表自己的心得~

(1)  一种简单的checked,unchecked exception的理解是,将checked exception作为业务异常去使用(关注它,则处理它,不关注,re-throw),可以使用errorCode之类的进行wrap,不要迷恋recover from,自己去实地感知一下,就全了然了;

(2) checked exception有额外的编码开销,君不见一会throws one exception from method ,一会又throw new XXXException from exception spot,同时过多的re-throw exception造成了堆栈异常庞杂(字节码层面的表现尤为让人惊讶,建议大家翻看ASM源码),尤其在异常抛出方面不讲究的话,很有可能造成信息混乱,建议大家研究一下Throwable的printStackTrace方法实现;

(3)  关于异常translate,我这里简单总结了一下,编码过程中一般会遇到两类,一类是 checked exception translate unchecked exception(实例代码如下),一类是error translate unchecked exception,使用template模式建立通用异常处理程式,简化异常处理,如有可能,可以使用AOP拦截集成点异常,让自己永远处于问题追踪的主动方(关于这一点,可以参考我的一篇博客中的ExceptionAspect部分,地址:http://blog.csdn.net/fengjia10/article/details/7341180).但需要注意的是,spring的AOP永远只会帮你拦截RuntimeException~

                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    result.cancel(true);//Future<Boolean> result = pool.submit(new Callable<Boolean>() {...});
                } catch (ExecutionException e) {
                    if (e.getCause() instanceof RuntimeException)
                        throw new RuntimeException(e);
                    else if (e.getCause() instanceof Error)
                        throw new Error(e.getCause());
                    else
                        throw new IllegalStateException("Not unchecked!", e.getCause());
                }

(4) 建立分级的异常监控,预警机制.(使用脚本语言,诸如perl,python等主动,被动兼施);

(5) 有技巧的"吞掉"异常.不按套路出牌的人,永远让人难以防备,关于这一点,可以研习一下jetty的continuation异步模型;

(6)  尝试使用Scala(或者Java7+的多重捕获),与Java不同,scala里全然是unchecked exception。另外通过模式匹配,异常处理逻辑,代码可读性也更好.如:

 def tryBreakable[T](op: =>T) = new TryBlock[T] {
    def catchBreak(onBreak: =>T) = try {
      op
    } catch {
      case ex: BreakControl =>
        if (ex ne breakException) throw ex
        onBreak
    }
  }

补充篇:

        最近设计OpenAPI的时候,由于要和前端进行交互,后端用的Webx3框架,部分

异常采用了其Pipeline处理,部分采用了编码映射处理。具体讲,就是错误码与状态码进行编排,前端按需所示(框架层面搂住5XX,4XX状态码,应用层面对其它码进行个性化展示。当然也可以采用位运算取而代之码编排)。示例代码如下:

/**
 * @author vongosling 2013-2-1
 * @see com.openapi.exception.ErrorCode
 */
public enum CommonErrorMapper {
    E_10000("10000", "500", "Unknown error"),
    E_10001("10001", "500", "System error"),
    E_10002("10002", "503", "Service unavailable "),
    E_10003("10003", "500", "Remote service error"),
    E_10004("10004", "400", "Illegal request"),
    E_10005("10005", "500", "Param error, see doc for more info"),
    E_10006("10006", "400", "Request records over limit "),
    E_10007("10007", "400", "IP limit "),
    E_10008("10008", "400", "Insufficient app permissions"),
    E_10009("10009", "404", "Request service not found "),
    E_10010("10010", "400", "IP requests out of rate limit"),
    E_10011("10011", "400", "User requests out of rate limit"),
    E_10012("10012", "400", "Access token does not exist "),
    E_10013("10013", "400", "Access token expired "),
    E_10015("10015", "400", "Request body length over limit ");

    private String httpStatus   = "";
    private String errorCode    = "";
    private String errorMessage = "";

    public String getHttpStatus() {
        return httpStatus;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    private CommonErrorMapper(String errorCode, String httpStatus, String errorMessage) {
        this.httpStatus = httpStatus;
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

然后在全局拦截点进行处理,实例代码如下:

     if (null != result.getErrors()) {
            CommonErrorMapper mapper = CommonErrorMapper.valueOf("E_"+ result.getErrors().get(0).getCode());//注意异常兼容,互斥等原则
            if (null != mapper) {
               response.setErrorCode(CommonErrorMapper.getErrorCode());
               response.setHttpStatus(CommonErrorMapper.getHttpStatus());
	       response.setContent(CommonErrorMapper.getErrorMessage());
	} else {
	       response.setErrorCode(CommonErrorMapper.E_10001.getErrorCode());
	       response.setHttpStatus(CommonErrorMapper.E_10001.getHttpStatus());
	       response.setContent(result.getErrors());
		}
	} else {
	       response.setHttpStatus("200");
	       response.setContent(result.getContent());
	       response.setMetadata( responseObject.getMetaData());
       }
       return response;
  }

前端返回RPC结果为:

  jcb1360050602232(
	{
		content: "Resubmit error.",
		errorCode: "10026",
		metadata: null,
		httpStatus: "500"
	})

剩下的就一目了然了吧~

下面给出一些比较有启发意义的异常处理文献:

1.http://tutorials.jenkov.com/java-exception-handling/index.html

2.http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

3. http://code.google.com/p/guava-libraries/wiki/ThrowablesExplained

时间: 2024-10-08 16:46:31

工业级应用中关于异常封装的一些感悟的相关文章

在ASP.NET 2.0中实现异常管理

介绍 在任何应用系统开发中,异常管理对开发人员来说都是一个关键领域.作为 一个开发人员,你应该采用一种合适的.能让你编写健壮且高质量代码的异常管 理策略.如果使用得当,异常管理将是一个很强大的概念而且使你的开发工作变 的很容易.然而,一个不合适的异常处理将会使你的应用系统性能降低. 在你钻研这些之前,要先搞清楚异常管理是什么,这点很重要.一般来说异 常就表示"打破系统预定的假设"."异常"和"错误"是不一样的,为了解释 清楚,我们来看两个例子:

Java中的异常和处理,你知道多少?

程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态. Java提供了更加优秀的解决办法:异常处理机制. 异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰. Java中的异常可以是函数中的语句执行时引发的,也可以是程序员通过throw 语句手动抛出的,只要在Java程序中

C#中如何处理异常

throw语句 在学习如何处理异常之前,我们先介绍一下throw语句. throw语句抛出一个异常: throw expression 带有表达式的throw语句抛出的异常是在计算这个表达式时产生的.这个表达式必须表示一个System.Exception类型或它的派生类型的值.如果对表达式的计算产生的结果是null,则抛出的将是一个NullReferenceException异常. 不带表达式的throw语句我们稍后再介绍. 异常处理语句 异常是由try语句来处理的. try语句提供了一种机制来

C++中的异常(exception)

1.简介 异常是由语言提供的运行时刻错误处理的一种方式.提到错误 处理,即使不提到异常,你大概也已经有了丰富的经验,但是为了可以清楚的看 到异常的好处,我们还是不妨来回顾一下常用的以及不常用的错误处理方式. 1.1 常用的错误处理方式 返回值.我们常用函数的返回值来标志成功或 者失败,甚至是失败的原因.但是这种做法最大的问题是如果调用者不主动检查 返回值也是可以被编译器接受的,你也奈何不了他:) 这在C++中还导致另外一个 问题,就是重载函数不能只有不同的返回值,而有相同的参数表,因为如果调用

JAVA中的异常与错误处理详解

  异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误: 它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务

使用Raygun来自动追踪AngularJS中的异常

这篇文章主要介绍了使用Raygun来自动追踪AngularJS中的异常,AngularJS是一款高人气的JavaScript库,需要的朋友可以参考下 Angular.js取得的巨大成就之一是实用的异常抛出,因为异常信息经常能够准确的表明你的代码为什么崩溃了.运行于世界各地的众多浏览器的大型客户端web应用会面临异常丢失的问题,而捕获它就有可能修复 bug并赢得用户. 当处理跨浏览器和设备的问题时,接收这些异常信息是很重要的,因为你的应用可能在你的开发机器上运行得正确可靠,但在你的用户的浏览器上却

浅谈Java中的异常

  作为一个面向对象编程的程序员对于 下面的一句一定非常熟悉: 复制代码 try { // 代码块 } catch(Exception e) { // 异常处理 } finally { // 清理工作 } 复制代码 就是面向对象中最最常见的异常处理程序,而且甚至我们会莫名其妙的被编译器要求加上这个模块,甚至我们自己也不知道捕捉到异常该怎么处理... 为什么要有异常 其实这个问题不用多说,程序员都知道,简单总结为一句话:就是为了增强程序健壮性呗,比如下面的代码: Class Denominator

VS2010连接数据库:已成功与服务器建立连接,但是在登录过程中发生异常

问题描述 VS2010连接数据库:已成功与服务器建立连接,但是在登录过程中发生异常 数据库确定没问题,服务器数据库其他人也可以连接正常使用,但是,我的VS2010连接的时候出现了这样的提示... 解决方案 看错误是超时 了,难道网络速度太慢了? 解决方案二: ssl握手错误,超时了 解决方案三: 先用你自己电脑连接对方sqlserver看有没有问题吧

802.11数据帧在framebody这个字段中是明文封装数据吗?

问题描述 802.11数据帧在framebody这个字段中是明文封装数据吗? 比如说我有一个""abc""要发送,封装到数据帧中framebody内是""01000001 01000010 01000011""吗?另外如果要发送的数据超出最大帧要求,拆分是不是简单地除法?比如说帧framebody最大要求是20字节,我有41个字节的数据要发,是分成20+20+1吗........... 我在网上搜了半天资料嘛也没找到T.T 解