下图圈起来的地方很关键,可以点开放大查看:
找到HTML 4.01第17.13.4节,其中明确指出:当content-type为application/x-www-form-urlencoded时,对names和vaules进行转义,空格用'+'代替。
HTML 4.01第17.13.4节原文如下:
Control names and values are escaped. Space characters are replaced by `+'
官方举的虽然是HTML 4.01的例子,但是我翻译了历史文献,发现其实在更早的HTML 3.2规范中就规定了,HTML 3.2规范在1996年就成为了W3C推荐标准,其中相关内容如下:
而HTML 3.2规范在1996年就成为了W3C推荐标准。
所以,我觉得这就是历史原因!
再说一次,在HTML 4.01规范中就明确规定了:当content-type为application/x-www-form-urlencoded时,对names和vaules进行转义,空格用'+'代替。
没有原因,就是规定!我在查询的过程中发现,其他的编程语言也有这样的问题,因为他们都遵从同样的标准,就有了同样的"历史原因"。
回到前面的这个地方:
这里解码的时候为什么把'+'转化为空格呢?因为"历史原因",如果URLs中出现了空格,需要用'+'替换,所以这里解码的时候把'+'转化回了空格。先有了编码的操作,所以才会有解码的操作。
很多的文章都在说这是'+'的原因,甚至有的文章说'+'的编码应该改为%20。但是其实上面分析过了,有问题的是空格,而不是'+'。
那为什么我们在做表单提交的时候,也经常写'+'号呀,为什么没有问题呢?
因为当Html的表单被提交时, 每个表单域都会被Url编码之后才在被发送,下面的小例子可以佐证:
解决方案
解决方案网上一大堆了,我这里罗列一下吧:
方案一:修改客户端,将客户端带'+'的参数中的'+'全部替换为'%2B',如下:
方案二:修改服务器端,将空格替换为'+',这种方式只适用于参数中'+'没有空格的情况。如下:
方案三:修改服务器端,将获取参数的方法由reuqest.getParameter改为request.getQueryString(),然后对得到的字符串进行解析。
最后说一句
正如我文章最开始说的,就算是熬夜爆肝,我也必须得输出这篇文章,因为我最开始的文章不仅写的表面,而且还有一些问题,我得对其进行纠正。
让我突然想起了之前和朋友的一次对话,他问我说:你作为程序员,时刻待命,只要系统一出问题你就立马会响应。你不觉得累吗?
我回答道:说真的,当系统出问题,需要我排查问题的时候,我不觉得累。因为这个系统是我负责的,代码是我自己一行行的写出来的。出现了问题,我得证明我的系统是没有问题的,是不是别人的打开方式不对。但是如果真的是我的代码导致的问题,我会心有愧疚,我也得立即响应,对其负责。
这是我作为一个程序员的自我修养。
这篇文章的风格和《这道面试题我真不知道面试官想要的回答是什么》有点相似,全文描述的都是很小的知识点,甚至可以说是冷知识。一句话就能说出表面上的为什么,提炼出一个知识点。
但是我觉得提炼出来的,是一个干瘪瘪的知识点,它不够丰富,没有探索的过程。
而我所展示的是我去寻找这个问题的答案的过程。通过JDK的"BUG"把几个协议串联起来,而且是全世界共同遵循的协议,极具权威性。
再推销一下我公众号:对于写文章,其实想到写什么内容并不难,难的是你对内容的把控。关于技术性的语言,我是反复推敲,查阅大量文章来进行证伪,总之慎言慎言再慎言,毕竟做技术,我认为是一件非常严谨的事情,我常常想象自己就是在故宫修文物的工匠,在工匠精神的认知上,目前我可能和他们还差的有点远,但是我时常以工匠精神要求自己。就像我之前表达的:对于技术文章(因为我偶尔也会荒腔走板的聊一聊生活,写一写书评,影评),我尽量保证周推,全力保证质量。坚持输出原创。
才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。