在代碼中使用自定義的異常類,可以對異常進行統一的封裝處理。使得整個項目的異常處理更規范、更統一、更優雅。同時,使得日志的記錄上更加清晰,便於后續查日志定位問題。
以下為自定義異常類的完整過程:
1、需要自定義一個類,繼承自系統的異常類。具體需要什么樣類型的異常類,就繼承自相應的系統類。
- 如果希望寫一個檢查性異常類,則需要繼承 Exception 類。
如果你想寫一個運行時異常類,那么需要繼承 RuntimeException 類。
public class InvalidReqException extends Exception { private final String userErrMsg; private final ErrorCode errorCode; public InvalidReqException(ErrorCode errorCode, String sysErrMsg, String userErrMsg) { super(sysErrMsg); this.userErrMsg = userErrMsg; this.errorCode = errorCode; } public InvalidReqException(ErrorCode errorCode, String sysErrMsg, String userErrMsg, Throwable cause) { super(sysErrMsg, cause); this.userErrMsg = userErrMsg; this.errorCode = errorCode; } public InvalidReqException(ErrorCode errorCode, String sysErrMsg) { super(sysErrMsg); this.userErrMsg = null; this.errorCode = errorCode; } public ErrorCode getErrorCode() { return errorCode; } public String getUserErrMsg() { return userErrMsg; } public String getSysErrMsg() { return getMessage(); } }
2、在需要拋出該異常的類或方法中,定義當出現異常時拋出自定義的異常。
static void checkTemplateValid(String content) throws InvalidReqException { if (content.length() > 100 * 1024) { throw new InvalidReqException(ErrorCode.TEMPLATE_INVALID, "template is too large, over 100KB", "模板HTML原文不得超過100KB"); } }
3、在使用到該類或方法的地方捕捉該異常(或繼續拋出,交給上級去處理),並對異常進行業務相關的響應與處理。
public void onMessage(Message message) { String tenantId = (String) message.getMessageProperties().getHeaders().get(MQRouting.HEADER_TENANT_ID); String requestId = (String) message.getMessageProperties().getHeaders().get(MQRouting.HEADER_REQ_ID); String body = null; CertApplyMsg msg; try { body = new String(message.getBody(), "utf8"); log.debug("received cert apply message: {}", body); msg = JsonUtil.parse(body, CertApplyMsg.class); } catch (IOException e) { // impossible to happen log.error("message failed due to invalid format:" + body, e); failMsg(MQRouting.EXCH_CERT, MQRouting.RK_CERT_APPLY_FAILED, message, e); return; } LegalEntityCertBo entity = msg.getLegalEntityCert(); try { if (entity.getCert().getStatus() != CertStatus.APPLYING) { reconcileConcurrentUpdate(tenantId, requestId, msg); // due to retry return; } LegalEntityCertBo created = certService.applyCert(entity.getOrganization(), entity.getCert().getCa(), entity.getLegalEntity()); if (!certService.updateCert(created, entity.getCert().getStatus())) { // due to data race reconcileConcurrentUpdate(tenantId, requestId, msg); } else { enqueueCallback(tenantId, requestId, msg, created, null, null); log.info("successfully processed cert application:" + body); } } catch (InvalidReqException e) { log.error("applying cert rejected. body=" + body + ", message=" + message, e); enqueueCallback(tenantId, requestId, msg, entity, e.getErrorCode(), e.getSysErrMsg()); rejectMsg(MQRouting.EXCH_CERT, MQRouting.RK_CERT_APPLY_REJECTED, message, e); } catch (RuntimeException e) { log.error("cert application failed, probably will retry, body=" + body + ", msg=" + e.getMessage(), e); throw e; } }