application/x-www-form-urlencoded

表单的enctype属性表示在发送到服务器之前应该如何对表单数据进行编码,默认值是application/x-www-form-urlencoded。如果表单提交时使用get请求,浏览器或者使用httpClient、okhttp这些组件开发的客户端会把编码后的数据加到URL后面,数据和URL使用“?”分隔。如果表单提交时使用post请求,编码后的数据会被放到请求报文体(body)中提交给服务端

注意,如果是自己使用httpClient、okhttp这些组件开发的客户端,那么设置了Content-Type:application/x-www-form-urlencoded; charset=UTF-8,还需要我们自己把要传的数据编码,组件不会帮我们处理。

编码后的数据是一个字符串,字符串中的键值对用 & 分隔,并且键与值用 = 分隔。如果值包含多字节的字符,那么该字符将被“%HH”取代,即一个百分比符号和两个十六进制数字表示的字符串。HH与字符编码有关,如果 Content-Type 为 application/x-www-form-urlencoded;charset=UTF-8,那么该字符将首先被编码为UTF-8字节数组,再将每个字节转换为HH。

特别要注意,不论字符编码是什么,空格都会被编码为 +,以下三行代码等同于使用application/x-www-form-urlencoded进行编码,都输出 +。

public static void main(String[] args) throws Exception {

System.out.println(URLEncoder.encode(" ", "UTF-8"));

System.out.println(URLEncoder.encode(" ", "GBK"));

System.out.println(URLEncoder.encode(" ", "BIG5"));

}

由于RFC1738没有规定具体的字符编码,所以各浏览器使用的字符编码不一样,可能是UTF-8,也可能是系统字符编码。

encodeURIComponent()

JS有三个常用的数据编码函数。

escape()

这个函数是最古老的,已经不推荐使用。实际上,escape()不能直接用于URL的编码,它的真正作用是返回一个字符的Unicode编码值。比如"春节"的返回结果是%u6625%u8282,也就是说在Unicode字符集中,"春"是第6625个(十六进制)字符,"节"是第8282个(十六进制)字符。

该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。在\u0000到\u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。对应的解码函数是unescape()。所以,"Hello World"的escape()编码就是"Hello%20World"。因为空格的Unicode值是20(十六进制)。

encodeURI()

encodeURI() 函数可把字符串作为 URI 进行编码。该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。该方法的目的是对 URI 进行完整的编码,因此对于 ;/?:@&=+$,# 这些在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的。

如果值包含多字节的字符,那么该字符将被“%HH”取代,即一个百分比符号和两个十六进制数字表示的字符串,字符编码为UTF-8。

encodeURIComponent()

encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

请注意 encodeURIComponent() 函数 与 encodeURI() 函数的区别之处,前者假定它的参数是 只是URI 的一部分(比如协议、主机名、路径或查询字符串),因此 encodeURIComponent() 函数将转义用于分隔 URI 各个部分的标点符号。

如果值包含多字节的字符,那么该字符将被“%HH”取代,即一个百分比符号和两个十六进制数字表示的字符串,字符编码为UTF-8。

为什么有时候JS的encodeURIComponent要连续用两次?

一般情况下,前端可以使用JS处理数据,encodeURIComponent(parmeName)+"="+encodeURIComponent(parmeValue),Java服务端接收时,  容器自动解码了, String paramValue = request.getParameter(paramName)。

encodeURIComponent 使用的是 UTF-8 字符编码来编的,如果 request.getParameter(paramName) 时,容器也按 UTF-8 解的话,结果就是正确的,根本无须在客户端进行二次的 encodeURIComponent。但是如果 request.getParameter(paramName)时容器没有按 UTF-8 解吗的话,就会乱码。容器按什么编码来解码,取决于 request.setCharacterEncoding()和servlet容器的配置(如Tomcat的Connector标签的URIEncoding属性)。

可以使用过滤器设置request.setCharacterEncoding("UTF-8"),并且 修改servlet容器配置(有的不用修改,默认就是UTF-8),让容器在解 GET 提交的参数时使用 UTF-8,这样客户端提交前就不用二次编码,服务端接收时也只要直接 request.getParameter(paramName) 即可。

为什么网上会有人提出在客户端对字符串重复编码两次呢?如果因为项目需要,不能指定容器使用何种编码规则来解码提交的参数。比如需要接收来自不同页面、不地编码的参数内容时,这个时候,在客户端对参数进行二次编码,可以有效的避开“提交多字节字符"的这个棘手问题。第一次编码,参数内容便不带有多字节字符了,成了纯粹的 Ascii 字符串。再编码一次,然后提交。接收时容器自动解一次(容器自动解的这一次,不管是按 GBK 、 UTF-8 还是 ISO-8859-1解码,都能够正确的得到结果),然后再在程序中实现一次 解码 (Java中通常使用 java.net.URLDecoder(***, "UTF-8")) 就可以得到提交的参数值。

最新文章

  1. ACM-ICPC退役选手的发言——满满的正能量(短视频)
  2. C# Gabbage Collecting System
  3. [转]tomcat中的session管理
  4. Ctrl+Shift+F12切换最大化编辑器
  5. POJ 3255 Roadblocks(A*求次短路)
  6. WCF中自定义消息编码器:压缩编码器的使用
  7. OTA(空中下载技术)
  8. tomcat maven book
  9. html5 canvas防微博旋转
  10. extjs 简单入门
  11. Java开发之File类
  12. ajax 请求二进制流 图片 文件 XMLHttpRequest 请求并处理二进制流数据 之最佳实践
  13. 【转】【可用】Android 登录判断器,登录成功后帮你准确跳转到目标activity
  14. 笔记 bug和任务 工具
  15. Hibernate执行流程和关系映射
  16. Vmware Vsphere WebService之vijava 开发一-vcenter连接、及集群信息获取
  17. React入门---JSX内置表达式-6
  18. jquery操作表格总结
  19. postman上传图片时已经添加cookie,但仍显示未登陆
  20. 网络编程一定要看过的socket大山

热门文章

  1. Three.js学习1_快速入门
  2. CobaltStrike与Metasploit联动配合
  3. Educational Codeforces Round 68 (Rated for Div. 2)-C-From S To T
  4. Black & White(尺取)
  5. 【python】迭代器与生成器到底是什么?看完你就知道
  6. 跟着兄弟连系统学习Linux-【day08】
  7. Netty进阶和实战
  8. pycharm安装模块方法
  9. sqli-labs 1-10关
  10. 什么是Lambda架构