運(yùn)行環(huán)境:Windows 10 茎用;IDEA-2019.3遣总;Tomcat 9.0.24;jdk 1.8.0_221轨功;
問(wèn)題切入
我在idea中開(kāi)發(fā)ssm框架的項(xiàng)目旭斥,然后直接在集成的tomat中運(yùn)行,其他日志都是正常顯示古涧,唯獨(dú)mybatis的參數(shù)日志中文亂碼垂券。
上面就是我遇到的具體亂碼問(wèn)題場(chǎng)景。從這個(gè)問(wèn)題的出現(xiàn)羡滑,以及我解決的過(guò)程菇爪。讓我有了寫這篇文章的動(dòng)機(jī)算芯。
中文亂碼,是我們這些中文世界的程序員常見(jiàn)到想吐的問(wèn)題凳宙。發(fā)生的頻率如此頻繁熙揍。解決的方式也是如此碰運(yùn)氣。讓我也是很氣餒氏涩。每一次遇到中文亂碼诈嘿,就像遇到一個(gè)新問(wèn)題,你不知道是哪個(gè)環(huán)節(jié)出了問(wèn)題削葱,你也不知道需要怎樣的配置解決奖亚。全靠百度搜索,碰運(yùn)氣解決析砸。
我思考了一通昔字,嘗試做個(gè)記錄,盡量去發(fā)現(xiàn)解決的通用邏輯首繁。
解決亂碼問(wèn)題作郭,我想要通過(guò)這么幾步,首先弦疮,要明白編碼/解碼原理夹攒;其次,要知道所有環(huán)節(jié)的默認(rèn)編碼胁塞;最后咏尝,要知道解決問(wèn)題的配置方式的含義。
我也要按這個(gè)思路來(lái)梳理啸罢。
亂碼底層原理分析
畫了個(gè)簡(jiǎn)單的圖编检,如上面,正常情況下扰才,解碼和編碼的過(guò)程中都要使用一致的編碼格式允懂。
如果發(fā)生亂碼,考慮存在以下問(wèn)題:
- 編碼和解碼的格式不一致衩匣。
- 編碼時(shí)使用的編碼格式不支持字符蕾总,當(dāng)時(shí)就亂碼了。解碼時(shí)琅捏,使用一致的編碼格式生百,也會(huì)亂碼。
如果發(fā)生亂碼午绳,就要從上面的兩種情況去考慮解決了置侍。
所有環(huán)節(jié)的默認(rèn)編碼
這里,也是亂碼問(wèn)題最難解決的問(wèn)題關(guān)鍵所在。因?yàn)槔唬S著軟件工業(yè)的發(fā)展杠输,封裝越來(lái)越厲害。終端使用者秕衙,根本不能知道終端使用之前蠢甲,經(jīng)歷了多少個(gè)環(huán)節(jié)的編碼和解碼過(guò)程。所以据忘,你去解決亂碼問(wèn)題鹦牛,也只能是丈二和尚摸不著頭腦了。
我這里也只能慢慢的窮舉我知道的環(huán)節(jié)的默認(rèn)編碼勇吊。
- windows系統(tǒng)默認(rèn)編碼 : GBK
這也是很多亂碼的源泉曼追。程序員都在說(shuō)要推進(jìn)統(tǒng)一編碼格式UTF-8『汗妫可是系統(tǒng)級(jí)別也沒(méi)有使用UTF-8呀礼殊。 - Java文件編譯后形成class默認(rèn)編碼:UTF-16編碼
- JVM中的默認(rèn)編碼:受平臺(tái),配置影響针史。
- idea開(kāi)發(fā)工具默認(rèn)編碼:idea本質(zhì)也是一個(gè)java應(yīng)用晶伦,還是遵循JVM的編碼設(shè)置規(guī)則。
- tomcat服務(wù)器默認(rèn)編碼:tomcat本質(zhì)也是一個(gè)java的應(yīng)用啄枕,還是遵循JVM的編碼設(shè)置規(guī)則婚陪。
- 源碼文件默認(rèn)編碼:根據(jù)自己設(shè)定。
配置參數(shù)含義
-Dfile.encoding=UTF-8
-Dfile.encoding 解釋:
在命令行中輸入 java频祝,在給出的提示中會(huì)出現(xiàn) -D 的說(shuō)明:
-D<name>=<value> # set a system property
-D 后面需要跟一個(gè)鍵值對(duì)泌参,作用是設(shè)置一項(xiàng)系統(tǒng)屬性
對(duì) -Dfile.encoding=UTF-8 來(lái)說(shuō)就是設(shè)置系統(tǒng)屬性 file.encoding 為 UTF-8
那么 file.encoding 什么意思?字面意思為文件編碼智润。
搜索 java 源碼及舍,只能找到 4 個(gè)文件中包含 file.encoding 的文件未辆,
也就是說(shuō)窟绷,只有四個(gè)文件調(diào)用了 file.encoding 這個(gè)屬性。
在 java.nio.charset 包中的 Charset.java 中咐柜,這段話的意思說(shuō)的很明確了兼蜈。
簡(jiǎn)單說(shuō)就是默認(rèn)字符集是在 java 虛擬機(jī)啟動(dòng)時(shí)決定的,
依賴于 java 虛擬機(jī)所在的操作系統(tǒng)的區(qū)域以及字符集拙友。
代碼中可以看到为狸,默認(rèn)字符集就是從 file.encoding 這個(gè)屬性中獲取的。
-
idea集成tomcat后遗契,tomcat的編碼設(shè)置
image.png -
idea工具的編碼設(shè)置
image.png
總結(jié)
我力圖去理解亂碼的問(wèn)題解決辐棒,我后續(xù)還會(huì)繼續(xù)充實(shí)此文。或者漾根,隨著我對(duì)編碼的理解加深泰涂,也會(huì)推翻現(xiàn)在的邏輯。
附錄:
有些段落引用自:http://yang3wei.github.io/blog/2013/02/10/java-dfile-dot-encoding-equals-utf-8-gan-diao-luan-ma/