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

简介:         Java的异常体系想必大家都熟记于心的,那么在日常的编码过程中,大家又是如何实施的呢?针对checked和unchecked exception大家的理解又有多少呢?         几乎所有的书本上都给出了一个conclusion,如果日常事务能从异常中恢复,那么建议用checked exception,如果不能recover from,那么就是unchecked的

        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

目录
相关文章
|
4天前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
13天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
8天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
541 206
|
3天前
|
编解码 Linux 数据安全/隐私保护
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
220 138
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
736 52
|
5天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
932 157
下一篇
oss云网关配置