查询字符串参数的Java URL编码
假设我有一个URL查询字符串参数的Java URL编码,java,http,url,encoding,urlencode,Java,Http,Url,Encoding,Urlencode,假设我有一个URL http://example.com/query?q= 我有一个由用户输入的查询,例如: 随机单词500英镑银行$ 我希望结果是正确编码的URL: http://example.com/query?q=random%20word%20%A3500%20bank%20%24 实现这一目标的最佳方式是什么?我尝试了urlcoder并创建了URI/URL对象,但没有一个是完全正确的。是一种方法。您只需要记住只编码单个查询字符串参数名称和/或值,而不是整个URL,确保不编码查询字
http://example.com/query?q=
我有一个由用户输入的查询,例如:
随机单词500英镑银行$
我希望结果是正确编码的URL:
http://example.com/query?q=random%20word%20%A3500%20bank%20%24
实现这一目标的最佳方式是什么?我尝试了urlcoder
并创建了URI/URL对象,但没有一个是完全正确的。是一种方法。您只需要记住只编码单个查询字符串参数名称和/或值,而不是整个URL,确保不编码查询字符串参数分隔符&
或参数名称值分隔符=
String q = "random word £500 bank $";
String url = "https://example.com?q=" + URLEncoder.encode(q, StandardCharsets.UTF_8);
当您还没有使用Java 10或更新版本时,请使用StandardCharsets.UTF_8.toString()
作为字符集参数,或者当您还没有使用Java 7或更新版本时,请使用“UTF-8”
请注意,查询参数中的空格由
+
表示,而不是合法有效的%20
。%20
通常用于表示URI本身中的空格(URI查询字符串分隔符前面的部分?
),而不是查询字符串中的空格(后面的部分?
)
还要注意有三种encode()
方法。一个不带字符集
作为第二个参数,另一个带字符串
作为第二个参数,引发选中的异常。不带Charset
参数的已弃用。永远不要使用它,始终指定Charset
参数。甚至还明确建议按照和的要求使用UTF-8编码
所有其他字符都是不安全的,首先使用某种编码方案将其转换为一个或多个字节。然后,每个字节由3个字符的字符串“%xy”表示,其中xy是字节的两位十六进制表示形式建议使用的编码方案是UTF-8。但是,出于兼容性原因,如果未指定编码,则使用平台的默认编码
另见:
- 我不会使用
urlcoder
。除了名称不正确(urlcoder
与URL无关),效率低下(它使用StringBuffer
而不是生成器,并且做了一些其他慢的事情)也很容易出错
相反,我会使用or。
原因是您必须以不同于参数值的方式转义查询参数名称(即BalusC的答案q
)
以上的唯一缺点(我痛苦地发现)是
示例代码:
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
因为我只是链接到其他答案,所以我将其标记为社区维基。您可以随意编辑。Guava15现已添加。您需要首先创建一个URI,如:
String urlStr=”http://www.example.com/CEREC®材料与附件/IPS Empress®CAD.pdf“
URL=新URL(urlStr);
URI=新URI(url.getProtocol()、url.getUserInfo()、url.getHost()、url.getPort()、url.getPath()、url.getQuery()、url.getRef());
然后将该Uri转换为ASCII字符串:
urlStr=uri.toascistring();
现在您的url字符串已完全编码,首先我们进行了简单的url编码,然后将其转换为ASCII字符串,以确保字符串中没有US-ASCII之外的字符。浏览器就是这样做的。在android中,我会使用以下代码:
Uri myUI = Uri.parse ("http://example.com/query").buildUpon().appendQueryParameter("q","random word A3500 bank 24").build();
其中
Uri
是一个android.net.Uri
Apache Http组件库为构建和编码查询参数提供了一个简洁的选项-
对于HttpComponents 4.x,使用-
对于HttpClient 3.x,请使用-
您可以在代码中使用以下方法将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;
}
String addQueryStringToUrlString(字符串url,最终映射参数)引发不支持的DencodingException{
if(参数==null){
返回url;
}
for(Map.Entry参数:parameters.entrySet()){
最终字符串encodedKey=URLEncoder.encode(参数.getKey().toString(),“UTF-8”);
最后一个字符串encodedValue=URLEncoder.encode(参数.getValue().toString(),“UTF-8”);
如果(!url.contains(“?”){
url+=“?”+encodedKey+“=”+encodedValue;
}否则{
url+=“&”+encodedKey+“=”+encodedValue;
}
}
返回url;
}
String encodedUrl1 = UriUtils.encodeQuery(query, "UTF-8");//not change
String encodedUrl2 = URLEncoder.encode(query, "UTF-8");//changed
String encodedUrl3 = URLEncoder.encode(query, StandardCharsets.UTF_8.displayName());//changed
System.out.println("url1 " + encodedUrl1 + "\n" + "url2=" + encodedUrl2 + "\n" + "url3=" + encodedUrl3);
http://example.com/query?q=random%20word%20%C2%A3500%20bank%20$
这里发生了什么
1.将URL拆分为结构部分。对它使用java.net.URL
2.正确编码每个结构部件
3.使用IDN.toASCII(putDomainNameHere)
对主机名进行编码
4.使用java.net.URI.toascistring()
对NFC编码的unicode(最好是NFKC!)进行百分比编码。有关更多信息,请参阅:
在某些情况下,建议使用。还将“+”编码空间替换为“%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$"
}
该解决方案通过了由提供的大约100个测试用例。在我的例子中,我只需要传递整个url并只编码每个参数的值。 我没有找到这样做的通用代码(!!),所以我创建了这个小方法来完成这项工作:
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");
}
publicstaticstringencodeurl(stringurl)引发异常{
if(url==null | |!url.contains(“?”){
返回url;
}
列表=新的ArrayList();
字符串rootUrl=url.split(“\\?”[0]+“?”;
字符串paramsUrl=url.replace(rootUrl,“”);
List paramsUrlList=Arrays.asList(paramsUrl.split(“&”);
for(字符串参数:paramsUrlList){
if(参数包含(=)){
字符串键=参数拆分(“=”[0];
字符串值=pa
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");
}
String example = "random word £500 bank $";
String URL = "http://example.com/query?q=" + example.replaceAll(" ","%20");
UriComponentsBuilder
.fromUriString(url)
.build()
.encode()
.toUri()