apache dubbo 自定义全局统一的异常处理器
生活随笔
收集整理的這篇文章主要介紹了
apache dubbo 自定义全局统一的异常处理器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
項目使用過的是apache dubbo 2.7.1, 封裝了自定義全局統一的異常處理器。
統一異常處理器
需要實現javax.ws.rs.ext.ExceptionMapper接口。
import org.apache.dubbo.rpc.RpcException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jboss.resteasy.spi.DefaultOptionsMethodException; import org.springframework.util.StringUtils;import javax.exceptions.ServiceException; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.List;/*** 全局統一的異常處理器。*/ public class CustomExceptionMapper implements ExceptionMapper<Exception> {private final static Logger logger = LogManager.getLogger(CustomExceptionMapper.class);private static final String TEXT_PLAIN_UTF_8 = "text/plain; charset=UTF-8";private static final String JSON_UTF_8 = "application/json;charset=UTF-8";private static final int FILTER_SIZE = 60;private static final String DEV = "dev";private static final String TEST = "test";private static final int UNAUTHORIZED = 401;public static String active;public static void setActive(String at) {active = at;}@Overridepublic Response toResponse(Exception e) {if (e instanceof DefaultOptionsMethodException ||(StringUtils.hasText(e.getMessage()) && e.getMessage().contains("org.jboss.resteasy.spi.DefaultOptionsMethodException"))) {// 忽略此異常: Option跨域請求探測return Response.status(Response.Status.OK).type(TEXT_PLAIN_UTF_8).build();}Response.Status httpStatus = Response.Status.INTERNAL_SERVER_ERROR;Result<String> errorResult = null;List<String> messages = new ArrayList<>();if (e.getStackTrace().length > 0) {StackTraceElement ste = e.getStackTrace()[0];messages.add("異常內容:" + e.getMessage());messages.add("異常名:" + e.getClass());messages.add("異常類名:" + ste.getClassName());messages.add("異常文件名:" + ste.getFileName());messages.add("異常行號:" + ste.getLineNumber());messages.add("異常方法:" + ste.getMethodName());}//1.處理404異常if (e instanceof NotFoundException) {logger.error("發生404異常: ", e);errorResult = fail(404, "404 not found!");httpStatus = Response.Status.NOT_FOUND;}//2.dubbo遠程調用異常if (e instanceof RpcException) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), "服務重新連線中,請稍后", messages);httpStatus = Response.Status.UNAUTHORIZED;}//3.非法參數異常if (e instanceof IllegalArgumentException) {if (!StringUtils.isEmpty(e.getMessage())) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), filterChinese(e.getMessage()), messages);} else {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), filterChinese("內部錯誤:A04"), messages);}}//4.對象解析異常if (e instanceof IllegalStateException) {if (StringUtils.isEmpty(e.getMessage())) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), filterChinese("內部錯誤:A03"), messages);} else {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), filterChinese(e.getMessage()), messages);}}//5.強制轉換異常if (e instanceof ClassCastException) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), "內部錯誤:A01", messages);}//6.空指針if (e instanceof NullPointerException) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), "內部錯誤:A02", messages);}//7.處理自定義異常if (e instanceof AlertException) {errorResult = fail(((AlertException) e).getErrorCode(), e.getMessage(), messages);logger.error("提示信息:{}", e.getMessage());} else if (e instanceof AlertAndReloadException) {errorResult = fail(((AlertAndReloadException) e).getErrorCode(), e.getMessage(), messages);logger.error("提示信息:{}", e.getMessage());} else if (e instanceof ServiceException) {ServiceException serviceException = (ServiceException) e;//統一異常碼Integer errorCode = serviceException.getErrorCode();String errorInfo = serviceException.getErrorInfo();if ((!StringUtils.isEmpty(errorCode)) && errorCode == UNAUTHORIZED) {httpStatus = Response.Status.UNAUTHORIZED;}if (StringUtils.isEmpty(errorCode)) {errorCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();}if (httpStatus == Response.Status.UNAUTHORIZED) {logger.debug("發生自定義異常,異常碼:{}, 異常說明:{}", errorCode, errorInfo);} else {logger.error("發生自定義異常,異常碼:{}, 異常說明:{}", errorCode, errorInfo, e);}//錯誤提示信息String reason = StringUtils.hasText(errorInfo) ? errorInfo : ErrorCodeEnums.getByCode(errorCode);errorResult = fail(errorCode, StringUtils.hasText(reason) ? reason : errorInfo, messages);}//8.其他異常if (errorResult == null) {logger.error("發生異常: ", e);String msg = e.getMessage();if (StringUtils.isEmpty(msg) || msg.length() > FILTER_SIZE) {msg = "服務器開小差了,請重試";}if (!StringUtils.isEmpty(active) && (active.equals(DEV) || active.equals(TEST))) {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), msg, getExceptionDetail(e), messages);} else {errorResult = fail(ErrorCodeEnums.InternalServerError.getCode(), msg, messages);}}return Response.status(httpStatus).entity(errorResult.toString()).type(JSON_UTF_8).build();}private Result<String> fail(int code, String msg) {return new Result<>(code, msg);}private Result<String> fail(int code, String msg, List<String> messages) {return new Result<>(code, msg, null, messages);}private Result<String> fail(int code, String msg, String errMessage) {return new Result<>(code, msg, errMessage);}private Result<String> fail(int code, String msg, String errMessage, List<String> messages) {return new Result<>(code, msg, errMessage, messages);}/*** 過濾掉 非中文字符。*/private static String filterChinese(final String str) {if (!StringUtils.hasText(str)) {return str;}if (str.length() <= FILTER_SIZE) {return str;}//只保留前60個中文字符String filterStr = str.replaceAll("[^(\\u4e00-\\u9fa5)]", "").replaceAll("\\(", "").replaceAll("\\)", "").replaceAll("\\.", "").replaceAll("\\_", "");if (StringUtils.isEmpty(filterStr)) {//過濾后為空,則原樣顯示前60個字符return str.substring(0, FILTER_SIZE);} else if (filterStr.length() > FILTER_SIZE) {return filterStr.substring(0, FILTER_SIZE);} else if (filterStr.length() < 15) {return str;} else {return filterStr;}}/*** 獲取異常詳細信息*/public static String getExceptionDetail(Exception ex) {String ret = null;try {ByteArrayOutputStream out = new ByteArrayOutputStream();PrintStream pout = new PrintStream(out);ex.printStackTrace(pout);ret = new String(out.toByteArray());pout.close();out.close();} catch (Exception e) {}return ret;}}統一異常碼枚舉類 ErrorCodeEnums.java:
/*** 全局統一的異常碼。*/ public enum ErrorCodeEnums {// ----------------- http標準狀態碼---------------------------------Unauthorized(401, "請先登錄"),Forbidden(403, "您無權限訪問此頁面,請聯系管理員或重新登錄"),NotFound(404, "抱歉,您訪問的頁面不存在"),InternalServerError(500, "服務器內部錯誤"),//----------------- 自定義異常碼 -----------------------------------ServerErrorRetry(666, "服務器內部錯誤,前端頁面嘗試再次調用接口直到返回666"),ParamsError(1001, "參數校驗失敗"),TokenExpired(1002, "登錄token已過期"),AlertMsg(1003, "頁面提示信息"),AlertMsgAndReload(1004, "提示信息,并自動刷新頁面"),;/*** 異常碼。*/public Integer code;/*** 異常描述。*/public String reason;ErrorCodeEnums(Integer code, String reason) {this.code = code;this.reason = reason;}public static String getByCode(Integer code) {for (ErrorCodeEnums item : ErrorCodeEnums.values()) {if (code.equals(item.getCode())) {return item.reason;}}return "";}public Integer getCode() {return code;}public String getReason() {return reason;} }application.yml文件配置
在application.yml文件中配置啟用
dubbo:application:name: xxx-service# 優雅停機超時時間shutwait: 15000provider:#負載均衡loadbalance: roundrobintimeout: 10000filter: xxxFilterconsumer: #關閉啟動時檢查依賴服務check: falsefilter: xxxFilterprotocols:dubbo:name: dubboport: -1server: nettyextension: xxx.CustomExceptionMapperrest:name: restport: 80server: tomcatcontextpath: xxx-serviceextension: xxx.CustomExceptionMapper總結
以上是生活随笔為你收集整理的apache dubbo 自定义全局统一的异常处理器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对账模块和赊购退款、还款流程
- 下一篇: 微服务架构方案 springBoot+d