java—使用uricomponentsbuilder正确编码路径变量和请求参数

42fyovps  于 2021-07-14  发布在  Java
关注(0)|答案(0)|浏览(508)

我正挣扎着 UriComponentsBuilder#queryParam 以及 UriComponents#expand 在正确编码uri的路径和查询部分中的所有特殊字符的同时,正确地协同工作。我特别纠结于“+”字符。或者,它被双重编码为 %252B ,或者根本没有编码。我需要有它的正确编码发送iso-8601日期作为请求参数。
当我这样做时:

@Test
public void test {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://www.google.com/{test}/");

Map<String, Object> expandParams = new HashMap<>();
expandParams.put("test", "junit 5");
Map<String, Object> queryParams = new HashMap<>();
queryParams.put("q", "junit+5");

for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
    builder = builder.queryParam(entry.getKey(), entry.getValue());
}

UriComponents uriComponents = builder.build();
if (MapUtils.isNotEmpty(expandParams)) {
    uriComponents = uriComponents.expand(expandParams);
}

final URI uri = uriComponents.encode().toUri();

assertEquals("https://www.google.com/junit%205/?q=junit%2B5", uri.toString());
}

测试失败:

Expected :https://www.google.com/junit%205/?q=junit%2B5  
Actual   :https://www.google.com/junit%205/?q=junit+5

因此,“+”符号不编码。
我知道我可以自己编码然后告诉 build() 我做的方法:

@Test
public void test {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://www.google.com/{test}/");

Map<String, Object> expandParams = new HashMap<>();
expandParams.put("test", "junit 5");
Map<String, Object> queryParams = new HashMap<>();
queryParams.put("q", encodeValue("junit+5"));

for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
    builder = builder.queryParam(entry.getKey(), entry.getValue());
}

UriComponents uriComponents = builder.build(true);
if (MapUtils.isNotEmpty(expandParams)) {
    uriComponents = uriComponents.expand(expandParams);
}

final URI uri = uriComponents.encode().toUri();

assertEquals("https://www.google.com/junit%205/?q=junit%2B5", uri.toString());
}

private static String encodeValue(String value) {
   try {
        return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
    } catch (UnsupportedEncodingException e) {
        // should not happen, we know the encoding is supported
        return value;
    }
}

但由于路径变量的原因,这会引发一个异常。 java.lang.IllegalArgumentException: Invalid character '{' for PATH in "/{test}/" 如果我使用 build() 或者 build(false) 在这种情况下,我得到双重编码:

Expected :https://www.google.com/junit%205/?q=junit%2B5  
Actual   :https://www.google.com/junit%205/?q=junit%252B5

我试着先扩展路径变量,然后才添加查询参数,但我也不能让它工作。
感谢您的帮助。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题