Java 中使用斜杠(无需双重编码)和特殊字符对 URI 查询参数进行编码

问题描述 投票:0回答:1

我有 2 个带有示例输入的字符串变量:

  1. 内容:“m/=a”
  2. 短信:“TEST123 ~!@#$%^&*()_+{}:<>?”

我需要使用 GET 方法将这两个变量作为查询参数发送。下面是我的代码。

创建休息模板:

DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);

RestTemplate restTemplate = constructRestTemplate(cpConnectivity);
restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);

编码函数:

return URLEncoder.encode(value, StandardCharsets.UTF_8);

发送请求:

UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance()
.queryParam("content", encode(content)
.queryParam("sms", sms.replace(" ", "+"));

ResponseEntity<String> responseEntity = restTemplate.exchange(uriComponentsBuilder.build(false).toUriString(), HttpMethod.GET, httpEntity, String.class);

这些变量的预期查询参数值为:

内容:“m%2F%3Da”

应对特殊字符进行编码,包括斜杠(/)。

短信:“TEST123+~!@%23$%25%5E%26*()_+%7B%7D:%3C%3E?”

空格应替换为+号,保留的特殊字符应进行编码。

使用现有代码,content按预期进行编码,但sms不能包含保留的特殊字符,否则会给出诸如“索引45处查询中的非法字符:”和“索引151处格式错误的转义对”之类的错误:“。

我尝试过其他解决方案:

  • uriComponentsBuilder.build(true).toUriString()
  • uriComponentsBuilder.build(false).encode().toUriString()
  • uriComponentsBuilder.build(true).encode().toUriString()
  • uriComponentsBuilder.encode().toUriString()
  • defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES);
  • defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
  • defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT);
  • URLDecoder.decode
    然后
    encode()

如果不调用

encode()
,斜杠(/)将不会被编码,因为它是一个有效的字符。如果我调用
encode()
,问题是 % 是双重编码的,因此斜杠 (/) 将是 %252F。如果我设置
.build(true)
,我会收到“无效字符”或“无效编码序列”等错误。

java encode resttemplate urlencode encodeuricomponent
1个回答
0
投票

“...我需要使用 GET 方法将这两个变量作为查询参数发送。...”

这是一个示例,它将对所有非字母数字进行编码。

String encode(String s) {
    StringBuilder b = new StringBuilder();
    char[] a = s.toCharArray();
    for (char c : a)
        if (c >= 'a' && c <= 'z') b.append(c);
        else if (c >= 'A' && c <= 'Z') b.append(c);
        else if (c >= '0' && c <= '9') b.append(c);
        else b.append("%%%x".formatted((int) c));
    return b.toString();
}
String decode(String s) {
    StringBuilder b = new StringBuilder();
    Pattern p = Pattern.compile("(?i)%[a-f\\d]{2}");
    Matcher m = p.matcher(s);
    char c;
    while (m.find()) {
        c = (char) Integer.parseInt(m.group().substring(1), 16);
        m.appendReplacement(b, Matcher.quoteReplacement(String.valueOf(c)));
    }
    m.appendTail(b);
    return b.toString();
}

并且,这是一个示例用法。

String s;
out.println(s = encode("TEST123 ~!@#$%^&*()_+{}:<>?"));
out.println(decode(s));

输出

TEST123%20%7e%21%40%23%24%25%5e%26%2a%28%29%5f%2b%7b%7d%3a%3c%3e%3f
TEST123 ~!@#$%^&*()_+{}:<>?
© www.soinside.com 2019 - 2024. All rights reserved.