Feign 客户端 GET 请求,从微服务中抛出 "Method Not Allowed: Request method 'POST' not supported"

Feign Client GET request, throws "Method Not Allowed: Request method 'POST' not supported" from microservice

我有一个带有 spring 后端的 Vue.js 应用程序,它通过 Feign 客户端调用 'orders' 微服务。我有许多使用@PathVariable(s) 工作正常的 GET 请求,但我有 1 个 GET 请求,它可以传递任意数量的不同 URL 参数,并且定义了一个 OrderListItemParameters class 和已将其添加到 GET 请求中,以将参数传递给微服务。我可以看到请求正在发送到微服务,但它因 "org.zalando.problem.spring.common.AdviceTrait : Method Not Allowed: Request method 'POST' not supported" 错误而被拒绝。

我已确保伪装客户端发送的 OrderListItemParameters 与微服务中预期的 OrderListItemParameters 匹配。并且在 Feign 客户端或微服务中都没有提到 POST 。我只有 GET 和 PUT 端点。

Java前端代码的后端:

@RestController
@RequestMapping("/api")
public class OrdersResource {

    ## THIS WORKS NO PROBLEM
    @GetMapping("/order/{orderId}")
    public @ResponseBody
    ResponseEntity<?> order(@PathVariable int orderId) throws Exception {
        return ResponseEntity.ok(orderClient.order(orderId));
    }


    ## THIS ENDPOINT IS THE ONE THAT FAILS
    @GetMapping("/order/list")
    public @ResponseBody
    ResponseEntity<?> orders(OrderListItemParameters orderListItemParams) {
        return ResponseEntity
           .ok(orderClient.getOrderList(orderListItemParams));
    }
}

@Component
@AuthorizedUserFeignClient(name = "orders")
public interface OrderClient {

    ## THIS WORKS NO PROBLEM
    @RequestMapping(method = RequestMethod.GET, value = "/api/order/pg/{orderId}")
    String order(@PathVariable("orderId") int orderId);

    ## THIS ENDPOINT IS THE ONE THAT FAILS
    @RequestMapping(method = RequestMethod.GET, value = "/api/order/list")
    String getOrderList(OrderListItemParameters orderListItemParams);
}

OrderListItemParameters Class 作为 URL 参数传入:(这在微服务中是相同的)

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class OrderListItemParameters implements Serializable {

  private String searchPhrase;
  private String startDate;
  private String endDate;
  private ArrayList<String> sortKey;
  private ArrayList<String> sortValue;
  private Integer from;
  private Integer size;
}

(with getters, and setters) 

微服务控制器:

@Controller
@RequestMapping("/api")
public class OrderController {

  ## THIS WORKS NO PROBLEM
  @GetMapping("/order/pg/{orderId}")
  public @ResponseBody
  Order pgorder(@PathVariable int orderId) {
    return orderService.getPgOrderById(orderId);
  }

  ## THIS ENDPOINT IS THE ONE THAT FAILS
  @GetMapping("/order/list")
  public @ResponseBody
  ResponseEntity getOrderListItemsByMerchant(OrderListItemParameters orderListItemParams) {
    return orderService
        .getOrderListItemsByMerchant(orderListItemParams);
}

这是日志图片:清楚说明 GET 请求...

任何帮助弄清楚为什么控制器认为这是一个 POST 请求的帮助都会很棒。

据推测,由于请求主体的存在,控制器将您的方法视为 POST。

我会尝试两种选择:

@GetMapping("/order/list")
public @ResponseBody ResponseEntity<?> getOrderListItemsByMerchant() {
    // method code
}

@PostMapping("/order/list")
public @ResponseBody ResponseEntity<?> getOrderListItemsByMerchant(OrderListItemParameters orderListItemParams) {
    // method code
}

更新。如果你仍然想使用带body的GET方法,你需要通过显式标记参数来更改feign client中的方法调用:

@Component
@AuthorizedUserFeignClient(name = "orders")
public interface OrderClient {

    // feign methods

    @RequestMapping(method = RequestMethod.GET, value = "/api/order/list")
    @Headers(value = "Content-Type: application/json")
    ResponseEntity<String> getOrderList(@RequestParam("orderListItemParams") 
    OrderListItemParameters orderListItemParams);

}

这是最终有效的解决方案...

#Resource
@GetMapping("/order/list")
public @ResponseBody 
ResponseEntity<?> getOrderListItemsByMerchant(
    @RequestParam Map<String, Object> params) {
    // method code
}

#Feign Client
@RequestMapping(method = RequestMethod.GET, value = "/api/order/list")
ResponseEntity<String> getOrderList(@RequestParam Map<String, Object> params);

#Microservice Controller
@GetMapping("/order/list")
public @ResponseBody
ResponseEntity getOrderListItemsByMerchant(OrderListItemParameters orderListItemParams) {
    // method code
}

这允许我使用动态参数获取 URL,并且微服务仍然将请求视为 GET。

在请求的两边都有相同的定义对象会很好,但我根本无法使@SpringQueryMap 或@QueryMap 工作。

我讨厌Feign。

问题应该通过更改解决:

String getOrderList(OrderListItemParameters orderListItemParams);

收件人:

String getOrderList(@SpringQueryMap OrderListItemParameters orderListItemParams);

问题是使用不带参数的数据 class 将其映射到 GET 请求无法编码的正文请求;因此将请求转换为客户端中的 POST,在未实现动词的正确服务器上失败并显示 405。

在普通的 Feign 中,而不是 Spring 应该使用集成 @QueryMap。 More detailed information can be found here