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