Get请求传参,与编码解码
@1 Get请求流程:
在get请求中,参数直接添加在了url后面,同url一起提交到服务器。
常用的url参数的格式为:
http://ip:port/path/file?参数1=值1&参数2=值2….
多个参数之间使用&分割,参数与值之间使用=分割
例如:
http://localhost:8080/http/test?p1=zhangsan&p2=18
服务器端Servlet通过 req.getParameter(“参数名”)就可以获取相应参数的值。
@2 问题的产生
这是正常的使用情况,我们需要考虑某些特殊情况,如下:
假如p1参数的值是 “zhang&san”,那么url地址变为:
http://localhost:8080/http/test?p1=zhang&san&p2=18
这时,我们通过req.getParameter(“p1”)获取到的值为“zhang”,而不是我们想要的“zhang&san”,
这该怎么办呢,URL机制该如何应对类似的这种情况呢?
@3 解决问题-1 URL编码过程
为了防止这种情况发生,URL规定(RFC1738草案),在通过URL进行网络访问时,
需要将URL参数中的特殊字符进行URL编码。
这里面涉及到两个问题:
1 哪些字符是特殊字符
2 编码的时候如何进行编码
第一个问题:
除了大小写字母、数字、-_.(横线下划线小数点)这三类字符之外的字符,均为特殊字符
第二个问题:
特殊字符进行编码时分为两个步骤,
1:
特殊字符需要按照一定的编码格式(gbk或utf-8)转换为byte数组 (ISO-8859-1),
如,在gbk编码格式下 :
; 对应[3B]
& 对应[26]
%对应[25]
马对应[C2,ED]
经过第一步 ;&%马对应的字节序列变为 [3B,26,25,C2,ED]
2:
将第一步生成的byte数组,每个byte前添加%号,生成URL编码后的字符串
于是:
[3B,26,25,C2,ED]
转换为
%3B%26%25%C2%ED
这就是URL编码的过程,以及最终生成的编码后字符串。
在编写程序时,我们可以调用方法(或js中的function)来帮我们完成这个编码过程:
java中:java.net.URLEncoder(源URL,‘编码格式’);
js中:encodeUrIComponent(源URL);
这里需要注意的一点是,对于特殊字符空格“ ”,在通过URLEncoder编码时,不会编码成%20,(空格对应的ascii为0x20),而是会编码成“+”加号。这一点与 URL规定(RFC1738草案)中描述的不同。
但是这并不影响我们的使用,只要在解码时,按照这个规则进行解码就行了。
@3 解决问题-2 URL解码过程
web容器(以Tomcat为例)在接收到用户的Get请求后,会解析http请求报文,根据报文内容与服务器的环境,生成request对象,发送给Servlet处理。
服务器的环境,就是当前服务器的一些配置信息,其中重要的一项就是“默认编码格式”,
以tomcat8为例,默认编码格式为utf-8。
在servlet中,我们可以通过req.getParameter(“参数名”);来获取对应参数的值,这里要注意该调用背后的工作:
1:
在第一次调用该方法时,tomcat会将queryString按照&和=号进行分割成一个个的键值对,
然后对各个键和它对应的值进行url解码,string str = URLDecoder.decode(键/值,“tomcat编码格式”);,
这样,之前经过url编码的键/z值,又回归到了原本的模样。(解码的过程与编码过程相反)。
然后,解析该字符串,获取参数名和参数值(键值对),放入request对象的parameterMap中。
2:
第二步根据参数名,查找parameterMap,返回参数值。
这里需要注意的是,
1、按照URL规定(RFC1738草案),%20会解码为空格;按照encode方案,+号也会被解码为空格,所以%20和+号,均会被解码为空格。
2、解码过程会出现错误,此时该参数的值为null,
如,queryString为“name=3&age=3%3+&size=8”,这样在decode时参数age的值3%3+不满足解析的规则(%号后需要两位16进制数);那么age参数的值为null,name和size的值不受影响。
所以,对于get请求,对url中参数进行URLDecode的工作,tomcat帮助我们做了,解码时采用的编码格式为tomcat默认的编码格式,当然我们也可以通过配置文件,修改默认编码。
最后有几点需要声明:
1:
如果decode时的编码格式与encode时不同,那么参数就会出现中文乱码的问题。
2:
在浏览器地址栏中输入地址,浏览器在发起http请求时,并不会自动帮你将特殊字符进行encode,造成这个假象的原因是,他会将空格和中文字符,按照“utf-8”编码格式进行urlencode,其他特殊字符,它是不管的。