ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Tomcat启动中文乱码:从编码原理到彻底解决指南

Tomcat启动中文乱码:从编码原理到彻底解决指南 讲真Tomcat启动时cmd窗口中文乱码这个问题十个人里有八个都遇到过。新手第一次解压Tomcat、跑startup.bat窗口里冒出一堆“鈥斺€斺€??”或者“淇℃伅”这种完全看不懂的乱码第一反应往往是慌是不是环境坏了是不是安装包有问题其实真不怪你这是Tomcat这个Java应用服务器和Windows中文系统之间一个非常经典的编码冲突本质就一句话Tomcat从8.5版本开始默认用UTF-8往控制台输出日志而Windows cmd窗口默认还用着GBK代码页936来解码显示两边对不上中文自然就变成了一堆问号、菱形和莫名奇妙的符号。这篇文章适合所有在Windows上用Tomcat做开发或部署的朋友不管你是刚配好Tomcat还没跑起来的新手还是被这个乱码问题烦了很久但一直没深究的老开发都可以在这里找到彻底解决的方案。我会从编码原理讲起再把市面上常见的几种解决方法改cmd代码页、改Tomcat日志编码、改JVM参数、改IDEA控制台设置全部拆开揉碎配合实操步骤和踩坑提醒确保你看完能根据自己场景选对方案一次搞定。1. 乱码根源Tomcat启动时中文乱码到底是怎么来的要解决问题先得搞清楚乱码是怎么产生的。这里的核心概念叫“编码/解码不一致”理解它之后后面所有配置修改你都会觉得理所当然而不是背步骤。1.1 三分钟搞懂编码体系GBK、UTF-8、代码页计算机底层只认二进制中文要想显示出来必须有一套规则把“汉字”映射成“二进制数字”。Windows中文版默认使用GBK编码也就是一个汉字占两个字节而Linux、macOS以及现在几乎所有国际通用软件默认使用UTF-8编码一个汉字占三到四个字节具体看字符范围。关键就在这同一串中文字符用UTF-8编码出来的字节序列和用GBK编码出来的字节序列完全不一样。那什么叫乱码呢说白了就是——发送方用A编码规则把文字变成字节接收方却用B编码规则把字节反解成文字。两边对不上屏幕上的字符自然就歪了。Windows cmd窗口里有个概念叫“代码页”Code Page你可以把它理解为“cmd窗口当前使用哪套字符编码规则”的开关。用chcp命令可以查看当前代码页chcp我的Windows中文版输出一般是活动代码页: 936936就是GBK。如果你执行后看到65001那说明你的cmd已经切到了UTF-8。Tomcat启动时乱码的直接原因就是Tomcat向stdout输出UTF-8编码的日志内容而cmd用GBK解码两套规则对不上。1.2 Tomcat从8.5开始的“编码转向”不知道你有没有发现Tomcat 7及以前的版本在Windows cmd窗口启动时乱码并不明显真正乱码大规模出现是Tomcat 8.5之后。原因很简单Tomcat 8.5对日志系统做了一次调整默认字符集从系统默认字符集Windows下就是GBK改成了UTF-8。这个改动在国际化上是好事——UTF-8能表示全世界所有字符部署到Linux服务器上日志不会乱码。但在Windows中文系统上就尴尬了Tomcat认为自己在说“普通话”UTF-8cmd窗口却只会听“粤语”GBK两边各说各的结果全是乱码。1.3 先判断乱码类型再决定改哪里很多人一上来就各种改改完发现没用原因是没分清自己到底是哪种乱码。我总结下来主要有三类cmd窗口里启动日志乱码但Tomcat目录下的logs文件夹里catalina*.log日志文件打开是正常中文。cmd窗口和日志文件全部乱码。在IDE比如IDEA、Eclipse里启动Tomcat乱码但单独双击startup.bat启动没事。这三种的病因和解决方案侧重点完全不同。第一种是单纯的cmd解码问题改控制台代码页即可第二种说明Tomcat的JVM文件编码和日志输出的编码链条都出了问题需要动Tomcat配置第三种多半是IDE自身控制台编码设置覆盖了系统默认需要在IDE里单独配置。所以动手前建议你先按这个顺序排查先打开Tomcat安装目录下logs文件夹里的catalina.日期.log文件用记事本看看中文是否正常。如果日志文件正常那问题基本锁定在cmd窗口显示环节如果日志文件也乱码那就要往Tomcat配置层面深挖了。2. 最直接的方案用chcp切换cmd窗口代码页如果你只想“先让眼前不乱码”不想动Tomcat任何配置那这个方案最合适用时一分钟。2.1 chcp 65001的原理与操作前面说了cmd窗口默认代码页是936GBK我们把它切成65001UTF-8就能让cmd窗口用UTF-8解码Tomcat输出的日志。操作很简单先正常启动Tomcat让它处于乱码状态然后在新开的cmd窗口里执行chcp 65001不过这有个问题chcp只对执行它的那个cmd窗口生效。意思是你得在启动Tomcat的那个cmd窗口里执行才有用。但Tomcat启动后那个窗口在被日志刷屏你怎么执行命令实际上常用的操作顺序是先打开一个干净的cmd窗口执行chcp 65001然后再到切换后的窗口里运行startup.bat。这样Tomcat输出的UTF-8日志在UTF-8代码页的cmd窗口里就能正常解码了。推荐自己动手试一次你会直观感受到代码页切换前后同一个日志内容从乱码变正常的全过程。2.2 让cmd窗口永久默认UTF-8两个技巧每次开cmd都要手动敲一次chcp太烦了有两个办法可以让cmd窗口“记住”65001这个代码页。第一个办法是改注册表。按下WinR输入regedit定位到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor在右侧新建一个字符串值数值名称填“Autorun”数值数据填“chcp 65001 nul”。这样之后每次打开cmd窗口都会自动执行一次chcp 65001。注意右下角的“nul”一定要带否则每次开局会多打印一行“活动代码页: 65001”虽然不影响使用但看着不够清爽。第二个办法是改cmd窗口的默认属性。打开cmd窗口后右键窗口标题栏进入“属性” - “选项”标签页把“当前代码页”从“936 (ANSI/OEM - 简体中文 GBK)”修改为“65001 (UTF-8)”。这个方式适用于自己的电脑如果你是公司电脑被组策略限制了注册表写入用这个方法也行。2.3 chcp方案的两个局限必须提醒你chcp方案虽然快但有两个明显短板。第一个它只影响cmd窗口的解码不会改变Tomcat实际往日志文件里写入的编码格式。日志文件该是UTF-8还是UTF-8你在cmd窗口看着正常只是在“翻译”层面纠正了显示问题并没有根治文件编码本身。第二个如果你在公司或者团队协作环境同事各自的cmd窗口可能设置了不同的默认代码页有的936有的65001代码页不一致会导致同一个Tomcat在不同人电脑上表现不同排查问题时容易互相干扰。所以我个人的建议是chcp方案适合应急如果你想一劳永逸还是继续往下看。3. 推荐方案改Tomcat自带的logging.properties如果说chcp是“临时翻译”那修改Tomcat的logging.properties就是“让Tomcat说中文系统能听懂的话”。这也是多数技术社区公认的最稳妥、影响面最小的方案。3.1 logging.properties里哪个配置在起作用Tomcat的日志系统基于java.util.logging组件配置文件位于Tomcat安装目录下的conf/logging.properties。这里面和乱码直接相关的配置是这个java.util.logging.ConsoleHandler.encoding UTF-8这句的意思是说控制台输出处理器ConsoleHandler将使用UTF-8编码来输出日志。Tomcat 8.5之后默认值就是UTF-8。在我们中文Windows环境下cmd窗口用的是GBK所以你会看到如下经典乱码鈥斺€斺€?mer????????????解决办法其实特别简单把它改成GBK就行。3.2 详细修改步骤用记事本或任意文本编辑器打开conf/logging.properties找到这一行java.util.logging.ConsoleHandler.encoding UTF-8改成java.util.logging.ConsoleHandler.encoding GBK如果你打开文件后找不到这行也可以直接在第一行注释下添加这句。保存文件后重启Tomcat乱码就消失了。这个修改只影响控制台Handler的编码不影响日志文件HandlerFileHandler的写入编码。日志文件那边有专门的配置比如1catalina.org.apache.juli.AsyncFileHandler.encoding UTF-8正常情况下不需要改让日志文件保持UTF-8对后续在Linux服务器上排查问题更有利。3.3 改完之后有些细节要注意首先修改后一定要重启Tomcat而且是完整地停止再启动不是关掉窗口就行。因为logging.properties只在启动时加载一次。其次改完logging.properties后如果用的是双击startup.bat方式启动乱码应该已经解决。但如果是在IDEA里启动可能仍然乱码这需要单独配置IDEA控制台编码这部分我在第五部分会详细讲。还有一个容易忽略的小坑GBK并不覆盖所有生僻字如果Tomcat日志里出现了GBK字符集以外的字符比如某些特殊符号控制台依然会显示问号。不过对绝大多数人的日志内容来说GBK完全够用。4. 进阶方案通过catalina.bat或setenv.bat设置JVM默认编码前面两个方案都是在“显示”或者“日志处理器”层面解决问题。还有一个角度是直接改JVM的默认字符集也就是让Java运行环境本身在Tomcat启动时就用统一的编码来做所有转换。4.1 file.encoding参数到底管什么JVM层面有个参数叫file.encoding它决定了Java里FileReader、OutputStreamWriter这些没有显式指定编码的IO操作默认使用什么字符集。在Windows中文系统上JVM默认的file.encoding其实是GBK跟随系统区域设置但如果你的Tomcat或某些依赖包在启动时把file.encoding改成了UTF-8就可能出现文件读写、控制台输出等多个环节编码紊乱。Tomcat启动时读取catalina.bat如果这个文件里加了JAVA_OPTS传递给Java虚拟机的启动参数最终也会在这里体现。通过手动把file.encoding指定为UTF-8能让JVM在多个环节保持同一个编码从源头上减少“某个环节偷偷切编码”导致的乱码。4.2 两种修改JVM参数的方式Tomcat很贴心地准备了一个专门的自定义位置bin目录下的setenv.bat。这个文件默认不存在需要自己创建。如果有这个文件Tomcat启动时会自动执行它。这样有个好处升级Tomcat不会丢失你的个性化设置因为catalina.bat升级时会被覆盖而setenv.bat不会。在bin目录下新建setenv.bat用文本编辑器写入set JAVA_OPTS%JAVA_OPTS% -Dfile.encodingUTF-8保存后重启Tomcat。如果你只想快速验证不想建新文件也可以直接修改bin/catalina.bat在文件靠近开头的位置找到set JAVA_OPTS这类行在合适位置追加相同的参数。需要注意文件里如果有中文保存setenv.bat时务必确认编码是ANSI记事本默认就是ANSI否则Windows批处理文件可能解析出错。4.3 什么时候必须用JVM参数方案这个方案最典型的应用场景是你已经改了logging.properties乱码好了但后面在Tomcat里部署了一个Web应用应用自身用System.out打印中文日志打印出来还是乱码。这往往是应用代码里没有显式指定编码吃了JVM的file.encoding默认值。这时候光调Tomcat日志不够JVM层面的统一设置是必不可少的。另外一个场景是Tomcat日志文件本身乱码。前面说了日志文件默认UTF-8如果你发现catalina日志文件在记事本里中文也是乱码说明Tomcat的FileHandler在写文件时使用的编码与文件读取工具不一致通过JVM参数强制全局UTF-8也可能顺带解决这类问题。5. IDEA场景专用Eclipse与IDEA里Tomcat控制台乱码很多朋友平时开发不是用startup.bat启动而是直接在IDEA或者Eclipse里配置Tomcat后点绿色三角启动。这个场景下前面两个方案不一定管用因为IDE的控制台有自己独立的编码设置。5.1 IDEA与cmd环境下的乱码有什么区别在cmd窗口里跑startup.bat输出链路是Tomcat - cmd窗口在IDEA里点启动输出链路是Tomcat - IDEA控制台 - 屏幕。IDEA控制台本身也是个解码器它的解码逻辑不一定跟随cmd窗口代码页。所以会出现一种情况cmd窗口已经正常了IDEA里却还是乱码或者反过来说IDEA里正常了cmd里又是乱码。两者要分开处理。IDEA默认情况下会用自己设置的字符集去读取Tomcat输出的字节流大多数情况下默认是UTF-8所以理论上编码是通的。但IDEA所在电脑的操作系统区域设置、IDEA的版本、以及IDEA全局编码配置都可能导致它不按UTF-8读取。5.2 IDEA编码配置三件套IDEA里设置编码主要看三处第一处是全局编码设置。打开File - Settings - Editor - File Encodings把Global Encoding和Project Encoding都设置为UTF-8Properties Files的Default encoding for properties files也改成UTF-8底部勾选Transparent native-to-ascii conversion。第二处是VM参数设置。在Run/Debug Configurations里找到你的Tomcat配置在VM options栏追加-Dfile.encodingUTF-8第三处是IDEA的安装目录bin下的idea64.exe.vmoptions文件在末尾加上-Dfile.encodingUTF-8这个主要解决IDEA自身进程的编码问题不是所有版本都必须但加了能减少一部分莫名其妙的乱码。5.3 Eclipse里的对照设置Eclipse用户通常在Run Configurations - Tomcat Server - Arguments标签页的VM arguments里加上-Dfile.encodingUTF-8然后在Window - Preferences - General - Workspace - Text file encoding里改成UTF-8。Eclipse控制台本身的编码设置比较直接改完这两处基本可以解决。无论是IDEA还是Eclipse设置完成后都需要重启IDE而且要让Tomcat彻底停止后再启动否则控制台显示可能还是缓存了旧配置。6. 常见问题与排查技巧实录这部分把你实际动手时可能碰到的高频坑按“问题-原因-解决”整理成速查表形式方便你遇到问题直接对号入座。6.1 乱码排查速查表症状直接原因首选解决方案cmd启动乱码日志文件正常cmd代码页936与Tomcat UTF-8输出不匹配chcp 65001或改logging.properties为GBKcmd启动乱码日志文件也乱码JVM file.encoding或日志FileHandler编码异常setenv.bat设置-Dfile.encodingUTF-8并检查日志编码IDEA里乱码cmd单独启动正常IDEA控制台编码与Tomcat输出编码不一致IDEA File Encodings设为UTF-8VM options加-Dfile.encodingUTF-8修改logging.properties后窗口中文变问号某些特殊符号超过GBK字符集范围尝试改回UTF-8改用chcp 65001方案部署应用System.out输出乱码应用未显式指定编码被系统默认GBK影响setenv.bat全局指定-Dfile.encodingUTF-8Windows系统区域里勾选了Beta版UTF-8后其他软件乱码系统级代码页被全局改成65001取消勾选回归逐应用配置6.2 踩坑记录改了一处仍然乱码怎么办我见过最多的情况是朋友只改了IDEA的File Encodings看着没变化就以为方案没用。其实是因为IDEA启动Tomcat时走的是Tomcat的catalina脚本Tomcat的ConsoleHandler编码还是默认的UTF-8IDEA控制台却因为某些原因用GBK解码两边又对不上了。正确思路是先确认日志文件本身是否正常再用chcp验证cmd窗口在65001下是否正常最后才轮到IDE控制台设置。如果所有方案都试了还乱码还有一个经常被忽略的地方运行Tomcat的JDK本身如果是修改过的非官方发行版它的默认字符集行为可能与标准JDK不同。建议统一使用官方OpenJDK或OracleJDK并在启动时打印一下file.encoding验证java -XshowSettings:properties -version看输出中file.encoding一行的值能帮你确认JVM当前认为的默认编码到底是什么。6.3 我的建议日常配置和临时应急怎么取舍最后分享一点我个人的实践心得。如果你是本地开发我推荐“logging.properties改GBK setenv.bat设UTF-8”这个组合前者快速解决cmd显示后者保证JVM在读写文件、System.out输出时有一个统一的UTF-8基调不易出幺蛾子。如果你是维护线上Linux服务器那保持原始配置不动日志文件用UTF-8通过tail或less方式查看才是正路。应急时用chcp临时切一下长期用还是要把编码“说清楚”。另外不管用哪个方案改完配置重启Tomcat后都先看一眼第一屏日志确认“信息”这两个字不再是“淇℃伇”再走别边启动边做别的事等回来看见乱码又得从头排查。
返回列表