启动Play Framework服务器时遇SLF4J依赖冲突错误求助
Play Framework项目SLF4J依赖冲突问题解决
项目依赖配置
"io.getquill" %% "quill-jdbc" % "4.3.0", "org.postgresql" % "postgresql" % "42.3.1", "com.h2database" % "h2" % "1.4.199", "org.tpolecat" %% "doobie-core" % DoobieVersion, "org.tpolecat" %% "doobie-postgres" % DoobieVersion, "org.tpolecat" %% "doobie-h2" % DoobieVersion, "org.tpolecat" %% "doobie-hikari" % DoobieVersion, "com.typesafe.play" %% "play-json" % "2.9.3", "com.typesafe.play" %% "play-json-joda" % "2.9.3", // 线程与流处理库 "io.monix" %% "monix-execution" % "3.4.0", "io.monix" %% "monix-reactive" % "3.4.1" exclude("org.typelevel", "cats-effect_2.13"), "org.typelevel" %% "cats-effect" % "3.5.1", // 测试库 "org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test, "org.specs2" %% "specs2-core" % "4.20.0" % Test, "org.scalacheck" %% "scalacheck" % "1.14.1" % Test
启动错误信息
SLF4J: No SLF4J providers were found. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details. SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8. SLF4J: Ignoring binding found at [jar:file:/home/joesan/.cache/coursier/v1/https/repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation. [error] java.lang.ClassCastException: class org.slf4j.helpers.NOPLoggerFactory cannot be cast to class ch.qos.logback.classic.LoggerContext (org.slf4j.helpers.NOPLoggerFactory and ch.qos.logback.classic.LoggerContext are in unnamed module of loader play.runsupport.NamedURLClassLoader @b900ff7) [error] at play.api.libs.logback.LogbackLoggerConfigurator.configure(LogbackLoggerConfigurator.scala:91) [error] at play.api.libs.logback.LogbackLoggerConfigurator.init(LogbackLoggerConfigurator.scala:31) [error] at play.core.server.DevServerStart$.$anonfun$mainDev$1(DevServerStart.scala:106) [error] at play.utils.Threads$.withContextClassLoader(Threads.scala:22) [error] at play.core.server.DevServerStart$.mainDev(DevServerStart.scala:76) [error] at play.core.server.DevServerStart$.mainDevHttpMode(DevServerStart.scala:50) [error] at play.core.server.DevServerStart.mainDevHttpMode(DevServerStart.scala) [error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [error] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [error] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [error] at java.base/java.lang.reflect.Method.invoke(Method.java:566) [error] at play.runsupport.Reloader$.startDevMode(Reloader.scala:306) [error] at play.sbt.run.PlayRun$.devModeServer$lzycompute$1(PlayRun.scala:100) [error] at play.sbt.run.PlayRun$.devModeServer$1(PlayRun.scala:83) [error] at play.sbt.run.PlayRun$.$anonfun$playRunTask$3(PlayRun.scala:107) [error] at play.sbt.run.PlayRun$.$anonfun$playRunTask$3$adapted(PlayRun.scala:67) [error] at scala.Function1.$anonfun$compose$1(Function1.scala:49) [error] stack trace is suppressed; run last Compile / run for the full output [error] (Compile / run) java.lang.reflect.InvocationTargetException [error] Total time: 1 s, completed Sep 6, 2023, 9:33:00 PM
sbt evicted执行结果
[warn] * org.slf4j:slf4j-api:2.0.7 is selected over {1.7.30, 1.7.36, 1.7.36, 1.7.36, 1.7.30, 2.0.0-alpha1, 1.7.25, 1.7.36, 1.7.36, 1.7.32} [warn] +- ch.qos.logback:logback-classic:1.4.11 (depends on 2.0.7) [warn] +- org.tpolecat:doobie-hikari_2.13:1.0.0-RC1 (depends on 1.7.32) [warn] +- org.slf4j:jul-to-slf4j:1.7.36 (depends on 1.7.36) [warn] +- org.slf4j:jcl-over-slf4j:1.7.36 (depends on 1.7.36) [warn] +- org.java-websocket:Java-WebSocket:1.4.0 (depends on 1.7.25) [warn] +- com.zaxxer:HikariCP:4.0.3 (depends on 2.0.0-alpha1) [warn] +- com.typesafe.scala-logging:scala-logging_2.13:3.9.4 (depends on 1.7.30) [warn] +- com.typesafe.play:play_2.13:2.8.19 (depends on 1.7.36) [warn] +- com.typesafe.akka:akka-slf4j_2.13:2.6.20 (depends on 1.7.36) [warn] +- com.typesafe.akka:akka-actor-typed_2.13:2.6.20 (depends on 1.7.36) [warn] +- com.openelectrons:ocpp-j-api_2.13:0.0.1-SNAPSHOT (depends on 1.7.30)
问题分析
从sbt evicted结果能看出,项目中slf4j-api被解析为2.0.7版本,但你使用的Play Framework 2.8.19依赖的是slf4j-api:1.7.36。SLF4J 2.x和1.x的日志绑定机制完全不同:
- SLF4J 1.x依赖
StaticLoggerBinder类绑定日志实现 - SLF4J 2.x改用ServiceLoader加载日志提供者
当前项目同时存在logback-classic:1.4.11(依赖slf4j-api 2.0.7)和Play自带的logback-classic:1.2.11(依赖slf4j-api 1.7.x)。SLF4J 2.x会忽略1.x的绑定实现,导致没有可用的日志提供者,最终使用NOPLoggerFactory。而Play的日志配置器试图将这个NOPLoggerFactory强制转换为Logback的LoggerContext,从而抛出ClassCastException。
解决方案
1. 强制统一slf4j-api版本为1.7.36
在build.sbt中添加强制依赖,确保所有模块都使用Play兼容的SLF4J版本:
libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.36" force()
2. 统一logback-classic版本为1.2.11
强制指定logback-classic版本,避免高版本logback引入不兼容的slf4j-api:
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.11" force()
3. 验证修复效果
执行以下命令清理并更新依赖,确认冲突已解决:
sbt clean update evicted
检查输出中slf4j-api的版本是否统一为1.7.36,且没有更高版本被选中。
4. 可选:排除冲突依赖
如果某个特定依赖引入了高版本的slf4j或logback,可以直接在该依赖上排除,比如针对doobie依赖:
"org.tpolecat" %% "doobie-hikari" % DoobieVersion exclude("org.slf4j", "slf4j-api")
不过强制版本的方式更直接,适合多依赖冲突的场景。
内容的提问来源于stack exchange,提问作者joesan
相关产品推荐
相关产品推荐

