package cn.mb.cloud.common.sentinel.fallback; import cn.mb.cloud.common.core.constant.enums.ErrorCodeConstants; import cn.mb.cloud.common.core.util.ResponseData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * 账户服务对公共 Sentinel Feign 降级处理的替代实现。 * *

依赖中的实现会将 {@link Method#getGenericReturnType()} 直接转换为 * {@link Class}。对于 {@code List} 等泛型 Feign 方法会转换失败; * 此处先解析原始类型,以便返回正确的空降级值。

*/ public class DefaultFeignFallback implements MethodInterceptor { private static final Logger log = LoggerFactory.getLogger(DefaultFeignFallback.class); private final Class targetType; private final String targetName; private final Throwable cause; public DefaultFeignFallback(Class targetType, String targetName, Throwable cause) { this.targetType = targetType; this.targetName = targetName; this.cause = cause; } @Override public Object intercept(Object object, Method method, Object[] arguments, MethodProxy methodProxy) { log.error("FunFeignFallback:[{}.{}] serviceId:[{}] message:[{}]", targetType.getName(), method.getName(), targetName, cause == null ? null : cause.getMessage()); Type declaredReturnType = method.getGenericReturnType(); Class returnType = rawType(declaredReturnType); if (ResponseData.class.equals(returnType)) { return ResponseData.builder() .code(ErrorCodeConstants.FAIL.getValue()) .msg("系统降级,请稍后再试!") .data(defaultValue(rawType(firstTypeArgument(declaredReturnType)))) .build(); } return defaultValue(returnType); } private Type firstTypeArgument(Type type) { if (type instanceof ParameterizedType) { Type[] arguments = ((ParameterizedType) type).getActualTypeArguments(); if (arguments.length > 0) return arguments[0]; } return null; } private Class rawType(Type type) { if (type instanceof Class) return (Class) type; if (type instanceof ParameterizedType) return rawType(((ParameterizedType) type).getRawType()); return Object.class; } private Object defaultValue(Class type) { if (List.class.isAssignableFrom(type)) return new ArrayList(); if (Set.class.isAssignableFrom(type)) return new HashSet(); if (Map.class.isAssignableFrom(type)) return new HashMap(); if (Boolean.class.equals(type) || boolean.class.equals(type)) return Boolean.FALSE; if (type.isPrimitive()) return primitiveDefault(type); return null; } private Object primitiveDefault(Class type) { if (char.class.equals(type)) return Character.valueOf('\0'); if (byte.class.equals(type)) return Byte.valueOf((byte) 0); if (short.class.equals(type)) return Short.valueOf((short) 0); if (int.class.equals(type)) return Integer.valueOf(0); if (long.class.equals(type)) return Long.valueOf(0L); if (float.class.equals(type)) return Float.valueOf(0F); if (double.class.equals(type)) return Double.valueOf(0D); return null; } }