Feign Client GET请求,从微服务抛出“方法不允许:请求方法'POST'不受支持”

时间:2019-10-19 23:53:07

标签: java spring-boot spring-mvc microservices feign

我有一个带有Spring后端的Vue.js应用,该应用通过Feign Client调用“订单”微服务。我有许多使用@PathVariable()都可以正常工作的GET请求,但是我有1个GET请求,可以将任何数量的不同URL参数传递给它,并且已经定义了OrderListItemParameters类并将其添加到GET请求中,将参数传递给微服务。我可以看到该请求正在发送到微服务,但是由于“ org.zalando.problem.spring.common.AdviceTrait:不允许的方法:请求方法'POST'不支持”错误而被拒绝。

我已经确保伪装客户端发送的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类作为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请求... Logs

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

3 个答案:

答案 0 :(得分:0)

大概是由于请求正文的存在,控制器将您的方法视为POST。

我会尝试两种选择:

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

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

UPDATE 。如果仍然希望将GET方法与body一起使用,则需要通过显式标记参数来更改伪客户端中的方法调用:

@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);

}

答案 1 :(得分:0)

这是最终可以解决的解决方案...

#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正常工作。

我讨厌假装。

答案 2 :(得分:0)

该问题应该通过更改来解决:

String getOrderList(OrderListItemParameters orderListItemParams);

收件人:

String getOrderList(@SpringQueryMap OrderListItemParameters orderListItemParams);

问题在于,使用没有参数的数据类会将其映射到GET请求无法编码的主体请求;从而将请求转换为客户端中的POST,但在未实现该动词的正确服务器上以405失败。

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