English 中文(简体)
Java URL 查询字符串参数编码
原标题:Java URL encoding of query string parameters

说我有一个 URL

http://example.com/query?q=

我有一个用户输入的查询, 例如 :

500英镑 美元

我希望结果能是一个正确编码的 URL :

http://example.com/query?q=random%20word%20%A3500%20bank%20%24

实现这个目标的最佳方法是什么? 我尝试了 URLENcoder 并创建了 URI/ URL 对象,但都没有完全正确。

最佳回答

"https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/net/URLEENcoder.html",rel="noreferr"\code >URLENcoder 是前进的道路。您只需要记住将个别查询字符串参数名称和/或值编码为 ,而不是整个 URLU, 以免查询字符串参数分隔符字符 或参数名称-价值分隔符字符

String q = "random word £500 bank $";
String url = "https://example.com?q=" + URLEncoder.encode(q, StandardCharsets.UTF_8);

当您在 Java 10 或 新的 Java 10 上重现时, 使用 < code> StandardCharsets.UTF_ 8. name () 作为字符集参数, 或者当您在 Java 7 上重现时, 使用 < code> "UTF-8" 。


请注意,查询参数中的空格由 , 而不是合法有效的 表示。 通常用于代表URI本身的空间(URI-query字符串分隔符 之前的部分? ),而不是在查询字符串中( 之后的部分? )。

请注意有三种 < code> encode () < /code > code () < < code> () < /code > ) 方法。 一种方法没有 Charset 作为第二个参数, 另一种方法是 < code> string 作为第二个参数, 扔出一个被检查的例外。 没有 < code> Charset 的参数已被废除。 从未使用它, 并且总是指定 < code > < Charset < /code > 参数。 https://www.rfc-editor.org/rfc/rfc3986/ en/java/java/java/java/ net/ URLEncoder.html/ net/ net/ URLEncoder. html/ a/ net/ URLENC_ org > 和 refr@ a\ char@ hrefs.

所有其他字符都是不安全的, 并且首先使用某种编码方案转换成一个或多个字节。 然后每个字节由三字符字符串 "%xy" 表示, 其中 xy 是字节的两位数十六进制表示 。 < enger > 推荐使用的编码方案是 UTF-8 。 但是, 出于兼容性的原因, 如果未指定编码, 那么会使用平台的默认编码 。

See also:

问题回答

我不会使用 URLENcoder 。 除了被错误命名( URLENcoder 与 URLERS 无关) 之外, 效率低下( 它使用 < code> StringBuffer 而不是构建器, 并且做了其他一些慢事), 也很容易把它搞砸 。

Instead I would use URIBuilder or Spring s org.springframework.web.util.UriUtils.encodeQuery or Commons Apache HttpClient. The reason being you have to escape the query parameters name (ie BalusC s answer q) differently than the parameter value.

上述情况的唯一不利之处(我痛苦地发现)是,>URLs并非URRIsss 的真正子集。

样本代码 :

import org.apache.http.client.utils.URIBuilder;

URIBuilder ub = new URIBuilder("http://example.com/query");
ub.addParameter("q", "random word £500 bank $");
String url = ub.toString();

// Result: http://example.com/query?q=random+word+%C2%A3500+bank+%24

您需要先创建 URI 如 :

String urlStr = "http://www.example.com/CEREC® Materials & Accessories/IPS Empress® CAD.pdf"
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());

然后将该 URI 转换为 ASCII 字符串 :

urlStr = uri.toASCIIString();

现在您的 URL 字符串已被完全编码。 首先, 我们做了简单 < a href=" https:// en.wikipedia. org/ wiki/ Percent- encoding" rel= “ 不跟随 noreferr" > URL 编码 , 然后我们将其转换为 ASCII 字符串, 以确保在字符串中不再有 US- ASCII 以外的字符 。 这就是浏览器的操作方式 。

Guava 15号现已添加

代码代码

URL url = new URL("http://example.com/query?q=random word £500 bank $");
URI uri = new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String correctEncodedURL = uri.toASCIIString();
System.out.println(correctEncodedURL);

打印打印

http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$

这是怎么回事?

1. 将 URL 分割成结构部件。 请使用 java. net. URL

<% 2> 正确编码每个结构部分!

3. 使用 IDN.toASCII(putDomainName here) Punycode 编码主机名!

4. 使用 java.net.URI.toASCIIString () < a href="https://en.wikipedia.org/wiki/Percent-encoding" rel=“nofollown noreferr'>>percent-encode ,NFC编码的Unicode - (最好是NFKC!) 详情见: 检查URL是否已编码为 。 另用% 20 编码为空格替换+编码为空格。

以下是一些也将适当发挥作用的例子。

{
      "in" : "http://نامه‌ای.com/",
     "out" : "http://xn--mgba3gch31f.com/"
},{
     "in" : "http://www.example.com/‥/foo",
     "out" : "http://www.example.com/%E2%80%A5/foo"
},{
     "in" : "http://search.barnesandnoble.com/booksearch/first book.pdf",
     "out" : "http://search.barnesandnoble.com/booksearch/first%20book.pdf"
}, {
     "in" : "http://example.com/query?q=random word £500 bank $",
     "out" : "http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$"
}

溶液通过Web平台测试 提供的大约100个测试病例。

使用 rel=“nofollown noreferrerr” >spring s Uriconcompentsbuilder :

UriComponentsBuilder
        .fromUriString(url)
        .build()
        .encode()
        .toUri()

“https://hc.apache.org/'rel=“不跟随 noreferrer>>Apache Httpconconcontents 图书馆为构建和编码查询参数提供了一个整齐的选项。

With HttpComponents 4.x use:

URLEENcodUtils

For HttpClient 3.x use:

< a href="https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ util/ intil/ EncodingUtil.html#formUrlEndol( org.apache. commons. commons. Name ValuePair% 5B% 5D,%20java. lang.String)" rel=“ 不随从 noreferrerr" > EncordingUtil

此处是您在代码中可以使用的方法,将一个 URL 字符串和参数地图转换为包含查询参数的有效编码 URL 字符串。

String addQueryStringToUrlString(String url, final Map<Object, Object> parameters) throws UnsupportedEncodingException {
    if (parameters == null) {
        return url;
    }

    for (Map.Entry<Object, Object> parameter : parameters.entrySet()) {

        final String encodedKey = URLEncoder.encode(parameter.getKey().toString(), "UTF-8");
        final String encodedValue = URLEncoder.encode(parameter.getValue().toString(), "UTF-8");

        if (!url.contains("?")) {
            url += "?" + encodedKey + "=" + encodedValue;
        } else {
            url += "&" + encodedKey + "=" + encodedValue;
        }
    }

    return url;
}

I would use this code: 我用这个密码:

Uri myUI = Uri.parse("http://example.com/query").buildUpon().appendQueryParameter("q", "random word A3500 bank 24").build();

此处的 Uri 是一个 android.net.Uri

In my case I just needed to pass the whole URL and encode only the value of each parameters. I didn t find common code to do that, so (!!) so I created this small method to do the job:

public static String encodeUrl(String url) throws Exception {
    if (url == null || !url.contains("?")) {
        return url;
    }

    List<String> list = new ArrayList<>();
    String rootUrl = url.split("\?")[0] + "?";
    String paramsUrl = url.replace(rootUrl, "");
    List<String> paramsUrlList = Arrays.asList(paramsUrl.split("&"));
    for (String param : paramsUrlList) {
        if (param.contains("=")) {
            String key = param.split("=")[0];
            String value = param.replace(key + "=", "");
            list.add(key + "=" +  URLEncoder.encode(value, "UTF-8"));
        }
        else {
            list.add(param);
        }
    }

    return rootUrl + StringUtils.join(list, "&");
}

public static String decodeUrl(String url) throws Exception {
    return URLDecoder.decode(url, "UTF-8");
}

它使用Apache Commons org.apache.commons.lang3.StringUtils

  1. 使用此选项 :

     URLEncoder.encode(query, StandardCharsets.UTF_8.displayName());
    

    或此:

     URLEncoder.encode(query, "UTF-8");
    
  2. 您可以使用以下代码 。

     String encodedUrl1 = UriUtils.encodeQuery(query, "UTF-8"); // No change
     String encodedUrl2 = URLEncoder.encode(query, "UTF-8"); // Changed
     String encodedUrl3 = URLEncoder.encode(query, StandardCharsets.UTF_8.displayName()); // Changed
    
     System.out.println("url1 " + encodedUrl1 + "
    " + "url2=" + encodedUrl2 + "
    " + "url3=" + encodedUrl3);
    

您可以使用 commons- httpclient 来编码url 的查询参数 :

马文依赖性:

    <dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
        <scope>test</scope>
    </dependency>

Java 代码 :

   import org.apache.commons.httpclient.URIException;
   import org.apache.commons.httpclient.util.URIUtil;
   import org.junit.jupiter.api.Test;

   import static org.junit.jupiter.api.Assertions.assertEquals;

   public class URIUtilTest {
      @Test
      void encodeQueryTest() throws URIException {
          assertEquals("https://example.com/search?q=java%2021", URIUtil.encodeQuery("https://example.com/search?q=java 21"));
          assertEquals("https://example.com/search?filter=%7B%7D", URIUtil.encodeQuery("https://example.com/search?filter={}"));
      }
  }




相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...