Spring cloud Feign不支持对象传参解决办法[完美解决]
spring cloud 使用 Feign 进行服务调用时,不支持对象参数。
通常解决方法是,要么把对象每一个参数平行展开,并使用 @RequestParam 标识出每一个参数,要么用 @RequestBody 将请求改为 body 传参,虽然这样解决了问题,但是这样限制了传参方式,并且使代码变得很繁重。
以下为完美解决 Feign 对象传参问题的办法。
1. 引入如下依赖(可以在maven仓库中搜索 strongfeign)
<dependency> <groupId>com.moonciki.strongfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>10.2.3</version> </dependency>
该源码修改自 https://github.com/OpenFeign/feign,提交过pr,但是项目原作者并没有采纳,pr地址如下:https://github.com/OpenFeign/feign/pull/949
之后为了同步到了maven 仓库,做了相应删减及pom的变更,具体改动可参考github。地址:https://github.com/cdmamata/strong-feign
注意:不要使用 10.3.x版本,该版本有问题。如果jar包无法下载请使用 maven 中央仓库。
2. 创建如下三个类
开始时,打算把以下三个类加进仓库中,但由于如下三个类内容不多,并且有很多定制化的可能,因此单独实现。
2.1 ParamModel.java
package com.moonciki.strongfeign.model.annotation; import java.lang.annotation.*; @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ParamModel { String value() default ""; }
2.2 ModelExpander.java
package com.moonciki.strongfeign.model.expander; import com.alibaba.fastjson.JSON; import feign.Param; import lombok.extern.slf4j.Slf4j; import java.util.Map; @Slf4j public class ModelExpander implements Param.Expander { public String expand(Object value) { String objectJson = JSON.toJSONString(value); return objectJson; } @Override public String expandWithName(Object value, String name) { String valueExpand = null; if(value != null){ if(name != null) { try { Map<String, Object> jsonMap = (Map<String, Object>)JSON.toJSON(value); Object getValue = jsonMap.get(name); if(getValue != null){ valueExpand = getValue.toString(); } } catch (Exception e) { log.error("GET VALUE ERROR:", e); } }else { valueExpand = value.toString(); } } return valueExpand; } }
注:该类需依赖 fastjson,也可根据个人需要修改该方法。
2.3 ParamModelParameterProcessor.java
package com.moonciki.strongfeign.model.processor; import com.moonciki.strongfeign.model.annotation.ParamModel; import com.moonciki.strongfeign.model.expander.ModelExpander; import feign.MethodMetadata; import org.springframework.cloud.openfeign.AnnotatedParameterProcessor; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; public class ParamModelParameterProcessor implements AnnotatedParameterProcessor { private static final Class<ParamModel> ANNOTATION = ParamModel.class; public Class<? extends Annotation> getAnnotationType() { return ANNOTATION; } @Override public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) { int parameterIndex = context.getParameterIndex(); Class parameterType = method.getParameterTypes()[parameterIndex]; MethodMetadata data = context.getMethodMetadata(); Field[] fields = parameterType.getDeclaredFields(); for(Field field: fields) { String name = field.getName(); context.setParameterName(name); Collection query = context.setTemplateParameter(name, (Collection)data.template().queries().get(name)); data.template().query(name, query); } data.indexToExpander().put(context.getParameterIndex(), new ModelExpander()); return true; } }
3. 使用注解配置 feign Contract 对象
@Bean public Contract feignContract(){ List<AnnotatedParameterProcessor> processors = new ArrayList<>(); processors.add(new ParamModelParameterProcessor()); processors.add(new PathVariableParameterProcessor()); processors.add(new RequestHeaderParameterProcessor()); processors.add(new RequestParamParameterProcessor()); return new SpringMvcContract(processors); }
4. 使用方法示例
@Primary @FeignClient(value = "/user", fallback = UserClientFallback.class) public interface UserClient { /** * demo post * @return */ @PostMapping("/demoPost") Result demoPost(@ParamModel UserAccount userAccount); /** * demo get * @return */ @GetMapping("/demoGet") Result demoPost(@ParamModel UserAccount userAccount); }
使用时,只需要在对象前加 @ParamModel 注解即可
需要同时传递对象及基本类型参数时, @ParamModel 可以与 @RequestParam("jobName") 同时使用在不同参数上。
- spring cloud feign 常见问题解决办法
- Spring Cloud Feign 第一次调用超时(Read timed out)的解决办法
- SpringCloud中Feign调Token丢失解决办法
- spring cloud feign不支持@RequestBody+ RequestMethod.GET报错的解决方法
- SpringCloud中Feign调Token丢失解决办法
- jmail组件 对象不支持此属性或方法: 'JMail.ServerAddress' 的解决办法
- spring cloud feign不支持@RequestBody+ RequestMethod.GET,报错
- spring cloud 学习(9) - turbine stream无法在eureka注册的解决办法
- 关于使用jquery时,ie8下提示对象不支持的属性或方法的解决办法
- 关于spring-cloud 的提供者服务启动报错解决办法。
- 解决document.form1.submit()对象不支持此属性或方法的办法
- 解决document.form1.submit()对象不支持此属性或方法的办法
- Spring JPA Save()对象后返回该对象ID为0解决办法
- SpringCloud之Ribbon和Feign断路器支持(Hystrix)|第四章-yellowcong
- springcloud-feign的hystrix支持
- spring容器创建对象时抛错解决办法
- spring cloud feign调其他微服务时参数是对象
- SpringCloud上传文件,经过Zuul,中文文件名乱码解决办法
- Spring cloud多模块开发下Feign的使用,以及@FeignClient注入bean找不到异常解决
- SpringCloud Feign对Hystrix(断路由)的支持