美文网首页
从今天FeignClient中GET方式被强制转换为POST方式

从今天FeignClient中GET方式被强制转换为POST方式

作者: Cherron | 来源:发表于2018-09-20 16:41 被阅读0次
    事情是这样的

    注:编写本文时已将敏感代码换为了其他代码代替

    本微服务需要调用另一微服务的GET查询接口,且该接口有十来个入参,所以我的FeignClient是这样写的:

    @FeignClient(name = "service-b", url = "${service.b.url}")
    public interface BFeignClient {
    
        /**
         * 查询
         * 
         * @param BRequest ,自定义的Java对象
         * @return BResponse ,自定义的Java对象
         */
        @RequestMapping(value = "/xxx", method = RequestMethod.GET)
        BResponse query(BRequest req);
    }
    

    本以为FeignClient会像Spring Boot Controller层一样,自动帮我把BRequest拆解为RequestParam。结果我用抓包工具监听了发出的请求,它转成了POST方式!

    (Request-Line):POST /xxx/xxx
    Content-Type:application/json;charset=UTF-8
    Apitoken:{xxxxxxxxx}
    Accept:*/*
    User-Agent:Java/1.8.0_162
    Host:xxxx:xxx
    Connection:keep-alive
    Content-Length:154
    
    

    问题就来了~

    找找为什么

    当接口入参是自定义的类型时,就会被放在RequestBody里面,以及变成了POST。
    GitHub上Spring Cloud也有相关的issue:Suggest supporting POJO as request parameter,另外,
    简友周立_itmuch的文章《Spring Cloud中,如何使用Feign构造多参数的请求》提到了这一现象,并且提出了解决办法

    两种解决办法
    1. 将BRequest的各个属性,手动拆开,放到query接口里,类似这样:
    //此处@RequestParam必须指明name
    @RequestMapping(value = "/xxx", method = RequestMethod.GET)
    BResponse query(@RequestParam("a") A a, @RequestParam("b") B b, @RequestParam("c") C c... ...);
    

    但这样麻烦且不雅观

    1. BRequest 转为 Map<String, Object> map:
    //此处@RequestParam不需指明name,具体原因,待考究。。。
    @RequestMapping(value = "/xxx", method = RequestMethod.GET)
    BResponse query(@RequestParam Map<String, Object> map);
    

    让我选的话,我选第二种方法,哈哈~

    Object 转为 Map<String, Object>

    麻烦来了,我们的BRequest怎么转为Map<String, Object>呢,百度找到的许多方法都比较麻烦,我希望有现成工具类,终于在StackOverflow上,找到了答案:
    How to convert a Java object (bean) to key-value pairs (and vice versa)?

    import com.fasterxml.jackson.databind.ObjectMapper;
    
    ObjectMapper m = new ObjectMapper();
    //Object to Map<String, Object>
    Map<String,Object> props = m.convertValue(myBean, Map.class);
    //Map<String, Object> to Object
    MyBean anotherBean = m.convertValue(props, MyBean.class);
    

    StackOverflow是个好东西!

    关键——ObjectMapper工具类

    入门介绍:Jackson ObjectMapper类
    它主要是处理Object和Json的互相转换。

    完,总结了解决这个问题时的步骤,写得不够深入

    相关文章

      网友评论

          本文标题:从今天FeignClient中GET方式被强制转换为POST方式

          本文链接:https://www.haomeiwen.com/subject/iexnnftx.html