Feign源码问题导致请求参数丢失

一、错误日志

feign.codec.DecodeException: Error while extracting response for type [***] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `***` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `***` out of START_ARRAY token at [Source: (PushbackInputStream); line: 1, column: 1]

 

二、错误原因排查

1、服务端开启了gzip,而客户端未开启;

2、参数未进行json序列化;

3、jackson反序列化失败引起:实体bean对应不正确,或者时间格式化错误;

发现这个错误的时候,也是度娘一顿搜索,逐个排查,但是都一一排除了;因为这个错误不是说一致存在,而是偶尔引起的,这就很烦人,因为我用postman测试服务端接口,怎么测试都是好使的。

并且服务也都开启了gzip,客户端使用的是httpclient,服务端是okhttp;后来搜到可能是因为httpclient源码问题导致解析gzip失败,所以给客户端换为okhttp(默认支持),但是还是会出现同样错误。

PS:现在才想起来不是所有都有这个问题,只是偶尔该接口才会报这个;所以我找到生产数据进行postman测试,发现仍然ok;然后彻底方了!然后我就查看controller中所有接口,虽然都遵循了restful接口规范,但是该接口(获取单个实体Bean,Get)与获取所有实体Bean(List,Get)请求路径一样,只是本接口中使用了@GetMapping的params来指定必传参数项!

脑子一抖,会不会是请求到了List的接口上,导致了客户端解析返回值错误!poastman测试,少勾选一个参数,然后我就重现了该错误。。。

从数据库中取到的真实数据,确实有一个字段的值是空的,但是怎么从客户端到服务端就给我少了一个参数,难道是Feign导致的!

随后,度娘加打断点发现Feign真的会把null值给过滤掉!

这是Feign源码:

   @Override
    public RequestTemplate create(Object[] argv) {
      RequestTemplate mutable = RequestTemplate.from(metadata.template());
      if (metadata.urlIndex() != null) {
        int urlIndex = metadata.urlIndex();
        checkArgument(argv[urlIndex] != null, "URI parameter %s was null", urlIndex);
        mutable.target(String.valueOf(argv[urlIndex]));
      }
      Map<String, Object> varBuilder = new LinkedHashMap<String, Object>();
      for (Entry<Integer, Collection<String>> entry : metadata.indexToName().entrySet()) {
        int i = entry.getKey();
        Object value = argv[entry.getKey()];
        if (value != null) { // Null values are skipped.
          if (indexToExpander.containsKey(i)) {
            value = expandElements(indexToExpander.get(i), value);
          }
          for (String name : entry.getValue()) {
            varBuilder.put(name, value);
          }
        }
      }

      RequestTemplate template = resolve(argv, mutable, varBuilder);
      if (metadata.queryMapIndex() != null) {
        // add query map parameters after initial resolve so that they take
        // precedence over any predefined values
        Object value = argv[metadata.queryMapIndex()];
        Map<String, Object> queryMap = toQueryMap(value);
        template = addQueryMapQueryParameters(queryMap, template);
      }

      if (metadata.headerMapIndex() != null) {
        template =
            addHeaderMapHeaders((Map<String, Object>) argv[metadata.headerMapIndex()], template);
      }

      return template;
    }

可以看到注释会把null值跳过!

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值