Spring 记录绑定到 Log4J 的 SLF4J

Spring Logging SLF4J binded to Log4J

我正在尝试将我的 SpringMVC 应用程序配置为使用 SLF4J 而不是 vanilla commons-logging 进行记录。

我完全卡住了,我的文件没有记录任何内容,尽管如果我调试代码,表达式 if (log.isDebugEnabled()) { 的计算结果为真。

我做错了什么?

这是我的配置:

我的pom.xml

<!-- Logging -->
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${org.springframework-version}</version>
        <exclusions>
            <!-- Exclude Commons Logging in favor of SLF4j -->
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
</dependency>
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${org.slf4j-version}</version>
        <scope>runtime</scope>
</dependency>
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${org.slf4j-version}</version>
</dependency>
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${org.slf4j-version}</version>
        <scope>runtime</scope>
</dependency>
<dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
        <scope>runtime</scope>
</dependency>

我的log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN"       "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%-5p: %c - %m%n" />
    </layout>
</appender>

<appender name="fileAppender" class="org.apache.log4j.FileAppender">
    <param name="Threshold" value="ALL" />
    <param name="File" value="${catalina.home}/logs/workcontrol.log" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d  %-5p  [%c{1}] %m %n" />
    </layout>
</appender>

<!-- Application Loggers -->
<logger name="es.jumtech.workcontrol">
    <level value="ALL" />
    <appender-ref ref="fileAppender" />
</logger>

<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
    <level value="info" />
</logger>

<logger name="org.springframework.beans">
    <level value="info" />
</logger>

<logger name="org.springframework.context">
    <level value="info" />
</logger>

<logger name="org.springframework.web">
    <level value="info" />
</logger>

<logger name="org.hibernate">
    <level value="info" />
</logger>

<!-- Root Logger -->
<root>
    <priority value="ERROR" />
    <appender-ref ref="console" />
</root>

</log4j:configuration>

我的 Java Class 应该记录:

package es.jumtech.workcontrol.persistence.initial;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import es.jumtech.workcontrol.persistence.dao.ProfileDAO;
import es.jumtech.workcontrol.persistence.dao.RoleDAO;
import es.jumtech.workcontrol.persistence.entity.Profile;
import es.jumtech.workcontrol.persistence.entity.Role;

@Component
public class DataSeeder implements ApplicationListener<ContextRefreshedEvent> {

@Autowired
private RoleDAO roleDAO;

@Autowired
private ProfileDAO profileDAO;

private static final Logger log = LoggerFactory.getLogger(DataSeeder.class);

@Override
@Transactional(readOnly = false)
public void onApplicationEvent(ContextRefreshedEvent event) {
    // Se inicializan los roles
    loadRoles();

    // Se inicializan los perfiles
    loadProfiles();
}

private void loadRoles() {
    if (log.isDebugEnabled()) {
        log.debug("Se comprueba si existen los roles");
    }

    Role roleBoss = roleDAO.getRoleByName(Role.BOSS);
    if (roleBoss == null) {
        log.error("No existe el rol ROLE_BOSS, se crea");
        roleBoss = new Role();
        roleBoss.setRole(Role.BOSS);
        roleDAO.createRole(roleBoss);
    }

    Role roleAdmin = roleDAO.getRoleByName(Role.ADMIN);
    if (roleAdmin == null) {
        log.error("No existe el rol ROLE_ADMIN, se crea");
        roleAdmin = new Role();
        roleAdmin.setRole(Role.ADMIN);
        roleDAO.createRole(roleAdmin);
    }

    Role roleWorker = roleDAO.getRoleByName(Role.WORKER);
    if (roleWorker == null) {
        log.error("No existe el rol ROLE_WORKER, se crea");
        roleWorker = new Role();
        roleWorker.setRole(Role.WORKER);
        roleDAO.createRole(roleWorker);
    }
}

private void loadProfiles() {
    log.error("Se comprueba si existen los perfiles");

    Profile deliveryProfile = profileDAO.getProfileByName("Repartidor");
    if (deliveryProfile == null) {
        log.error("No existe el perfil Repartidor, se crea");
        deliveryProfile = new Profile();
        deliveryProfile.setProfile("Repartidor");
        profileDAO.createProfile(deliveryProfile);
    }

    Profile comercialProfile = profileDAO
            .getProfileByName("Agente Comercial");
    if (comercialProfile == null) {
        log.error("No existe el perfil Agente Comercial, se crea");
        comercialProfile = new Profile();
        comercialProfile.setProfile("Agente Comercial");
        profileDAO.createProfile(comercialProfile);
    }

    Profile officeProfile = profileDAO.getProfileByName("Oficinista");
    if (officeProfile == null) {
        log.error("No existe el perfil Oficinista, se crea");
        officeProfile = new Profile();
        officeProfile.setProfile("Oficinista");
        profileDAO.createProfile(officeProfile);
    }

}
}

解决方案

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-solr</artifactId>
        <version>1.1.4.RELEASE</version>
    </dependency>

正如@mp911de 所指出的,此依赖项正在导入同样实现 SLFJ4 的 Logback 库,以及正在返回的记录器:

private static final Logger log = LoggerFactory.getLogger(DataSeeder.class);

是 ch.qos.logback.classic.Logger 的实例而不是 org.slf4j.impl.Log4jLoggerAdapter

提前致谢, 迭戈.

这是我通常使用的设置。在我的 Maven 项目中没有问题。

Maven 依赖项:

<!-- The slf4j api -->
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${org.slf4j-version}</version>
</dependency>
<!-- The slf4j implementation -->
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${org.slf4j-version}</version>
        <scope>runtime</scope>
</dependency>

log4j.properties - 此文件应位于您的 src/main/resources 目录中:

# Root logger logging level option
log4j.rootLogger=ERROR, appenderName

# Redirect log messages to a log file
log4j.appender.appenderName=org.apache.log4j.RollingFileAppender
#outputs to Tomcat home
log4j.appender.appenderName.File=${catalina.home}/logs/MyLog.log
log4j.appender.appenderName.MaxFileSize=5MB
log4j.appender.appenderName.MaxBackupIndex=10
log4j.appender.appenderName.layout=org.apache.log4j.PatternLayout
log4j.appender.appenderName.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

在您的 java 代码中创建日志:

private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);

当然,调用日志:

LOG.error("Some exception happened", exception);

您检查过任何 SLF4J 输出吗?如果存在 SLF4J 的多个绑定,SLF4J 会抱怨它。

另一个问题是;您已将记录器类别 es.jumtech.workcontrol 设置为级别 ALL,这导致 isDebugEnabled() 为 return true。您至少应该在其中看到一些东西(以防您记录超过 8k,这是默认缓冲区大小)。

我提出三件事:

  1. 暂时将根记录器设置为ALLDEBUG
  2. 使用 -Dlog4j.debug=true 启动您的应用程序。您应该看到引导 log4j 的一些细节。
  3. 确保 logger.getClass().getName() 是 org.slf4j.impl.Log4jLoggerAdapter

HTH,马克