对使用 Spring 和 Hibernate 的 Java 日志系统感到困惑
Posted
技术标签:
【中文标题】对使用 Spring 和 Hibernate 的 Java 日志系统感到困惑【英文标题】:Baffled by Java Logging Systems with Spring and Hibernate 【发布时间】: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 文件中的内容。这也需要吗?
【问题讨论】:
【参考方案1】: commons-logging 和 SLF4J 都是围绕其他日志记录实现的 API 包装器。 SLF4J 是两者中更现代的,而且功能更强大。 Log4j 是一个日志实现,几乎是事实上的标准。 JUL(java.util.logging
的缩写)是 JRE 附带的(通常很糟糕)日志记录实现。另一个日志实现是 logback,它正在慢慢获得关注,但还没有普及。
log4j.properties
和 log4j.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.jar
和slf4j-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.10Xserver %-4.4Xuser %dISO8601 %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
,它就开始工作了。
【讨论】:
以上是关于对使用 Spring 和 Hibernate 的 Java 日志系统感到困惑的主要内容,如果未能解决你的问题,请参考以下文章
使用 Hibernate + Spring 进行缓存 - 一些问题
如何使用 Spring + Hibernate 对实体进行自定义验证以进行多租户设置
ssh整合hibernate 使用spring管理hibernate二级缓存,配置hibernate4.0以上二级缓存