package com.ycl.config.feign; import com.ycl.utils.StringUtils; import feign.Param; import feign.QueryMapEncoder; import feign.codec.EncodeException; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; public class UnderlineQueryEncoder implements QueryMapEncoder { private final Map, ObjectParamMetadata> classToMetadata = new HashMap(); @Override public Map encode(Object object) throws EncodeException { try { ObjectParamMetadata metadata = getMetadata(object.getClass()); Map propertyNameToValue = new HashMap(); for (PropertyDescriptor pd : metadata.objectProperties) { Method method = pd.getReadMethod(); Object value = method.invoke(object); if (value != null && value != object) { Param alias = method.getAnnotation(Param.class); String name = alias != null ? alias.value() : pd.getName(); propertyNameToValue.put(StringUtils.camelToUnderlineLowerCase(name), value); } } return propertyNameToValue; } catch (IllegalAccessException | IntrospectionException | InvocationTargetException e) { throw new EncodeException("Failure encoding object into query map", e); } } private ObjectParamMetadata getMetadata(Class objectType) throws IntrospectionException { ObjectParamMetadata metadata = classToMetadata.get(objectType); if (metadata == null) { metadata = ObjectParamMetadata.parseObjectType(objectType); classToMetadata.put(objectType, metadata); } return metadata; } private static class ObjectParamMetadata { private final List objectProperties; private ObjectParamMetadata(List objectProperties) { this.objectProperties = Collections.unmodifiableList(objectProperties); } private static ObjectParamMetadata parseObjectType(Class type) throws IntrospectionException { List properties = new ArrayList(); for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) { boolean isGetterMethod = pd.getReadMethod() != null && !"class".equals(pd.getName()); if (isGetterMethod) { properties.add(pd); } } return new ObjectParamMetadata(properties); } } }