一、问题描述:
一句话概括:我们的 FeignClient 接口在 GET 请求下支持 POJO 参数?
如果我们调用放的接口是一个 GET 请求,如果我们是用 @FeignClient 直接定义 POJO 参数如下代码:
@FeignClient(name = "payment-service", contextId = "payment-core", path = "/payment") public interface PaymentFeign { @GetMapping("/refund") RefundPaymentVo refund(RefundPaymentDto refundPaymentDto); }
就会报下面的错误信息:
feign.FeignException$MethodNotAllowed: [405] during [GET] to [http://payment-service/payment/refund] [PaymentFeign#refund(RefundPaymentDto)]: [{"timestamp":"2022-03-26T18:34:47.058+00:00","status":405,"error":"Method Not Allowed","path":"/payment/refund"}] at feign.FeignException.clientErrorStatus(FeignException.java:221) at feign.FeignException.errorStatus(FeignException.java:194) at feign.FeignException.errorStatus(FeignException.java:185) at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:138) at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) at org.springframework.cloud.openfeign.FeignCircuitBreakerInvocationHandler.lambda$asSupplier$1(FeignCircuitBreakerInvocationHandler.java:112) 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)
二、解决方法:
OpenFeign@QueryMap
注解支持将 POJO 用作 GET 参数映射。不幸的是,默认的 OpenFeign QueryMap 注解与 Spring 不兼容,因为它缺少value
属性。
Spring Cloud OpenFeign 提供了等效的@SpringQueryMap
注解,用于将 POJO 或 Map 参数注解为查询参数映射。
例如,RefundPaymentDto
该类定义参数orderCode
和refundAmount
:
@Data public class RefundPaymentDto { /** * 订单号 */ private String orderCode; /** * 退款金额(单位:分) */ private Integer refundAmount; }
以下 feign 客户端通过注解使用Params
该类:@SpringQueryMap
@FeignClient(name = "payment-service", contextId = "payment-core", path = "/payment") public interface PaymentFeign { @GetMapping("/refund") RefundPaymentVo refund(@SpringQueryMap RefundPaymentDto refundPaymentDto); }
如果您需要对生成的查询参数映射进行更多控制,可以实现自定义QueryMapEncoder
bean。
三、总结:
@SpringQueryMap
注解的使用,简化了我们在 FeignClient 中 GET 参数的复杂定义(如果我们单个定义只能使用 @RequestParam
)
参考资料:1. Spring Cloud OpenFeign 官方文档