feign不支持get请求参数对象解决方案
1. 问题描述:早期controller有一个由前端直接调用的获取商品详情的接口getGoodsInfo(ReqGoodsInfo req), Get请求方式;
后来想要在业务服务由后台对商品详情页的几个接口整合成一个,那么前端直接只调用一次即可。选择了feign昨晚跨服务调用的调用框架。那么原先的getGoodsInfo接口就要提供一个可供调用的client端如下
@RequestMapping( method = RequestMethod.GET, value = "/goods/***/goodsInfo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) ResultInfo<RespUsersideGoodsInfo> getUsersideGoodsInfo(@RequestParam("req") ReqGoodsInfo req);
很遗憾,feign并不支持get请求参数对象,feign在底层会直接将get的请求方式转为post请求。
private synchronized OutputStream getOutputStream0() throws IOException { try { if (!this.doOutput) { throw new ProtocolException("cannot write to a URLConnection if doOutput=false - call setDoOutput(true)"); } else { if (this.method.equals("GET")) { this.method = "POST"; } } } }
2. 既然如此,那么有些人直接在feignClient端直接加@RequestBody注解,但是那样的话,controller层也需要使用@RequestBody注解,这违反HTTP协议;而且这种方式也不适用我的需要。
3. 那么就想到,controller使用对象接收的get入参,实际上也是各个参数url上的拼接。那么就可以在feignClient端的方法改为
@RequestMapping( method = RequestMethod.GET, value = "/goods/***/goodsInfo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) ResultInfo<RespUsersideGoodsInfo> getUsersideGoodsInfo(@RequestParam("goodsId") Long goodsId, @RequestParam("productId") Long productId);
注意:这里的@RequestParam每一项的value都要与controller参数名保持一致,否则无法接收值。
4. 但是,如果是对于入参个数比较多,甚至是嵌套对象等等复杂情况,以上3也是不好处理。
有推荐使用@SpringQueryMap注解的,但是spring版本需要2.1以上才支持;