【问题标题】:UriComponentsBuilder - how to replace some of the queryParams and remove the unused?UriComponentsBuilder - 如何替换一些查询参数并删除未使用的?
【发布时间】:2018-10-11 06:18:23
【问题描述】:

嘿,我有这个包含多个查询参数的 url - 它用于搜索。这是一个讨厌的链接

https://someurl/customers?customer-id={customer-id}&type={type}&something={something}

我希望只替换其中两个参数

Map<String, String> params = new HashMap<>();
    params.put("customer-id", customerId);
    params.put("something", something)

    UriComponents customerUrl = UriComponentsBuilder
          .fromHttpUrl(specialURL)
          .buildAndExpand(params).encode();

但这会抛出。

java.lang.IllegalArgumentException: Map has no value for 'type'
    at org.springframework.web.util.UriComponents$MapTemplateVariables.getValue(UriComponents.java:346) ~[spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]

这里最好的解决方法是什么,假设我有大约 7 个参数,用空字符串替换它们或将字符串切成两半似乎相当 hacky。

【问题讨论】:

  • 它的内部实现要求所有的键必须存在于参数中,否则你会得到这个异常。
  • 您可能需要解析特殊 URL 的查询字符串并将其放入地图中。现在你知道了没有 query 的 url。你知道你想发送什么,所以你可以在这里使用两种方法。 1) 仅附加要编码的 URL 中存在的参数。 2)总是实例化完整的地图(所有非必填字段为空白/空/空(任何工作)并保留一些值)。然后你可以在 uri 组件构建器中传递该映射。
  • 想要删除所有查询参数的人可以这样做:builder.replaceQuery("")

标签: java spring http spring-boot resttemplate


【解决方案1】:

UriComponents 总是期望所有关键数据都必须存在于地图中,下面是引发异常的 UriComponents 使用的代码。

@Override
public Object getValue(String name) {
    if (!this.uriVariables.containsKey(name)) {
        throw new IllegalArgumentException("Map has no value for '" + name + "'");
    }
    return this.uriVariables.get(name);
}

解决方案:

所以要解决您的问题,您可以尝试以下代码。

class Param extends HashMap<String, String>{


    @Override
    public String get(Object key) {
        if(!super.containsKey(key)){
            super.put(key.toString(), "");
        }
        return super.getOrDefault(key, "t");
    }

    @Override
    public boolean containsKey(Object arg0) {
        return true;
    }   
}

public class UriComponenet {

    public static void main(String[] args) {

        Param params = new Param();
        params.put("customer-id", "1");
        String specialURL="https://someurl/customers?customer-id={customer-id}&type={type}&something={something}";
        UriComponents customerUrl = UriComponentsBuilder
              .fromHttpUrl(specialURL)
              .buildAndExpand(params).encode();

        System.out.println(customerUrl);        
    }
}

我已将 HashMap 类扩展为 Param,然后将该类用作 buildAndExpand 方法的输入。

希望这能解决你的问题。

【讨论】:

  • 嗯,为什么默认值是“t”?这确实解决了不抛出的问题,但看起来我的 api 设计不像它应该的那样工作。没有回应。
  • 这只是一个错误,现在你甚至不需要那个 getOrDetault 方法,你可以直接使用 get 方法。
【解决方案2】:
public static <T> UriComponents removeQueryParams(URI uri, Set<T> removeThese) {

    UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder
        .newInstance()
        .scheme(uri.getScheme())
        .schemeSpecificPart(uri.getSchemeSpecificPart())
        .userInfo(uri.getUserInfo())
        .host(uri.getHost())
        .port(uri.getPort())
        .path(uri.getPath())
        .fragment(uri.getFragment());

    UriComponents uriComponents = UriComponentsBuilder
        .fromUri(uri).build();

    MultiValueMap<String, String> args = new LinkedMultiValueMap<>(uriComponents.getQueryParams());
    removeThese.forEach(o -> args.remove(o.toString()));

    return uriComponentsBuilder
        .queryParams(args).build();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多