|
@@ -0,0 +1,85 @@
|
|
|
|
|
+package com.sckw.remote.filter;
|
|
|
|
|
+
|
|
|
|
|
+import org.apache.dubbo.common.constants.CommonConstants;
|
|
|
|
|
+import org.apache.dubbo.common.extension.Activate;
|
|
|
|
|
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
|
|
|
|
+import org.apache.dubbo.common.logger.LoggerFactory;
|
|
|
|
|
+import org.apache.dubbo.common.utils.StringUtils;
|
|
|
|
|
+import org.apache.dubbo.rpc.*;
|
|
|
|
|
+import org.apache.dubbo.rpc.service.GenericService;
|
|
|
|
|
+
|
|
|
|
|
+import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_FILTER_VALIDATION_EXCEPTION;
|
|
|
|
|
+
|
|
|
|
|
+@Activate(group = CommonConstants.CONSUMER)
|
|
|
|
|
+public class DubboConsumerExceptionFilter implements Filter, Filter.Listener {
|
|
|
|
|
+ private ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DubboConsumerExceptionFilter.class);
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
|
|
|
|
+ return invoker.invoke(invocation);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
|
|
|
|
+ if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Throwable exception = appResponse.getException();
|
|
|
|
|
+
|
|
|
|
|
+ // 直接抛出RuntimeException,避免将底层异常信息暴露给调用方
|
|
|
|
|
+ String className = exception.getClass().getName();
|
|
|
|
|
+ if (className.startsWith("java.") || className.startsWith("javax.")) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 自定义异常处理
|
|
|
|
|
+ if (className.startsWith("com.sckw.core.exception")) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Dubbo异常处理
|
|
|
|
|
+ if (exception instanceof RpcException) {
|
|
|
|
|
+ // 记录RpcException日志,但不暴露给前端
|
|
|
|
|
+ logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "",
|
|
|
|
|
+ "Dubbo RpcException. service: " + invoker.getInterface().getName() +
|
|
|
|
|
+ ", method: " + invocation.getMethodName() +
|
|
|
|
|
+ ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(),
|
|
|
|
|
+ exception);
|
|
|
|
|
+
|
|
|
|
|
+ // 包装为通用异常信息返回给客户端
|
|
|
|
|
+ appResponse.setException(new RuntimeException("服务暂时不可用,请稍后重试"));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 记录异常日志
|
|
|
|
|
+ logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "",
|
|
|
|
|
+ "Dubbo consumer caught exception. service: " + invoker.getInterface().getName() +
|
|
|
|
|
+ ", method: " + invocation.getMethodName() +
|
|
|
|
|
+ ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(),
|
|
|
|
|
+ exception);
|
|
|
|
|
+
|
|
|
|
|
+ // 包装为RuntimeException并返回给客户端
|
|
|
|
|
+ appResponse.setException(new RuntimeException("服务调用异常,请稍后重试"));
|
|
|
|
|
+ } catch (Throwable e) {
|
|
|
|
|
+ logger.warn(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "",
|
|
|
|
|
+ "Fail to ExceptionFilter when called by " + RpcContext.getServiceContext().getRemoteHost() +
|
|
|
|
|
+ ". service: " + invoker.getInterface().getName() +
|
|
|
|
|
+ ", method: " + invocation.getMethodName() +
|
|
|
|
|
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void onError(Throwable e, Invoker<?> invoker, Invocation invocation) {
|
|
|
|
|
+ logger.error(CONFIG_FILTER_VALIDATION_EXCEPTION, "", "",
|
|
|
|
|
+ "Got unchecked and undeclared exception which called by " + RpcContext.getServiceContext().getRemoteHost() +
|
|
|
|
|
+ ". service: " + invoker.getInterface().getName() +
|
|
|
|
|
+ ", method: " + invocation.getMethodName() +
|
|
|
|
|
+ ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // For test purpose
|
|
|
|
|
+ public void setLogger(ErrorTypeAwareLogger logger) {
|
|
|
|
|
+ this.logger = logger;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|