url、get、post中的编码

1,697 阅读3分钟

这是《Java与MySQL字符集与编码》 第二篇。本篇主要是从请求的角度来看,主要有哪些编码问题,以及Java后端主要做了哪些设置来解码。

1 url 中的编码

我们先看一个例子:

在path 中,我们使用了 "testCharset中国" ,另外在参数中,extra字段我们也传入了汉字“中国2”。我们看到服务端能够很好地支持,并且返回结果中返回了emoji 表情。那么,有如下几个问题需要解释下:

  • url path中汉字转换是基于什么编码?选择这种编码的依据是?

如上图所示,“testCharset中国” 被转换成了“testCharset%E4%B8%AD%E5%9B%BD”,查了一下,这个编码是 UTF-8。 查了一下,如果没有设置相关的请求content-type, 则Chrome浏览器会默认以UTF-8进行编码。

插播一下:

查阅 URL 的编码规范 RFC3986 可知浏览器编码 URL 是将非 ASCII 字符按照某种编码格式编码成 16 进制数字然后将每个 16 进制表示的字节前加上“%”,所以最终的 URL 就成了上图的格式了。
  • url param中汉字转换是基于什么编码?选择这种编码的依据是?

param 中的参数,不同浏览器的默认编码不同,我这儿是Mac

Chrome

的配置,默认也是UTF-8编码。

  • 服务端是如何解码的?

客户端默认以UTF-8编码发送请求,那么服务端(我这儿主要是springboot 2 ,所以主要说springboot )是如何解码的呢?服务端主要依赖如下几个设置:


 spring.http.encoding.force=true
 spring.http.encoding.charset=UTF-8
 spring.http.encoding.enabled=true
 server.tomcat.uri-encoding=UTF-8

我搜了一下代码,发现服务端并没有设置这些,那为什么没有出现乱码呢?这是因为spring boot 默认设置这些变量为UTF-8了,所以不会有问题。那下面我们设置一下为GBK,看看会有什么结果?

再次请求一下http://localhost:8080/testCharset中国?itemId=112233445&extra=中国2, 发现报404了。

我们手改改为UTF-8

再来试下上面的请求,已经可以正常返回了。

这说明我们服务端设置的编码其作用了。

2 post 请求中的编码

上面的例子中,我们一直使用的是GET请求,那么post请求会有什么不一样的地方呢? 引用《深入分析 Java 中的中文编码问题》的一段描述。

POST 表单参数传递方式与 QueryString 不同,它是通过 HTTP 的 BODY 传递到服务端的。当我们在页面上点击 submit 按钮时浏览器首先将根据 ContentType 的 Charset 编码格式对表单填的参数进行编码然后提交到服务器端,在服务器端同样也是用 ContentType 中字符集进行解码。所以通过 POST 表单提交的参数一般不会出现问题,而且这个字符集编码是我们自己设置的,可以通过 request.setCharacterEncoding(charset) 来设置。

那我用postman 发送一个post请求来验证下。

发现也是可以正常请求的。 那我们再改下刚刚springboot 的设置再来看下。

发现404了。

spring boot 配置改回 UTF-8,就又可以正常返回了。

3 总结

本文在Mac上,使用Chrome浏览器、postman对get 和post 请求进行了包含中文的测试。对URL 中path、param以及body中的中英文进行测试,并对服务端spring boot 对编码的设置进行了测试。

4 参考文献

《一个字符集与编码的合集》,其中关于url编码的部分:

xiaogd.net/url-中的编码与乱码…

xiaogd.net/url-中的编码与乱码…

spring boot 如何很好地支持URL中包含汉字的请求: cloud.tencent.com/developer/a…

深入分析 Java 中的中文编码问题:

www.ibm.com/developerwo…