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 {@Autowiredprivate ObjectMapper objectMapper;/*** Called for every request. Add data using methods on the supplied {@link RequestTemplate}.** @param template*/@Overridepublic 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 实战》

能力一般,水平有限,如有错误,请多指出。
如果对你有用点个关注给个赞呗


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部