为什么要URL编码

  • 在因特网上传送URL,只能采用ASCII字符集

也就是说URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号,即
只有字母和数字[0-9a-zA-Z]、一些特殊符号$-_.+!‘()[不包括双引号]、以及某些保留字(空格转换为+),才可以不经过编码直接用于URL**

这意味着 如果URL中有汉字,就必须编码后使用。 但是麻烦的是 标准的国际组织并没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。 这导致”URL编码”成为了一个混乱的领域。
  
如果包含中文,其实会自动编码的,比如Chrome和火狐,”文”和”章”的utf-8编码分别是”E6 96 87”和”E7 AB A0” ,下图所示的”%e6%96%87%e7%ab%a0”就是按照顺序,在每个字节前加上%而得到的:

1610803599411.png

但是不同的浏览器可能会有不同的编码方式,不要将编码交给浏览器。应该用JS在前端对URL编码,这样就实现了统一

  • 如果key=value这种传参方式中,value中包含?``=或者&等符号,url的解析会变得很困难
  • 不同的操作系统、浏览器、不同的网页字符集(charset)有不同的默认编码方式,要有一个统一格式来发送url

如何编码

URL编码通常也被称为百分号编码(percent-encoding),是因为它的编码方式非常简单:
使用%加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式。URL编码要做的,就是将每一个非安全的ASCII字符都被替换为“%xx”格式,

对于非ASCII字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。

如”中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到”%E4%B8%AD%E6%96%87”。

一些常见的特殊字符换成相应的十六进制的值:

  1. + %20
  2. / %2F
  3. ? %3F
  4. % %25
  5. # %23
  6. & %26

JS的三种编码函数

上面说了编码方式的混乱,那么如何统一呢?

使用Javascript先对URL编码,或者将可以在后台编码的参数编码后再发送给前端使用。然后再向服务器提交,不要给浏览器插手的机会,这样就能保证客户端只用一种编码方法向服务器发出请求

escape

js中编码出生最早的一个,不提倡使用,真正作用是:

返回一个字符的Unicode编码值,为的是方便他们能在所有计算机上可读,规则:
所有空格、标点以及其他非ASCII字符都用%xx编码替换; 例如空格返回的是%20 字符值大于255的字符以%uxxxx格式储存

encodeURI函数(推荐使用)

这个函数才是javascript中真正用来对URL编码的函数

它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号”; / ? : @ & = + $ , #”,也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。

需要注意的是,它不对单引号’编码

它对应的解码函数是decodeURI()。

规则就是我上面第二部分所说的,采用utf-8编码。比如:
1610803599434.png

encodeURIComponent函数(推荐使用)

与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。

因此,”; / ? : @ & = + $ , #”,这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码,具体的编码规则是和encodeURI函数是一样的
它对应的解码函数是decodeURIComponent()。

实验:
利用chrome的开发者工具:
1610803599472.png
可以看到第一种,对需要url编码的部分用encodeURIComponent函数,其他部分不编码符合要求,即对需要编码的参数用encodeURIComponent函数最推荐

java解码

JS中用encodeURIComponent编码,后台JAVA怎么解码

后端

  1. String decode = URLDecoder.decode(searchParam.getQuery(), "UTF-8");

前端

let search = Object.assign({},searchParam)
let query = encodeURIComponent(search.query)
search.query = query