如何编码 URI 参数值?
Posted
技术标签:
【中文标题】如何编码 URI 参数值?【英文标题】:How do I encode URI parameter values? 【发布时间】:2010-10-01 10:36:19 【问题描述】:我想发送一个 URI 作为查询/矩阵参数的值。在将其附加到现有 URI 之前,我需要根据 RFC 2396 对其进行编码。例如,给定输入:
http://google.com/resource?key=value1 & value2
我期望输出:
http%3a%2f%2fgoogle.com%2fresource%3fkey%3dvalue1%2520%26%2520value2
java.net.URLEncoder
和 java.net.URI
都不会生成正确的输出。 URLEncoder
用于 html 表单编码,它与 RFC 2396 不同。URI
没有一次编码单个值的机制,因此它无法知道 value1 和 value2 是同一个键的一部分。
【问题讨论】:
我不确定我是否理解您期望的结果。我会使用 URLEncoder。 根据 Javadoc for URL:“也可以使用 URLEncoder 和 URLDecoder 类,但仅用于 HTML 表单编码,与 RFC2396 中定义的编码方案不同。” @Peter:同意,但后者已经死了。至少有一个投票赞成的答案,因此即使答案在技术上是错误的,它也不会出现在未回答的问题列表中。如果您想提供帮助,请投票为零。 我想知道例如你在你的问题中给出的结果。 抱歉,我删除了关于这是 ***.com/questions/304806/… 重复的评论 【参考方案1】:Jersey 的 UriBuilder 根据需要使用 application/x-www-form-urlencoded 和 RFC 3986 对 URI 组件进行编码。根据Javadoc
根据查询参数的 application/x-www-form-urlencoded 媒体类型规则和所有其他组件的 RFC 3986 规则,构建器方法执行相应 URI 组件中不允许的字符的上下文编码。请注意,只有特定组件中不允许的字符才需要进行编码,例如,提供给路径方法之一的路径可能包含矩阵参数或多个路径段,因为分隔符是合法字符并且不会被编码。在允许的情况下,百分比编码值也会被识别,并且不会被双重编码。
【讨论】:
网址无法访问。但是download.oracle.com/javaee/6/api/javax/ws/rs/core/… 已经可以使用了 您是如何使用 UriBuilder 生成上述预期输出的?我不知道如何告诉它对“?”之前的部分进行编码。谢谢! 如果你不使用 JAX-RS 而使用 Spring,你可以使用 Spring 的 UriUtils @tbh,我想说的是,如果您使用 UriBuilder,它将对需要为您编码的内容进行编码。如果您想手动编码文本部分,那么***.com/questions/304806/… 将起作用。或者,你可以使用 UriBuilder.fromPath("host/").matrixParam("key", "google.com/resource?key=value1 & value2").build() 你会得到 "host/…"。 谨防将 UriBuilder 用于不使用带有花括号的 JAX-RS 参数方案的“免费”URL。即使它可能是一个奇异的值,试试这个:UriBuilder.fromPath("http://www.query.example/").queryParam("key", "val").build();
会失败。 "http://www.query.example?key=" + URLEncoder.encode("val", "UTF-8")
会起作用。【参考方案2】:
你也可以使用 Spring 的UriUtils
【讨论】:
【参考方案3】:我没有足够的声誉来评论答案,但我只想指出,单独下载 JSR-311 api 是行不通的。您需要下载参考实现 (jersey)。
当 api 试图在运行时寻找实现时,只有从 JSR 页面下载 api 会给你一个 ClassNotFoundException。
【讨论】:
具体来说,您需要 jsr311-api、jersey-server 和 jersey-core jars。【参考方案4】:我自己写的,很短,超级简单,喜欢的话可以复制一下: http://www.dmurph.com/2011/01/java-uri-encoder/
【讨论】:
我猜人们对喜欢这个解决方案犹豫不决,因为他们可能担心它会有错误等。它看起来很全面,并且已经解决了几个错误,所以我想我会尝试一下. Java 和 Objective C 都没有内置例程来进行这种编码,这只是......令人困惑 嗯,这是针对 URI 本身而不是针对参数? 空格应该被转义:) 它只包含数字、字母和“标记”字符为未转义 @HerrGrumps 什么? Obj-C def 早就内置了 URL 编码。 @Jadar 哦?好的,也许我在 Obj-C 和/或 Java 上没有它是错误的 - 抱歉 :) 作为参考,也许您可以发布带有一些类/方法名称的回复,以防它可能会帮助可能不知道去哪里的人看起来(像我;))【参考方案5】:看来来自 Google GData-java-client 的 CharEscapers 有你想要的。它具有 uriPathEscaper 方法、uriQueryStringEscaper 和通用 uriEscaper。 (全部返回执行实际转义的 Escaper 对象)。 Apache 许可证。
【讨论】:
不幸的是它使用了一些其他的类和接口,但我认为你可以修改它以满足你的需要。 “一定有比这更简单的方法”。令我惊讶的是,这个常见的用例(构建 URI)并不容易做到。 java.net.URI 应该做得更好。 我对这个区域的混乱程度感到惊讶(老实说,我什至不知道有特殊的 URI 编码之类的东西......我学到了一些东西)。 彼得,我刚刚意识到这可能会起作用:jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/core/… 我正在为我的应用程序使用 JAX-RS。我会尝试并报告。 彼得,请添加以下内容,我会将其标记为已接受的答案:“ javax.ws.rs.core.UriBuilder 会做你想做的事:jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/core/…”【参考方案6】:我认为URI class 是您正在寻找的那个。
【讨论】:
它没有帮助,因为它希望我传递一个完整的查询字符串。它无法知道字符串的哪一部分需要编码,哪一部分不需要。我需要一个接收原始参数值并传递 URL 编码形式的方法。 是的。如果问题被投票一次,*** 会将问题标记为已回答。这个答案被一个人投了赞成票,而我投了反对票。它仍然将我的问题标记为上次我检查时已回答。 我的错。你说得对。我认为“赞成的答案”是指......你知道,左边有一个正数的答案...... 同样,请为***.uservoice.com/pages/general/suggestions/…投票 我会更新问题。无法对完整 URI 进行编码的原因是,如果我传入“key=value with spaces&still part of value”,则构造函数无法知道值的开始和结束位置。【参考方案7】:嗯,我知道你已经放弃了 URLEncoder,但不管文档怎么说,我还是决定试一试。
你说:
例如,给定一个输入:
http://google.com/resource?key=value
我期望输出:
http%3a%2f%2fgoogle.com%2fresource%3fkey%3dvalue
所以:
C:\oreyes\samples\java\URL>type URLEncodeSample.java
import java.net.*;
public class URLEncodeSample
public static void main( String [] args ) throws Throwable
System.out.println( URLEncoder.encode( args[0], "UTF-8" ));
C:\oreyes\samples\java\URL>javac URLEncodeSample.java
C:\oreyes\samples\java\URL>java URLEncodeSample "http://google.com/resource?key=value"
http%3A%2F%2Fgoogle.com%2Fresource%3Fkey%3Dvalue
正如预期的那样。
这会有什么问题?
【讨论】:
与RFC2396类似但又不一样。例如,尝试编码空格。 URLEncoder 会将其编码为“+”,URI 需要 %20。还有其他区别。 好的,但你不会是这样编码的:“value with space”而是“value+with+space”: like:java URLEncodeSample "google.com/resource?key=value+with+spaces" http%3A%2F%2Fgoogle.com%2Fresource%3Fkey%3Dvalue%2Bwith%2Bspaces 对于 RFC 2369,必须遵循一大堆规则。与其用输入字符串玩游戏,我宁愿找到一个能正确编码的类。 你打算做什么?知道这将非常有帮助,以便为您提供正确的答案。以上是关于如何编码 URI 参数值?的主要内容,如果未能解决你的问题,请参考以下文章