今天我整合了log4j2到spring-boot,排了一整天的雷,记录一下。
整合过程很简单,
1,排除spring-boot原有的spring-boot-starter-logging,将log4j2的依赖引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
因为其他依赖里也会引这个,可以做个全局排除
<!--全局排除spring-boot-starter-logging内的所有依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
2,配置log4j2.xml, yml文件也可以
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<!--只接受程序中DEBUG级别的日志进行处理-->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss.SSS}] %-5level %class{36} %L %M - %msg%xEx%n"/>
</Console>
<!--处理DEBUG级别的日志,并把该日志放到logs/debug.log文件中-->
<!--打印出DEBUG级别日志,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileDebug" fileName="./logs/debug.log"
filePattern="logs/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="DEBUG"/>
<ThresholdFilter level="INFO" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout
pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--处理INFO级别的日志,并把该日志放到logs/info.log文件中-->
<RollingFile name="RollingFileInfo" fileName="./logs/info.log"
filePattern="logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<!--只接受INFO级别的日志,其余的全部拒绝处理-->
<ThresholdFilter level="INFO"/>
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout
pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--处理WARN级别的日志,并把该日志放到logs/warn.log文件中-->
<RollingFile name="RollingFileWarn" fileName="./logs/warn.log"
filePattern="logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="WARN"/>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>
<PatternLayout
pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--处理error级别的日志,并把该日志放到logs/error.log文件中-->
<RollingFile name="RollingFileError" fileName="./logs/error.log"
filePattern="logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
<ThresholdFilter level="ERROR"/>
<PatternLayout
pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %class{36} %L %M - %msg%xEx%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--druid的日志记录追加器-->
<RollingFile name="druidSqlRollingFile" fileName="./logs/druid-sql.log"
filePattern="logs/$${date:yyyy-MM}/api-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] %-5level %L %M - %msg%xEx%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="500 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
</appenders>
<loggers>
<root level="DEBUG">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
<appender-ref ref="RollingFileDebug"/>
<appender-ref ref="druidSqlRollingFile"/>
</root>
<!--记录druid-sql的记录-->
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="druidSqlRollingFile"/>
</logger>
<logger name="druid.sql" level="debug" additivity="false">
<appender-ref ref="druidSqlRollingFile"/>
</logger>
<logger name="druid.sql" level="debug" additivity="false">
<appender-ref ref="Console"/>
</logger>
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="Console"/>
</logger>
<!--log4j2 自带过滤日志-->
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.crsh.plugin" level="warn" />
<logger name="org.crsh.ssh" level="warn"/>
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="warn"/>
<logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<logger name="org.thymeleaf" level="warn"/>
</loggers>
</configuration>
3,在application.yml中引入配置文件
# log4j2 日志配置
logging:
config: classpath:log4j2.xml
本以为这样直接启动就可以了,可发现启动不了了·····
报这个错
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/core/appender/rolling/DirectFileRolloverStrategy
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.logging.log4j.core.config.plugins.util.PluginRegistry.decodeCacheFiles(PluginRegistry.java:181)
at org.apache.logging.log4j.core.config.plugins.util.PluginRegistry.loadFromMainClassLoader(PluginRegistry.java:119)
at org.apache.logging.log4j.core.config.plugins.util.PluginManager.collectPlugins(PluginManager.java:132)
at org.apache.logging.log4j.core.pattern.PatternParser.<init>(PatternParser.java:131)
at org.apache.logging.log4j.core.pattern.PatternParser.<init>(PatternParser.java:112)
at org.apache.logging.log4j.core.layout.PatternLayout.createPatternParser(PatternLayout.java:209)
at org.apache.logging.log4j.core.layout.PatternLayout.createSerializer(PatternLayout.java:123)
at org.apache.logging.log4j.core.layout.PatternLayout.<init>(PatternLayout.java:111)
at org.apache.logging.log4j.core.layout.PatternLayout.<init>(PatternLayout.java:58)
at org.apache.logging.log4j.core.layout.PatternLayout$Builder.build(PatternLayout.java:494)
at org.apache.logging.log4j.core.config.AbstractConfiguration.setToDefault(AbstractConfiguration.java:567)
at org.apache.logging.log4j.core.config.DefaultConfiguration.<init>(DefaultConfiguration.java:47)
at org.apache.logging.log4j.core.LoggerContext.<init>(LoggerContext.java:81)
at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.createContext(ClassLoaderContextSelector.java:171)
at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.locateContext(ClassLoaderContextSelector.java:145)
at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:70)
at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:57)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:147)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(AbstractLoggerAdapter.java:103)
at org.apache.logging.slf4j.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:43)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:42)
at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:29)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:273)
at org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:179)
at com.gwmfc.cheetah.CheetahApplication.main(CheetahApplication.java:27)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.core.appender.rolling.DirectFileRolloverStrategy
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 42 more
Disconnected from the target VM, address: '127.0.0.1:13969', transport: 'socket'
Process finished with exit code 1
百思不得其解,就去问了前辈,前辈推荐这个网站
发现是差log4j-core这个依赖
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
然后又换了个错
"C:\Program Files\Java\jdk1.8\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:12999,suspend=y,server=n -javaagent:C:\Users\zhangjinqi\.IntelliJIdea2018.2\system\captureAgent\debugger-agent.jar=file:/C:/Users/zhangjinqi/AppData/Local/Temp/capture2882.props -Dfile.encoding=UTF-8 -classpath C:\Users\zhangjinqi\AppData\Local\Temp\classpath1497961761.jar com.gwmfc.cheetah.CheetahApplication
Connected to the target VM, address: '127.0.0.1:12999', transport: 'socket'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Disconnected from the target VM, address: '127.0.0.1:12999', transport: 'socket'
Exception in thread "main" java.lang.ClassCastException: org.apache.logging.log4j.simple.SimpleLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.getLoggerContext(Log4J2LoggingSystem.java:265)
at org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.beforeInitialize(Log4J2LoggingSystem.java:132)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:230)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:209)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122)
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:69)
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:48)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:292)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at com.gwmfc.cheetah.CheetahApplication.main(CheetahApplication.java:27)
Process finished with exit code 1
网上说是需要排除这些依赖
log4j-to-slf4j-2.0.2.jar
log4j-to-slf4j-2.0.2-sources.jar
log4j-slf4j-impl-2.0.2.jar
log4j-slf4j-impl-2.0.2-sources.jar
我试了,没有任何卵用
不过是需要排除的 (次日又加上试了一遍)
次日加回的错误
后来终于找到是还差一个依赖log4j-api
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
项目终于正常启动了,日志文件也生成了。
可我正在沾沾自喜时,发现这生成的Druid的SQL是什么啊···
SQL呢···
又陷入了绝境·····经过一下午的冥思苦想
发现application.yml的filters配置写的是slf4j``可现在用的是log4j 就改了
SQL就正常输出了,但日志配置文件还需要修改,以保证日志文件和控制台都有SQL和参数输出
<!--记录druid-sql的记录-->
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="druidSqlRollingFile"/>
</logger>
<logger name="druid.sql" level="debug" additivity="false">
<appender-ref ref="druidSqlRollingFile"/>
</logger>
<logger name="druid.sql" level="debug" additivity="false">
<appender-ref ref="Console"/>
</logger>
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="Console"/>
</logger>
后来发现用logger.info什么输出的都不生效
因为程序用的还是slf4j的写法
private static Logger logger = LoggerFactory.getLogger(HiveService.class);
需要换成
private static Logger logger= LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
生效
2020.7.13
后来同事发现自己Druid的mybatis数据源映射失败,没报错但项目启动失败,找了好久才找到。
我觉得是自己的日志框架有问题
try {
SpringApplication.run(CheetahApplication.class, args);
} catch (Exception e) {
logger.error(e);
// System.out.println(e);
}
在启动类加这个解决