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的文件上传实现
在Spring Cloud封装的Feign中并不直接支持传文件,但可以通过引入Feign的扩展包来实现,本来就来具体说说如何实现. 原文:http://blog.didispace.com/sprin ...
- spring cloud feign不支持@RequestBody+ RequestMethod.GET,报错
1.问题梳理: 异常:org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not ...
- 第六章:声明式服务调用:Spring Cloud Feign
Spring Cloud Feign 是基于 Netflix Feign 实现的,整合了 Spring Cloud Ribbon 和 Spring Cloud Hystrix,除了提供这两者的强大功能 ...
- SpringCloud---声明式服务调用---Spring Cloud Feign
1.概述 1.1 Spring Cloud Ribbon.Spring Cloud Hystrix的使用几乎是同时出现的,Spring Cloud提供了一个更高层次的封装这2个工具类框架:Spring ...
- RestTemplate OR Spring Cloud Feign 上传文件
SpringBoot,通过RestTemplate 或者 Spring Cloud Feign,上传文件(支持多文件上传),服务端接口是MultipartFile接收. 将文件的字节流,放入ByteA ...
- datasnap远程方法支持自定义对象传参
有同仁需要远程方法传输自定义的数据类型,他以为要自己写代码会很复杂,其实DATASNAP早就为我们想到了. datasnap的数据序列和还原真是无与伦比的强大,其远程方法支持自定义对象传参,DATAS ...
- SpringCloud:feign对象传参和普通传参及遇到的坑
对象传参: #使用@RequestBody来指定传参对象 @RequestMapping(value = "/v2/matterCode/genCode", method = Re ...
- Spring Cloud Feign 如何使用对象参数
概述 Spring Cloud Feign 用于微服务的封装,通过接口代理的实现方式让微服务调用变得简单,让微服务的使用上如同本地服务.但是它在传参方面不是很完美.在使用 Feign 代理 GET 请 ...
- 微服务实战SpringCloud之Spring Cloud Feign替代HTTP Client
简介 在项目中我们有时候需要调用第三方的API,微服务架构中这种情况则更是无法避免--各个微服务之间通信.比如一般的项目中,有时候我们会使用 HTTP Client 发送 HTTP 请求来进行调用,而 ...
随机推荐
- 你所不知的spring与mybatis整合方法
内容目录 1.采用MapperScannerConfigurer2.采用接口org.apache.ibatis.session.SqlSession的实现类org.mybatis.spring.Sql ...
- python的输入和输出
基本输出 python中的输出使用关键字--print,与python2不同的是,python3的输出后面必须要加括号,示例如下: python3.0以上输出: python2.0以上的输出: 格式化 ...
- 关于自己"手机瘾"的切身体验
其实之前也喜欢看手机,只是从去年7月份开始,因为自控能力.新项目等原因,导致"手机瘾"这个病更严重了,控制不住,一看就是几小时.去年过年的时候,自己定的第一个目标就是戒掉手机瘾,到 ...
- C++模版的用法
模板是实现代码重用机制的一种工具,实质就是实现类型参数化,即把类型定义为参数. C++提供两种模板:函数模板,类模板 函数模板 template <typename T> T myMax( ...
- 文档管理器 PDFelement Pro v6.8.4.3921 精简绿色版
下载地址:点我 PDFelement是PDF全套解决方案专家,专注于PDF的创建.编辑.转换.标注.保护.管理.水印.压缩.签名等功能.Wondershare PDFelement是款国产优秀的专业P ...
- 哈工大计算机网络Week3-传输层
目录 学习目标 传输层服务概述 传输层服务和协议 传输层 vs. 网络层 Internet传输层协议 多路复用和多路分用 多路复用/分用 分用如何工作? 无连接分用(UDP) 面向连接的分用 面向连接 ...
- 腾讯云tomcat问题
Ubuntu启动特别慢 1.在$JAVA_HOME/jre/lib/security/java.security中,把securerandom.source=file:/dev/urandom替换成s ...
- NET多线程之进程间同步锁Mutex
Mutex类似于lock.Monitor,都是为了解决多线程环境下,资源竞争导致的访问顺序问题.常见资源竞争有以下情况: 1.单例,如何确保单例: 2.IO文件操作,如果同时又多个线程访问同一个文件会 ...
- Linux运维跳槽必备
Linux运维跳槽必备的40道面试精华题 1.什么是运维?什么是游戏运维?1)运维是指大型组织已经建立好的网络软硬件的维护,就是要保证业务的上线与运作的正常, 在他运转的过程中,对他进行维护,他集合了 ...
- JAVA通过URL链接获取视频文件信息(无需下载文件)
最近项目碰到一个大坑:APP上需要在获取视频列表时就获取视频的时长,但早期上传的时候数据库都没有保存这个数据,所以前段时间添加一个时长字段,在上传时手动输入视频时长,但是之前库中有上万条数据没这个信息 ...