Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)

在配置tomcat8.5源码项目时, 启动tomcat后, 控制台出现部分中文乱码

Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)_第1张图片

日期部分的中文日志输出是正常的,  但是日志信息中的中文出现了乱码;

由于日期部分输出是正常的, 所以可以确定日志的编码是没问题的, 只是日志中局部内容出现了乱码, 有可能这些乱码是在程序运行中获取的配置文件中的中文信息;  那这些中文信息是什么? 为什么会乱码? 会不会是因为编译软件?

然后我重新下载了一个tomcat8.5.47的运行包, 在本地启动一下试试

Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)_第2张图片

可见通过startup.bat命令启动的日志是正常的

由此可以判断应该是编译软件的问题

从正常的日志信息也可以看出乱码的日志信息, 根据这些日志信息在tomcat项目中找到了相关的资源文件:

Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)_第3张图片

根据这些资源信息找到是在哪里调用读取了这些中文信息

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 e : System.getProperties().entrySet()) {
                sortedMap.put(String.valueOf(e.getKey()), String.valueOf(e.getValue()));
            }
            for (Map.Entry e : sortedMap.entrySet()) {
                log.info(sm.getString("versionLoggerListener.prop", e.getKey(), e.getValue()));
            }
        }
    }
}

基本上可以确定就是在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获取本地语言时, 不论获取到的语言是什么都设置为英语

Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)_第4张图片

由于定位器Localizer中未指定语言, 在ResourceBundle.getBundle()时才去查询, 所以进行修改, 直接指定语言

Idea中tomcat8启动时控制台日志中出现部分乱码(tomcat国际化处理乱码)_第5张图片

 

解决方案(日志为中文)三

把所有文件的编码格式统一......

 

该方案笔者还没有实验成功,希望有大佬指点一下 

 欢迎补充. . . 哈哈

 

 

 

 

 

 

 

 

你可能感兴趣的:(Tomcat源码解析)