【Feign踩坑】Get传参String中的“;”被转换成“,”问题

【Feign踩坑】Get传参String中的“;”被转换成“,”问题

例:
发出的请求为http://xxxx?temp=‘dsdd;ffff’。
下游服务接收到的temp参数值将会变成"dsdd,ffff"。

首先,我们知道feign底层使用RequestTemplate进行请求发送

RequestTemplate在发送请求前将会对请求进行转换。
使用resolve方法对GET参数变量进行url拼接。

public RequestTemplate resolve(Map<String, ?> variables) {

    StringBuilder uri = new StringBuilder();

    /* create a new template form this one, but explicitly */
    RequestTemplate resolved = RequestTemplate.from(this);

    if (this.uriTemplate == null) {
      /* create a new uri template using the default root */
      this.uriTemplate = UriTemplate.create("", !this.decodeSlash, this.charset);
    }

    uri.append(this.uriTemplate.expand(variables));

    /*
     * for simplicity, combine the queries into the uri and use the resulting uri to seed the
     * resolved template.
     */
    if (!this.queries.isEmpty()) {
      /*
       * since we only want to keep resolved query values, reset any queries on the resolved copy
       */
      resolved.queries(Collections.emptyMap());
      StringBuilder query = new StringBuilder();
      Iterator<QueryTemplate> queryTemplates = this.queries.values().iterator();

      while (queryTemplates.hasNext()) {
        QueryTemplate queryTemplate = queryTemplates.next();
        String queryExpanded = queryTemplate.expand(variables);
        if (Util.isNotBlank(queryExpanded)) {
          query.append(queryExpanded);
          if (queryTemplates.hasNext()) {
            query.append("&");
          }
        }
      }

      String queryString = query.toString();
      if (!queryString.isEmpty()) {
        Matcher queryMatcher = QUERY_STRING_PATTERN.matcher(uri);
        if (queryMatcher.find()) {
          /* the uri already has a query, so any additional queries should be appended */
          uri.append("&");
        } else {
          uri.append("?");
        }
        uri.append(queryString);
      }
    }

    /* add the uri to result */
    resolved.uri(uri.toString());

    /* headers */
    if (!this.headers.isEmpty()) {
      /*
       * same as the query string, we only want to keep resolved values, so clear the header map on
       * the resolved instance
       */
      resolved.headers(Collections.emptyMap());
      for (HeaderTemplate headerTemplate : this.headers.values()) {
        /* resolve the header */
        String header = headerTemplate.expand(variables);
        if (!header.isEmpty()) {
          /* split off the header values and add it to the resolved template */
          String headerValues = header.substring(header.indexOf(" ") + 1);
          if (!headerValues.isEmpty()) {
            resolved.header(headerTemplate.getName(), headerValues);
          }
        }
      }
    }

    resolved.body(this.body.expand(variables));

    /* mark the new template resolved */
    resolved.resolved = true;
    return resolved;
  }

queryTemplate.expand(variables)对整体请求变量进行组装;

public final class QueryTemplate extends Template {
  
  static final String COLLECTION_DELIMITER = ";";
  
  ......

  @Override
  public String expand(Map<String, ?> variables) {
    String name = this.name.expand(variables);
    return this.queryString(name, super.expand(variables));
  }

  private String queryString(String name, String values) {
    if (this.pure) {
      return name;
    }

    /* covert the comma separated values into a value query string */
    List<String> resolved = Arrays.stream(values.split(COLLECTION_DELIMITER))
        .filter(Objects::nonNull)
        .filter(s -> !UNDEF.equalsIgnoreCase(s))
        .collect(Collectors.toList());

    if (!resolved.isEmpty()) {
      return this.collectionFormat.join(name, resolved, this.getCharset()).toString();
    }

    /* nothing to return, all values are unresolved */
    return null;
  }
 }

由以上代码可见,当我们将参数temp的值设置为“dsdd;ffff”时,使用get请求发送时,将会将query的值转换为temp=dsdd&temp=ffff。
最终发送给下游服务的请求将会变成 http://xxxx?temp=dsdd&temp=ffff。

同时由于springmvc框架的解析方式,GET中同参数变量将会被转成以“,”分割的字符串。因此最终解析出的的temp的值将会变为"dsdd,ffff"。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值