Java URL encoding: URLEncoder vs. URI

2022-09-01 21:51:48

W3学校URL编码网页上,它说应该编码为,并且应该编码为。@%40space%20

我已经尝试了两者和,但上述两者都不正确:URLEncoderURI

import java.net.URI;
import java.net.URLEncoder;

public class Test {
    public static void main(String[] args) throws Exception {

        // Prints me%40home.com (CORRECT)
        System.out.println(URLEncoder.encode("me@home.com", "UTF-8"));

        // Prints Email+Address (WRONG: Should be Email%20Address)
        System.out.println(URLEncoder.encode("Email Address", "UTF-8"));

        // http://www.home.com/test?Email%20Address=me@home.com
        // (WRONG: it has not encoded the @ in the email address)
        URI uri = new URI("http", "www.home.com", "/test", "Email Address=me@home.com", null);
        System.out.println(uri.toString());
    }
}

出于某种原因,电子邮件地址是否正确但未使用空格,并且空格是否为货币而不是电子邮件地址。URLEncoderURI

我应该如何对这2个参数进行编码,以与w3schools所说的正确(或者w3schools是错误的?)保持一致。


答案 1

虽然我认为@fge的答案是正确的,但由于我使用的是第三方Web服务,它依赖于W3Schools文章中概述的编码,因此我遵循了Java的答案,相当于JavaScript的encodeURIComponent,它产生相同的输出?

public static String encodeURIComponent(String s) {
    String result;

    try {
        result = URLEncoder.encode(s, "UTF-8")
                .replaceAll("\\+", "%20")
                .replaceAll("\\%21", "!")
                .replaceAll("\\%27", "'")
                .replaceAll("\\%28", "(")
                .replaceAll("\\%29", ")")
                .replaceAll("\\%7E", "~");
    } catch (UnsupportedEncodingException e) {
        result = s;
    }

    return result;
}

答案 2

URI 语法由 RFC 3986 定义(查询字符串的允许内容在第 3.4 节中定义)。Java符合这个RFC,在其Javadoc中提到了一些警告。URI

您会注意到语法规则由以下公式定义:pchar

pchar = unreserved / pct-encodeed / sub-delims / “:” / “@”

这意味着 a 在查询字符串中是合法的@

信任 URI。它将做正确的,“合法”的事情。

最后,如果你看一下URLEncoder的Javadoc,你会看到它声明:

此类包含用于将字符串转换为应用程序/x-www-form-urlencoded MIME 格式的静态方法。

这与 URI 规范定义的查询字符串不是一回事。