为何我的Java项目中SLF4J无法找到任何日志提供者?
问题分析与解决方案
你遇到的SLF4J错误核心是运行时classpath里缺少SLF4J的实现类——要么是依赖没正确引入,要么是打包成uberJar时没把这些依赖包含进去。结合你的项目使用自定义fetchdeps.pl脚本+Gradle uberJar的情况,问题大概率出在依赖管理和打包配置环节,以下是分步解决指南:
一、彻底清理旧依赖
- 删除项目内所有旧版Log4J 1.x(如
log4j-1.2.*.jar)和旧版SLF4J(如slf4j-api-1.x.*.jar、slf4j-log4j12-*.jar)文件,确保无遗留。 - 打开
default.deps文件,删除所有与Log4J 1、旧SLF4J相关的行,后续改用Gradle管理日志依赖(更可靠)。
二、用Gradle声明日志依赖(替代手动下载)
手动下载Jar包容易出现版本不兼容或缺失问题,直接在Gradle里配置依赖更稳妥:
找到子项目PygmyMarmosetLauncher的build.gradle文件,添加以下依赖配置:
dependencies { // SLF4J API 核心 implementation 'org.slf4j:slf4j-api:2.0.7' // Log4J2 核心 + SLF4J绑定(将SLF4J日志转至Log4J2处理) implementation 'org.apache.logging.log4j:log4j-core:2.20.0' implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.20.0' }
如果fetchdeps.pl还负责其他非日志依赖的下载,保留脚本但删除其中日志相关的下载逻辑,后续依赖由Gradle自动拉取。
三、确保UberJar打包时包含所有依赖
默认的uberJar任务可能未正确打包依赖,需调整Gradle配置确保SLF4J实现类被包含:
在子项目的build.gradle中修改uberJar任务:
task uberJar(type: Jar) { // 保留原有配置(如mainClass设置) from sourceSets.main.output // 打包所有运行时依赖 from { configurations.runtimeClasspath.findAll { it.name.endsWith('.jar') }.collect { zipTree(it) } } // 避免META-INF文件重复冲突 duplicatesStrategy = DuplicatesStrategy.EXCLUDE }
如果已有uberJar配置,检查是否引用了configurations.runtimeClasspath,确保所有依赖都被打包。
四、配置Log4J2滚动日志
将log4j2.properties放在PygmyMarmosetLauncher/src/main/resources目录下(Gradle会自动将其打包进Jar),以下是每日滚动日志的示例配置:
status = warn name = PropertiesConfig appenders = console, rolling # 控制台输出 appender.console.type = Console appender.console.name = STDOUT appender.console.layout.type = PatternLayout appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n # 每日滚动文件输出 appender.rolling.type = RollingFile appender.rolling.name = RollingFile appender.rolling.fileName = logs/app.log appender.rolling.filePattern = logs/app-%d{yyyy-MM-dd}.log.gz appender.rolling.layout.type = PatternLayout appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n appender.rolling.policies.type = Policies appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.interval = 1 appender.rolling.policies.time.modulate = true # 自定义包日志级别 logger.file.name = com.yourpackage # 替换为UberjarDaemon所在的包名 logger.file.level = info logger.file.appenderRefs = rolling logger.file.appenderRef.rolling.ref = RollingFile # 根日志配置 rootLogger.level = info rootLogger.appenderRefs = console rootLogger.appenderRef.console.ref = STDOUT
五、测试构建与运行
- 清理旧构建文件:
gradle clean - 构建UberJar:
gradle uberJar - 运行生成的Jar文件,检查SLF4J错误是否消失,同时查看
logs目录是否生成滚动日志文件。
若想先测试SLF4J SimpleLogger
只需将Gradle依赖替换为:
dependencies { implementation 'org.slf4j:slf4j-api:2.0.7' implementation 'org.slf4j:slf4j-simple:2.0.7' }
同样确保UberJar包含这两个依赖,运行时即可用SimpleLogger输出日志。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

