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 降级处理的替代实现。
|
*
|
* <p>依赖中的实现会将 {@link Method#getGenericReturnType()} 直接转换为
|
* {@link Class}。对于 {@code List<IntegralCommodity>} 等泛型 Feign 方法会转换失败;
|
* 此处先解析原始类型,以便返回正确的空降级值。</p>
|
*/
|
public class DefaultFeignFallback<T> implements MethodInterceptor {
|
private static final Logger log = LoggerFactory.getLogger(DefaultFeignFallback.class);
|
|
private final Class<T> targetType;
|
private final String targetName;
|
private final Throwable cause;
|
|
public DefaultFeignFallback(Class<T> 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<Object>();
|
if (Set.class.isAssignableFrom(type)) return new HashSet<Object>();
|
if (Map.class.isAssignableFrom(type)) return new HashMap<Object, Object>();
|
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;
|
}
|
}
|