springboot使用feign
pom.xml
<!--feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>10.2.3</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-openfeign-core</artifactId> <version>2.2.6.RELEASE</version> </dependency>
feign自定义编码器
package com.jw.demo.jw_demo.config.feign; import feign.Param; import feign.QueryMapEncoder; import feign.codec.EncodeException; import org.springframework.format.annotation.DateTimeFormat; import java.lang.reflect.Field; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** * @ClassName PowerfulQueryMapEncoder * @Description feign自定义编码器 * @Author yangjingwei * @Date 2022/3/29 10:07 * @Version 1.0 **/ public class PowerfulQueryMapEncoder implements QueryMapEncoder { private final Map<Class<?>, ObjectParamMetadata> classToMetadata = new ConcurrentHashMap<>(); @Override public Map<String, Object> encode(Object object) { ObjectParamMetadata metadata = classToMetadata.computeIfAbsent(object.getClass(), ObjectParamMetadata::parseObjectType); return metadata.objectFields.stream() .map(field -> this.FieldValuePair(object, field)) .filter(fieldObjectPair -> fieldObjectPair.right.isPresent()) .collect(Collectors.toMap(this::fieldName, this::fieldObject)); } private String fieldName(Pair<Field, Optional<Object>> pair) { Param alias = pair.left.getAnnotation(Param.class); return alias != null ? alias.value() : pair.left.getName(); } // 可扩展为策略模式,支持更多的格式转换 private Object fieldObject(Pair<Field, Optional<Object>> pair) { Object fieldObject = pair.right.get(); DateTimeFormat dateTimeFormat = pair.left.getAnnotation(DateTimeFormat.class); if (dateTimeFormat != null) { DateFormat format = new SimpleDateFormat(dateTimeFormat.pattern()); format.setTimeZone(TimeZone.getTimeZone("GMT+8")); // TODO: 最好不要写死时区 fieldObject = format.format(fieldObject); } else { } return fieldObject; } private Pair<Field, Optional<Object>> FieldValuePair(Object object, Field field) { try { return Pair.pair(field, Optional.ofNullable(field.get(object))); } catch (IllegalAccessException e) { throw new EncodeException("Failure encoding object into query map", e); } } private static class ObjectParamMetadata { private final List<Field> objectFields; private ObjectParamMetadata(List<Field> objectFields) { this.objectFields = Collections.unmodifiableList(objectFields); } private static ObjectParamMetadata parseObjectType(Class<?> type) { List<Field> allFields = new ArrayList<Field>(); for (Class<?> currentClass = type; currentClass != null; currentClass = currentClass.getSuperclass()) { Collections.addAll(allFields, currentClass.getDeclaredFields()); } return new ObjectParamMetadata(allFields.stream() .filter(field -> !field.isSynthetic()) .peek(field -> field.setAccessible(true)) .collect(Collectors.toList())); } } private static class Pair<T, U> { private Pair(T left, U right) { this.right = right; this.left = left; } public final T left; public final U right; public static <T, U> Pair<T, U> pair(T left, U right) { return new Pair<>(left, right); } } }
编码器注册
package com.jw.demo.jw_demo.config.feign; import feign.Feign; import feign.Retryer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName FeignConfig * @Description 编码器注册 * @Author yangjingwei * @Date 2022/3/29 10:18 * @Version 1.0 **/ @Configuration public class FeignConfig { @Bean public Feign.Builder feignBuilder() { return Feign.builder() .queryMapEncoder(new PowerfulQueryMapEncoder()) .retryer(Retryer.NEVER_RETRY); } }
启动类增加注解
@EnableFeignClients
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通