【已解决】项目启动时报找不到log4j配置文件警告

项目使用slf4j日志框架+log4j实现,为了方便区分开发环境和生产环境,根据dev模式手动加载不同的log4j配置文件,开发环境打印控制台,生产环境打印日志文件,现在遇到一个问题,项目启动时会提示找不到log4j配置文件的警告,看着很不舒服,就是由于undertow中提前加载了log4j,造成在JfinalConfig中的configConstant方法配置的手动加载配置文件在启动时还未生效,所以产生了警告。

评论区

jounzhang

2019-02-20 11:45

JFinal

2019-02-20 11:58

你的 Filter 的时机太早,比 jfinal 初始化要早,所以会获取到 null

一个解决办法是使用 Handler 代替 Filter,第二个解决办法是想办法让 log 初始化的时机推后,例如做个 getLog 方法:
private Log getLog(...) {
if (log == null) {
log = ....;
}
return log;
}

注意看 JFinalFilter 中有一个 initLog() 方法,就是因为这个时机问题,该方法是便于 log 后续被初始化,多调试一下,了解流程

jounzhang

2019-02-20 15:48

@JFinal 你没理解到我的意思,我没有其他多余的filter,我是在JFinalConfig类中初始化常量的configConstant方法中根据devMode来选择加载的log4j配置文件的,但是项目一启动就会打印出警告,我看了源码,是因为在JfinalFilter中有个static的Log对象,在Log类中有个static块,里面就加载了log4j,就是在那报的警告。

我的核心代码就这一句:
PropertyConfigurator.configure(PathKit.getRootClassPath() + "/config/" + (SysConfig.isSysDevModel() ? "debug" : "release") + ".log4j.properties");

JFinal

2019-02-20 15:50

@jounzhang 大致也差不多,都是一个时机问题,时间有限每个贴子我只有 10 秒的时间去读

单步调试一下,利用 initLog() 这个机制应该可以解决

jounzhang

2019-02-20 17:29

@JFinal 终与找到最终凶手了,是undertow中使用了org.jboss.logging,在

com.jfinal.server.undertow.UndertowServer类
547行:di.setResourceManager(config.getResourceManager());

com.jfinal.server.undertow.UndertowConfig类
264行:return new ResourceManagerBuilder().build(resourcePath, getClassLoader());

com.jfinal.server.undertow.ResourceManagerBuilder类
49行:buildFileResourceManager(resourcePathList, classLoader, ret);
87行:ret.add(createFileResourceManager(path));

com.jfinal.server.undertow.ResourceManagerBuilder类
99行:return new FileResourceManager(new File(path), 1024, false);

用到了类
io.undertow.server.handlers.resource.FileResourceManager
该类继承自
io.undertow.server.handlers.resource.PathResourceManager
该类31行:private static final Logger log = Logger.getLogger(PathResourceManager.class.getName());
用到了
org.jboss.logging.Logger类
2465行:return LoggerProviders.PROVIDER.getLogger(name);
用到了
org.jboss.logging.LoggerProviders类
此类中有个static变量PROVIDER,该变量的初始化核心代码即尝试使用各种log框架,因为了项目引入了log4j所以匹配到了log4j,加载了log4j,log4j检查配置文件抛出了该警告。

由于包括jfinal在内的所有框架并没有固定使用某个log框架,所以是由于项目引入了log4j,log4j的配置文件也应该由项目提供,所以说都没有毛病。只需要在
UndertowServer.start(AppConfig.class);
运行前设置一个默认的log4j配置文件即可。

我在项目里面有两种方式可以解决:
1、使用默认的log4j配置文件位置resource根目录和默认配置文件名称log4j.properties
2、设置环境变量log4j.configuration指定配置文件:
System.setProperty("log4j.configuration","config/debug.log4j.properties");

最终我的解决方案为:
使用默认位置默认名称的配置文件作为开发配置,另外的名称为生产配置,在JfinalConfig类中初始化常量时,判断当不为开发模式时,主动加载生产配置:
if (SysConfig.isSysDevModel()) {
PropertyConfigurator.configure(PathKit.getRootClassPath() + "release.log4j.properties");
}

感谢波总,我应该坚持自己查找问题的根源而不急于“拿来主义”

热门反馈

扫码入社