在配置tomcat8.5源码项目时, 启动tomcat后, 控制台出现部分中文乱码
日期部分的中文日志输出是正常的, 但是日志信息中的中文出现了乱码;
由于日期部分输出是正常的, 所以可以确定日志的编码是没问题的, 只是日志中局部内容出现了乱码, 有可能这些乱码是在程序运行中获取的配置文件中的中文信息; 那这些中文信息是什么? 为什么会乱码? 会不会是因为编译软件?
然后我重新下载了一个tomcat8.5.47的运行包, 在本地启动一下试试
可见通过startup.bat命令启动的日志是正常的
由此可以判断应该是编译软件的问题
从正常的日志信息也可以看出乱码的日志信息, 根据这些日志信息在tomcat项目中找到了相关的资源文件:
根据这些资源信息找到是在哪里调用读取了这些中文信息
versionLoggerListener.vm.vendor=JVM.供应商: {0}
public class VersionLoggerListener implements LifecycleListener {
private static final Log log = LogFactory.getLog(VersionLoggerListener.class);
protected static final StringManager sm = StringManager.getManager(Constants.Package);
private boolean logArgs = true;
private boolean logEnv = false;
private boolean logProps = false;
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
log();
}
}
private void log() {
log.info(sm.getString("versionLoggerListener.serverInfo.server.version",
ServerInfo.getServerInfo()));
log.info(sm.getString("versionLoggerListener.serverInfo.server.built",
ServerInfo.getServerBuilt()));
log.info(sm.getString("versionLoggerListener.serverInfo.server.number",
ServerInfo.getServerNumber()));
log.info(sm.getString("versionLoggerListener.os.name",
System.getProperty("os.name")));
log.info(sm.getString("versionLoggerListener.os.version",
System.getProperty("os.version")));
log.info(sm.getString("versionLoggerListener.os.arch",
System.getProperty("os.arch")));
log.info(sm.getString("versionLoggerListener.java.home",
System.getProperty("java.home")));
log.info(sm.getString("versionLoggerListener.vm.version",
System.getProperty("java.runtime.version")));
log.info(sm.getString("versionLoggerListener.vm.vendor",
System.getProperty("java.vm.vendor")));
log.info(sm.getString("versionLoggerListener.catalina.base",
System.getProperty("catalina.base")));
log.info(sm.getString("versionLoggerListener.catalina.home",
System.getProperty("catalina.home")));
if (logArgs) {
List args = ManagementFactory.getRuntimeMXBean().getInputArguments();
for (String arg : args) {
log.info(sm.getString("versionLoggerListener.arg", arg));
}
}
if (logEnv) {
SortedMap sortedMap = new TreeMap<>(System.getenv());
for (Map.Entry e : sortedMap.entrySet()) {
log.info(sm.getString("versionLoggerListener.env", e.getKey(), e.getValue()));
}
}
if (logProps) {
SortedMap sortedMap = new TreeMap<>();
for (Map.Entry
基本上可以确定就是在log()方法中, 通过sm.getString(..) 获取资源信息时,出现中文乱码
为什么会出现中文乱码呢?
因为在通过ResourceBundle进行国际化设置时, 资源文件必须是ISO-8859-1, 而Idea设置的编码格式是UTF-8, tomcat默认日志格式(logging.properties)也是UTF-8; ResourceBundle对于所有非西方语系的处理,都必须先将之转换为Java Unicode Escape格式。转换方法是通过JDK自带的工具native2ascii, 在解析过程中由于格式不匹配导致了乱码
详情参考这博客: Tomcat中的ResourceBundle国际化解析
将所有的资源文件中的中文信息转换为Unicode存储
versionLoggerListener.vm.vendor=JVM.供应商: {0}
versionLoggerListener.vm.version=JVM 版本: {0}
转换为:
versionLoggerListener.vm.vendor=\u004a\u0056\u004d\u002e\u4f9b\u5e94\u5546: {0}
versionLoggerListener.vm.version=\u004a\u0056\u004d\u0020\u7248\u672c: {0}
在转为unicode编码后, 在获取资源信息时不会出现乱码
注意: 要替换所有含有中文的资源文件
(1) 删除所有的中文资源文件, 在查找不到对应国际化资源文件时会使用默认的资源文件(English)
(2) 或者修改源码在StringManager获取本地语言时, 不论获取到的语言是什么都设置为英语
由于定位器Localizer中未指定语言, 在ResourceBundle.getBundle()时才去查询, 所以进行修改, 直接指定语言
把所有文件的编码格式统一......
该方案笔者还没有实验成功,希望有大佬指点一下
欢迎补充. . . 哈哈