解决 HTTP 请求参数中的加号被替换为空格问题
HTTP Java Tomcat About 2,267 words现象
使用GET
请求添加query string
(?
后的参数)或使用Content-Type
为application/x-www-form-urlencoded
的POST
请求携带参数时,加号(+
号)被替换为了空格。
原因
如果URLs
中出现了空格,需要用+
替换,所以这里解码的时候把+
转化回了空格。先有了编码的操作,所以才会有解码的操作。
Control names and values are escaped. Space characters are replaced by '+'
HTML 4.01 第 17.13.4 节,明确指出:当 Content-Type 为 application/x-www-form-urlencoded 时,对 names 和 vaules 进行转义,空格用 + 代替。
原文地址:https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
所以因为规范的原因,上传的+
号都在解码阶段转义成了空格。
源码
org.apache.tomcat.util.http.Parameters#processParameters(byte[], int, int, java.nio.charset.Charset)
判断有+
号则需要解码。
private void processParameters(byte bytes[], int start, int len, Charset charset) {
...
do {
switch(bytes[pos]) {
...
case '+':
// Decoding required
if (parsingName) {
decodeName = true;
} else {
decodeValue = true;
}
pos ++;
break;
...
}
...
} while (!parameterComplete && pos < end);
...
}
java.net.URLDecoder#decode(java.lang.String, java.lang.String)
可以看到URLDecoder
解码时在匹配字符串+
号时转换为了空格。
public static String decode(String s, String enc) {
...
while (i < numChars) {
c = s.charAt(i);
switch (c) {
case '+':
sb.append(' ');
i++;
needToChange = true;
break;
...
}
...
}
解决
方式一
前端上传时对+
号进行URLEncode
处理,或者将+
号统一换成%2B
。
HTML
规范对于GET
请求参数和Content-Type
为application/x-www-form-urlencoded
的POST
的请求参数都要进行URLEncode
处理。
方式二
使用request.getQueryString()
方法代替@RequestParam
和request.getParameter()
方法。
代码:
@GetMapping("/test")
public String test(@RequestParam("name") String name, HttpServletRequest request) {
System.out.println("request param#" + name);
String name1 = request.getParameter("name");
System.out.println("get parameter#" + name1);
String queryString = request.getQueryString();
System.out.println("request query string#" + queryString);
return name;
}
请求:
http://localhost:8080/test?name=Java+Go&age=13
输出:
request param#Java Go
get parameter#Java Go
request query string#name=Java+Go&age=13
参考
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓