工業級應用中關於異常封裝的一些感悟
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,自己去實地感知一下,就全了然了;
} 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.https://tutorials.jenkov.com/java-exception-handling/index.html
2.https://onjava.com/pub/a/onjava/2003/11/19/exceptions.html
3. https://code.google.com/p/guava-libraries/wiki/ThrowablesExplained
最後更新:2017-04-02 06:52:05