【问题标题】:Baffled by Java Logging Systems with Spring and Hibernate对使用 Spring 和 Hibernate 的 Java 日志系统感到困惑
【发布时间】:2011-01-07 23:21:33
【问题描述】:

在部署我的 Spring / Hibernate 应用程序时,我收到以下与日志记录相关的警告:

log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.

令我惊讶的是,Google/SO 搜索中缺少信息。唯一相关的是这个 SO 帖子 Problem with Commons Logging / Log4j setup in spring webapp with tomcat 6

但是,这甚至超出了我的范围。有人可以在这里澄清正在使用的日志系统,或者指向我关于此事的最近资源(有一些古老的谷歌搜索结果并不真正适用)。具体来说,我正在努力解决的问题是:

  • commons-logging、log4j、slf4j 和 JCL 的区别。我的理解是 slf4j 是一个包装器,而 commons-logging 和 log4j 是实际的实现。我不知道 JCL 适合哪里。

  • 如何为 Spring 配置日志记录。 web.xml 文件中有什么,我需要 log4j.properties 文件还是 log4j.xml 文件?在 WEB-INF 中它在哪里?我的 applicationContext.xml 文件中有什么内容吗? (对不起,我需要从零开始)。

  • 我在我的项目中使用 Hibernate,包括通过 Maven。似乎 Hibernate 使用 slf4j-simple。我看到警告说我不能在类路径上同时拥有 slf4j-simple 和 slf4j-log4j。我没有包含 slf4j-log4j 作为依赖项,但 Hibernate 必须包含它。我该如何解决这个问题?我可以强制 Hibernate 使用 log4j 吗?

任何帮助将不胜感激。谢谢。


编辑:

感谢到目前为止的所有答案。我正在尝试这些建议。 spring web-app 具体怎么样?我已经看到了侦听器和参数的示例以及放入 web.xml 文件中的内容。这也需要吗?

【问题讨论】:

    标签: java hibernate spring logging log4j


    【解决方案1】:
    • commons-loggingSLF4J 都是围绕其他日志记录实现的 API 包装器。 SLF4J 是两者中更现代的,而且功能更强大。 Log4j 是一个日志实现,几乎是事实上的标准。 JULjava.util.logging 的缩写)是 JRE 附带的(通常很糟糕)日志记录实现。另一个日志实现是 logback,它正在慢慢获得关注,但还没有普及。
    • log4j.propertieslog4j.xml 是配置 log4j 的不同方式,两者同样有效。您使用哪一个取决于您,尽管某些应用程序服务器会指定其中一个。阅读log4j manual 了解如何配置它。
    • 如果 Hibernate 使用 SLF4J 作为其 API,那是 Hibernate 开发人员的选择。但是,您可以选择 SLF4J 将委托给哪个日志记录实现。再次阅读slf4j manual,了解如何选择您选择的实现。

    是的,这一切都相当混乱。给定一个开放的选择,SLF4J 和 Logback 是最有能力的组合,但你通常没有一个开放的选择。不同的框架(如 Hibernate 和 Spring)可能会使用不同的日志 API,通常是 commons-logging 或 SLF4J,但您可以让所有这些 API 最终记录到相同的底层实现(通常是 log4j)。

    【讨论】:

      【解决方案2】:
      • commons-logging、log4j、slf4j 和 JCL 之间的区别。我的理解是 slf4j 是一个包装器,而 commons-logging 和 log4j 是实际的实现。我不知道 JCL 适合哪里。

      Jakarta Commons Logging (JCL) 和 Simple Logging Facade for Java SLF4J 都是各种日志框架抽象,例如java.util.logging、log4j 和 logback,允许最终用户在部署时插入所需的日志框架。众所周知,Commons Logging 存在类加载器问题,这是 SLF4J 试图解决的问题(众所周知,SLF4J 是一个更干净的库)。

      话虽如此,事实上 Spring 使用 Jakarta Commons Logging API(参见 Logging Dependencies in Spring):Spring 是针对 JCL 编译的,Spring 使 JCL Log 对象可用于扩展 Spring 的类。实际上是 Spring 中唯一的强制外部依赖。这个选择has been made 因为许多其他框架也在使用它(例如 Struts)。这个想法是避免在构建应用程序时必须在类路径上有多个外观库(“A”代表 Spring,“B”代表 Struts 等)。但是,如果您愿意,可以用 SLF4J 替换 JCL(SFL4J 提供与日志框架的绑定,但也提供“JCL 到 SLF4J”的桥梁)。有关所有详细信息,请参阅提到的帖子Logging Dependencies in Spring

      • 如何为 Spring 配置日志记录。 web.xml 文件中有什么,我需要 log4j.properties 文件还是 log4j.xml 文件?在 WEB-INF 中它在哪里?我的 applicationContext.xml 文件中有什么内容吗? (抱歉,我这里需要从零开始)。

      要记录,您有 1. 决定要使用哪种实现(java.util.logging、log4j 或 logback),2. 如果需要,将选择的实现放在类路径中(java.util.logging 在Java SE 所以它不需要额外的库)和 3. 配置它(通过将配置文件放在类路径上)。如果您选择使用 log4j,只需将其 jar 和 log4j.properties 或更花哨(但更冗长)log4j.xml(这只是配置的另一种格式)添加到类路径。

      • 我在我的项目中使用 Hibernate,包括通过 Maven。似乎 Hibernate 使用 slf4j-simple。我看到警告说我不能在类路径上同时拥有 slf4j-simple 和 slf4j-log4j。我没有包含 slf4j-log4j 作为依赖项,但 Hibernate 必须包含它。我该如何解决这个问题?我可以强制 Hibernate 使用 log4j 吗?

      Hibernate utilizes Simple Logging Facade for Java (SLF4J),事实上,你不能在类路径上同时有多个bindings(例如slf4j-simple.jarslf4j-logj12.jar)。在这里,您很可能会从另一个依赖项传递slf4j-simple.jar。要解决此问题,请运行 mvn dependency:tree 以找出它的来源,并在需要时将其排除。

      顺便说一句,在您的情况下,我会将 Spring 配置为使用 SLF4J,因为 Hibernate 正在使用它。请按照第一段中提到的链接中的步骤进行操作。我会使用 logback 作为日志框架(它是 log4j 的继承者),这就是现在发生的事情。

      【讨论】:

        【解决方案3】:

        您的类路径中需要一个 log4j.properties 文件。这是我昨天碰巧创建的一个最小属性文件:

        log4j.logger.BillReview=INFO,BillReviewLog
        log4j.appender.BillReviewLog=org.apache.log4j.RollingFileAppender
        log4j.appender.BillReviewLog.File=BillReview.log
        log4j.appender.BillReviewLog.Append=true
        log4j.appender.BillReviewLog.MaxFileSize=5000KB
        log4j.appender.BillReviewLog.MaxBackupIndex=5
        log4j.appender.BillReviewLog.layout=org.apache.log4j.PatternLayout
        log4j.appender.BillReviewLog.layout.ConversionPattern=%c %p %-10.10X{server} %-4.4X{user} %d{ISO8601} %m%n
        

        将其放入 log4j.properties 文件中,将所有对“BillReview”的引用更改为更像您的项目的内容,这将记录到文件并停止这些消息。

        您对哪个日志框架的问题主要是个人选择。 Log4j 是旧标准,它运行良好,Commons 日志记录和 slf4j 是较新的 API,允许一些更复杂的用例。

        【讨论】:

          【解决方案4】:

          我会让一些比我回答第一个问题更有经验的大师。

          回答你的第二个问题...

          您可以使用 log4j.properties 或 log4j.xml 文件(哪个都没有关系)。无论您选择什么,都应该将它添加到类路径中(通常它应该与源代码位于同一目录中)。如果您使用 Spring,将 src 目录分解为逻辑部分的好方法是使用以下目录结构...

          src/main/java -- 把主要源码放在这里
          src/main/resources -- 把你主要来源使用的资源放在这里
          src/test/java -- 将测试源放在这里(用于测试)
          src/test/resources -- 将测试资源放在这里

          因此,您需要将 log4j.properties 放在 src/test/resources 目录中。

          回答你的第三个子弹......

          您可以通过执行以下操作在 pom.xml 文件中排除依赖项中的依赖项...

          <dependency>
              <groupId>org.apache.xbean</groupId>
              <artifactId>xbean-spring</artifactId>
              <version>${xbean.version}</version>
              <exclusions>
                  <exclusion>
                      <groupId>commons-logging</groupId>
                      <artifactId>commons-logging</artifactId>
                  </exclusion>
              </exclusions>
          </dependency>
          

          【讨论】:

            【解决方案5】:

            我在运行测试时在同一区域遇到了问题。我最终注意到,除了我想要的 slf4j-log4j12 之外,junit 还引入了 slf4j-nop 作为依赖项。一旦我排除了slf4j-nop,它就开始工作了。

            【讨论】:

              猜你喜欢
              • 2012-03-01
              • 1970-01-01
              • 2021-04-27
              • 2021-11-28
              • 2021-08-31
              • 1970-01-01
              • 1970-01-01
              • 2016-11-16
              • 2014-03-15
              相关资源
              最近更新 更多