问题

最近做一个URL拼接的函数,需要将用户名拼接到url上。因为用户名可能会有特殊字符,所以需要进行urlencode。这里我使用的是java的urlEncode方式。问题代码可以提炼如下:

public static void main(String[] args) throws UnsupportedEncodingException, EncoderException, DecoderException {
	String source = "hello,  张三1+";
	String encodeStr = URLEncoder.encode(source, "UTF-8");
	String decodeStr = URLDecoder.decode(encodeStr, "UTF-8");
	System.out.println("原生编码后:" + encodeStr);
	System.out.println("原生解码后:" + decodeStr);
	
	String encodeStr1 = new URLCodec().encode(source);
	String decodeStr1 = new URLCodec().decode(encodeStr);
	System.out.println("Apache Common 编码后:" + encodeStr1);
	System.out.println("Apache Common 解码后:" + decodeStr1);
}

运行后结果如下:

原生编码后:hello%2C++%E5%BC%A0%E4%B8%891%2B
原生解码后:hello,  张三1+
Apache Common 编码后:hello%2C++%E5%BC%A0%E4%B8%891%2B
Apache Common 解码后:hello,  张三1+

从结果里可以看到,经过encode之后,空格被转换成了“+”号
这里我试了两种方式,一种是java原生的URLEncoder(java.net.URLDecoder),另一种是apache common下的URLCodec类,但是均转换成+号。我将这样的结果给前端,前端说转换有误。空格应该转换为“%20

原因

这个问题我没有注意过,特意网上百度了一下,总结如下:
首先,这个解析方式并没有错。只是标准不同而已,这里设计到三个标准:RFC1738、RFC2396、HTML4.01
从源码java.net.URLDecoder#encode方法上的注释可以看到,该方法转换规则为application/x-www-form-urlencoded,对应的网址为 https://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars,我们可以从https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 章节中看到,这里特殊指定了

Space characters are replaced by `+’
URLEncode

Java官方的URLEncoder.encode 实际上是为了post请求的content-type为x-www-form-urlencoded来设计的。

所以对于get和post两种请求:

  • 如果是get提交 或者是路径的话 如: http://www.bai du.com?wo=he he&ni=abc 就应该遵循RFC1738、RFC2396;空格转换为 %20

  • 如果是post提交:参数的值如果有空格应该编码成+号(注意不是%20)

结尾

因为我这次要拼接的却是是get请求,所以我按照网上大多数说法,在encode之后再特殊处理一下空格

 encodeStr = URLEncoder.encode(content, "UTF-8");
 encodeStr = encodeStr.replaceAll("\\+", "%20");
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐