Spring Cloud Feign 多参数传递了解一下?

简介: Spring Cloud Feign 多参数传递了解一下?

Feign 可以在服务消费者和服务提供者之间进行GET和Post多参数传递的。springmvc中是支持GET方法绑定pojo的,但是Feign 并未覆盖springmvc中的所有方法,目前解决方式很多,常见的有如下方式:


  • 把pojo拆分成一个个单独的属性做为方法参数
  • 方法参数作为map传递


如果不这么解决当使用对象做为参数时会报以下错误:

当然以下错误的原因还有可能是通过Feign 进行服务间调用时,GET方法的参数没有加@PathVariable或@RequestParam注解

feign.FeignException$MethodNotAllowed: status 405 reading UserProviderClientService#save(UserEntity)
  at feign.FeignException.clientErrorStatus(FeignException.java:167)
  at feign.FeignException.errorStatus(FeignException.java:141)
  at feign.FeignException.errorStatus(FeignException.java:133)
  at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92)
  at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:151)
  at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80)
  at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:109)
  at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
  at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
  at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
  at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  at rx.Observable.unsafeSubscribe(Observable.java:10327)
  at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
  at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
  at rx.Observable.unsafeSubscribe(Observable.java:10327)
  at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
  at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
  at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  at rx.Observable.unsafeSubscribe(Observable.java:10327)
  at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
  at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
  at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
  at org.springframework.cloud.sleuth.instrument.async.TraceCallable.call(TraceCallable.java:70)
  at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
  at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  at java.lang.Thread.run(Thread.java:748)

上面的问题还可以通过拦截器去解决,Feign 提供了一个请求拦截器RequestInterceptor,可以在请求之前给请求加请求头等功能,有点类似于spring cloud gateway中的断言工厂,有关spring cloud gateway可以查看springcloud 入门 之网关 springcloud gateway

代码如下:

@Component
public class FeignRequestInterceptor implements RequestInterceptor {
    @Autowired
    private ObjectMapper objectMapper;
    /**
     * Called for every request. Add data using methods on the supplied {@link RequestTemplate}.
     *
     * @param template
     */
    @Override
    public void apply(RequestTemplate template) {
        final String method = template.method();
        final Request.Body requestBody = template.requestBody();
        if ("GET".equals(method) && requestBody != null && requestBody.bodyTemplate() != null) {
            final String requestParam = requestBody.asString();
            try {
                //把之前的请求体清空
                template.body(Request.Body.empty());
                final JsonNode jsonNode = objectMapper.readTree(requestParam);
                Map<String, Collection<String>> params = new HashMap<>(jsonNode.size());
                buildQuery(jsonNode , "" , params);
                template.queries(params);
            } catch (IOException e) {
                //可根据项目需求处理异常
                e.printStackTrace();
            }
        }
    }
    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
        if (!jsonNode.isContainerNode()) {   // 叶子节点
            if (jsonNode.isNull()) {
                return;
            }
            Collection<String> values = queries.computeIfAbsent(path, k -> new ArrayList<>());
            values.add(jsonNode.asText());
            return;
        }
        if (jsonNode.isArray()) {   // 数组节点
            Iterator<JsonNode> it = jsonNode.elements();
            while (it.hasNext()) {
                buildQuery(it.next(), path, queries);
            }
        } else {
            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
            while (it.hasNext()) {
                Map.Entry<String, JsonNode> entry = it.next();
                if (StringUtils.hasText(path)) {
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {  // 根节点
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }
}

通过FeignRequestInterceptor拦截器就能解决GET方法无法传递pojo的问题了。

有关feign的学习可以参考springcloud 入门(3) 声明式调用 Feign


学习更多关于springcloud的可以关注我的 springcloud 专栏


GitHub地址:

https://github.com/ArronSun/micro-services-practice.git


参考:


《重新定义springcloud 实战》


能力一般,水平有限,如有错误,请多指出。

如果对你有用点个关注给个赞呗


目录
相关文章
|
2月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
2月前
|
Java 开发工具 git
实现基于Spring Cloud的配置中心
实现基于Spring Cloud的配置中心
|
2月前
|
设计模式 监控 Java
解析Spring Cloud中的断路器模式原理
解析Spring Cloud中的断路器模式原理
|
6天前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
2月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14605 26
|
2月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
288 15
|
2月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
60 3
|
2月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
145 5
|
2月前
|
Java API 开发工具
Spring Boot与Spring Cloud Config的集成
Spring Boot与Spring Cloud Config的集成