奇葩的FeignClient问题

这些问题只是本人觉得奇葩,也许不是FeignClient的问题,whatever,只是做个记录。

1、一言不合就POST

/**
     * 查询单个档案(根据档案类型名称)
     * 用法:GET http://<host>:<port>/v1.0/devices/archives2/{archiveName}/{deviceId}
     * @param deviceId 设备id
     * @param archiveName 档案类型名称
     * @param appToken 应用token
     * @return 返回查询结果
     */
    @Headers("app-token:{appToken}")
    @RequestLine("GET /devices/archives2/{archiveName}/{deviceId}")
    DeviceArchive findSingleArchiveByDeviceId2(@Param("appToken")String appToken,
                                               @Param("archiveName")String archiveName,
                                               @Param("deviceId")String deviceId);

对于上面这个接口,能看出哪里有错吗?服务端返回的报错:

Exception in thread "main" feign.FeignException: status 405 reading Mongo#findSingleArchiveByDeviceId2(String,String,String); content:
{"timestamp":1488507926013,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/devices/archives2/air_container/4661125"}
    at feign.FeignException.errorStatus(FeignException.java:62)
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:134)
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
    at com.sun.proxy.$Proxy4.findSingleArchiveByDeviceId2(Unknown Source)
    at com.chinamobile.iot.App.main(App.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

第一反应是见了鬼了,明明是GET,怎么会提示”Request method ‘POST’ not supported”。搞了半天才发现是@Herders里边的键值对冒号后面必须有个空格!正确的写法:

 @Headers("app-token: {appToken}")

另外,如果GET方法有一堆参数:

/**
     * 查询单个设备数据
     * 用法:GET http://<host>:<port>/v1.0/devices/datas/{deviceId}
     * @param deviceId          设备ID
     * @param appToken          应用Token
     * @param deviceDataId      数据集合的UUID
     * @param deviceDataName   数据名
     * @param filters           过滤条件
     * @param limit             最大查询数据量
     * @param startTime         开始时间
     * @param endTime           结束时间
     * @return 返回查询结果
     */

想要设置一个request实体类,把所有参数都包进去,放到HTTP 的body来上传,也会被当成POST。一句话:GET参数不支持复杂对象(只支持String、Integer这些简单对象)

2、传的是NULL,收到的是参数名

例子如下:

@RequestLine("POST /mongodb/datas")
boolean addBatchDatas(@Param("app-token") String appToken, AddBatchDataRequest addBatchDataRequest);

如果传参的时候,因为某些原因给appToken传的是null(并非有意要传null,有时是程序出现了bug)

mongo.addBatchDatas(null, addBatchDataRequest); //mongo是已初始化的Feign对象

服务端报错,输出的调试信息如下:

appToken={app-token}

当第一次遇到这个问题的时候,百思不得其解为何appToken会被设为“{app-token}”,调试了半天才发现是设值null时Feign就会传这个,私以为Feign更合理的做法是提示某某参数为null。

3、服务是POST,Client错写为GET

服务端是POST:

@RequestMapping(value = "{productId}", method = RequestMethod.GET)
    ProductInfo getProduct(@PathVariable("productId") Integer productId);

@RequestMapping(value = "getByProductKey", method = RequestMethod.POST)
    public ProductInfo getByProductKey(@RequestParam("productKey") String productKey);

Client错把getByProductKey写为GET

@RequestMapping(value = "{productId}", method = RequestMethod.GET)
    ProductInfo getProduct(@PathVariable("productId") Integer productId);

@RequestMapping(value = "getByProductKey", method = RequestMethod.GET)
    ProductInfo getByProductKey(@RequestParam("productKey") String productKey);

客户端调用时报错:

"message":"Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: \"getByProductKey\""

服务端打印的调试信息也很奇怪,明明调的是getByProductKey,怎么变成了getProduct:

GET 192.168.1.115:9000/products/getByProductKey?productKey=ukyUPF7S started, method=getProduct

4、直接返回NULL

如果忘了加@EnableFeignClients,则会直接调callback,导致返回null。

    原文作者:quiterr
    原文地址: https://www.jianshu.com/p/df6b738e2f9a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞