java web 异常实践

异常实践

前言

本文是我在项目中设计和处理异常的一些实践,主要是围绕着常见的web项目,欢迎大家指正。

本文分为两个个部分

  1. 异常设计
  2. 异常处理

异常设计

通常考虑异常设计时大致分为三个部分

  1. 接口层
  2. 业务层
  3. 类库

接口层就是我们通常说的 controller 层,以及提供 rpc 服务的接口层。

业务层就是主要的业务代码模块,主要是 service 层。

类库主要是指一些公共模块,可以在各个项目中使用的,比如 json,分布式锁等。

业务层

在业务层,我们主要是要设计业务异常。什么是业务异常?业务异常就是我们能够人为的判断出业务逻辑走到某一个位置是不对的。比如,我们要根据一个 uid 来修改一个 user 的 name,但我们发现并没有这个 uid 对应的 user 数据,这时候就应该抛出一个业务异常。在发生业务异常时,要避免抛出 npe,RuntimeException 等其他内置异常,以方便上层来分辨到底是业务错误还是程序 bug。

我一般会设计一个业务异常的基类 ServiceException,将所有业务异常以这种类型来抛出,并带有必要的 message。

为了把用户可读的消息和开发人员可读的消息区别开,ServiceException 还需要实现一个接口 UserMessage,并实现其中方法 getUserMessage()来返回用户可读的信息,而 getMessage() 可以携带更详细的开发人员可读的错误信息

设计一个 ServiceErrorException,继承 ServiceExceptionServiceErrorException 的主要目的是为了表明这个异常的错误程度高,需要记录 error。

以上就定型了业务异常的基本结构,上面一些特殊设计会在异常处理中用到,我们后面来说,再做前后对照。我们可以根据需要来实现若干子类来表示业务层中不同模块的错误。

接口层

对于接口层,特别是rpc调用,比如我们的dubbo调用,需要把api的jar包放在调用方。我们需要把异常类给包括进去,但调用方不能也不应该拿到我们业务层的 ServiceException,所以需要在接口层定义新的业务异常类型,比如,就叫ApiServiceException,放在api的jar包里给调用方。

接口实现需要把业务层的ServiceException给catch到,重新封装为ApiServiceException抛出。

这样,调用方在判断调用时发生的异常时,有三种可能:

  1. rpc框架异常。比如又dubbo框架抛出的异常,这一版两种可能:1. 网络异常,我们需要重试;2. 调用未能达成,这种一般是接口没有匹配上,在开发测试时都可以发现的错误,改掉即可。所以,当发生rpc框架异常时,调用方的策略就应该是重试。
  2. ApiServiceException。这表示被调用方出现了业务异常,调用方也需要作为业务异常来处理。
  3. 其他异常。这表示被调用方的程序有bug报出了异常透传给了调用方,这是调用方应及时联系接口实现方来修补bug。

以上,就能够分类准确应对rpc过程中的异常情况。

http方式的接口层也可以这么做,不过由于api并不对外,所以也可以完全由自身来处理异常类型,详见异常处理部分。

类库

作为类库,因为通常没有业务意义,所以在发生逻辑上的异常时,根本不可能知道需要怎么处理,这就需要直接向上抛出,到交给业务层处理。

类库需要将自身的逻辑上的异常,同一封装。比如,处理 Json 的类库,异常最终抛出时,都被封装成为JsonParseExceptionJsonSerializeExcption

这样调用方使用类库时,异常会有两种:

  1. 类库封装的自定义异常。这种是调用时出现的逻辑错误,调用方以业务异常来处理。
  2. 其他异常。可以认为是类库bug。

异常处理

有了以上的异常设计,那么处理时就可以按照以下流程。

以 http 请求的 ExceptionHandler 为例,所有 http 请求异常都会放在这里处理,过程:

  1. ex 异常传入。
  2. 装饰 ex 异常,ex = new WebApiException(...,ex),其包含有 messageisLogError 属性
    1. 如果 ex 是非 ServiceException,那么message = “系统内部错误”isLogError = true
    2. 如果 ex 是 ServiceException,那么message = ex.getUserMessage();更进一步,如果是 ServiceErrorException,那么isLogError = true,否则 isLogError = false
  3. 如果 ex.isLogError == true,记录 error log,否则,记录 warn log。
  4. 判断 http 请求是页面请求,还是ajax请求。
    1. 如果是页面请求。500转错误页,显示 ex.getMessage(),如果是debug环境或者是请求带有debug参数,也把错误堆栈输出在页面上。
    2. 如果是 ajax 请求。返回表示错误的 json 消息,同样,如果是debug环境或者是请求带有debug参数,消息中带上堆栈信息。

以上,就是一个简单而有效的异常处理机制。

最后

以上是我的个人实践经验总结,请各位批评指正,欢迎讨论。

欢迎加入群 661035226,gradle,spring,activiti 交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,567评论 18 399
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,416评论 25 707
  • 来源与:阿里云栖 禁止用于商业用途 ps:如果需要电子书 评论你们邮箱 我会发给你们 下面感觉还是有点乱 目录 一...
    小向资源网阅读 7,570评论 0 12
  • 这是颓废的一周,也是回家的一周 做的事情 1.回家 2.《算法数据结构javascript》完成75%,当然感觉最...
    酱油_阅读 173评论 0 0
  • 启动页不显示,LaunchImage不起作用如果项目中原来使用了LaunchScreen.xib,现在改为xcss...
    囧书阅读 630评论 0 0