这是《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编码的部分:
spring boot 如何很好地支持URL中包含汉字的请求: cloud.tencent.com/developer/a…
深入分析 Java 中的中文编码问题: