以下是基于Spring Boot的异常处理机制封装,定义标准的异常码、统一的异常类、链路追踪TraceId、请求服务链AppName,统一处理接口请求异常信息、Feign Client、Dubbo请求异常处理的代码示例:
- 定义异常类和异常码
public class ApiException extends RuntimeException {
private int code;
private String traceId;
private String appName;
public ApiException(int code, String message, String traceId, String appName) {
super(message);
this.code = code;
this.traceId = traceId;
this.appName = appName;
}
public int getCode() {
return code;
}
public String getTraceId() {
return traceId;
}
public String getAppName() {
return appName;
}
}
public class ApiErrorCode {
public static final int UNKNOWN_ERROR = 10000;
public static final int PARAMETER_ERROR = 10001;
public static final int BUSINESS_ERROR = 10002;
public static final int AUTH_ERROR = 10003;
public static final int REMOTE_ERROR = 10004;
}
- 统一异常处理
@ControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(ApiException.class)
@ResponseBody
public Result handleApiException(ApiException e) {
return Result.error(e.getCode(), e.getMessage(), e.getTraceId(), e.getAppName());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handleException(Exception e) {
String traceId = MDC.get("traceId");
String appName = MDC.get("appName");
// appName -> chain + '->' + appName,在服务调用链中每个服务都处理将当前appName拼接形成服务链
return Result.error(ApiErrorCode.UNKNOWN_ERROR, e.getMessage(), traceId, appName);
}
}
- Feign Client异常处理
public class FeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
try {
String body = Util.toString(response.body().asReader());
JSONObject json = JSON.parseObject(body);
String message = json.getString("message");
int code = json.getIntValue("code");
String traceId = response.headers().get("traceId").iterator().next();
String appName = response.headers().get("appName").iterator().next();
return new ApiException(code, message, traceId, appName);
} catch (IOException e) {
return new ApiException(ApiErrorCode.REMOTE_ERROR, "远程调用异常", "", "");
}
}
}
- Dubbo异常处理
public class DubboExceptionFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
RpcContext rpcContext = RpcContext.getContext();
Result result = invoker.invoke(invocation);
if (result.hasException()) {
Throwable exception = result.getException();
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
apiException.setTraceId(rpcContext.getAttachment("traceId"));
apiException.setAppName(rpcContext.getAttachment("appName"));
return Result.error(apiException.getCode(), apiException.getMessage(), apiException.getTraceId(), apiException.getAppName());
} else {
return Result.error(ApiErrorCode.REMOTE_ERROR, "远程调用异常", rpcContext.getAttachment("traceId"), rpcContext.getAttachment("appName"));
}
} else {
return result;
}
} catch (RpcException e) {
return Result.error(ApiErrorCode.REMOTE_ERROR, "远程调用异常", RpcContext.getContext().getAttachment("traceId"), RpcContext.getContext().getAttachment("appName"));
}
}
}
以上是基于Spring Boot的异常处理机制封装,定义标准的异常码、统一的异常类、链路追踪TraceId、请求服务链AppName,统一处理接口请求异常信息、Feign Client、Dubbo请求异常处理的代码示例。