笔者最近创建了一个新的spring boot 工程,项目要发布到测试环境用docker来跑,日志需要输出到指定目录映射出来查看,就想着配置一下log。
引入log4j2
首先介绍如何引入log4j2,spring boot 不做修改默认使用的是logback,性能不如log4j2优秀,所以我们换成log4j2。
我们要在pom中先将默认的logging(里面用的Logbak)包排除,排除的方法有很多,由于笔者采用分模块打包的形式,所有项目有一个根pom,我选择在根pom的 dependencyManagement 依赖管理中排除这个包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
如此一来,子模块引入的spring-boot-starter里面都不包含spring-boot-starter-logging的
然后我们在需要打印log的模块中引入spring-boot-starter-log4j2就可以了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
配置log4j2
引入后,spring-boot-starter-log4j2会有默认的配置,然后笔者的需求是修改日志打印的路径,所以要修改其配置文件
我们在resources目录下创建log4j2-spring.xml,注意这样命名是为了spring可以自动加载我们的配置文件,当前你也可以随便起名字,那就需要你在application.yml配置中指定你的配置文件名
logging:
config: 你的配置文件名
个人比较喜欢它原生的日志格式,想在它默认配置下只修改文件目录,于是在 spring-boot这个jar包里面的org.springframework.boot.logging.log4j2下找到默认配置log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<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.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
只需要在里面增加文件配置就可以了,修改后的文件如下
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="log.name">${project.name}</Property>
<Property name="log.path">/mnt/logs/${project.name}/${hostName}</Property>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
<RollingFile name="File"
fileName="${log.path}/${log.name}.log"
filePattern="${log.path}/$${date:yyyy-MM}/${log.name}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${sys:FILE_LOG_PATTERN}"/>
<!--每个日志文件的大小,达到size后自动打包-->
<SizeBasedTriggeringPolicy size="500 MB"/>
<!--每天最多有多少个压缩包,超过该值,自动删除当天最早的压缩包-->
<DefaultRolloverStrategy max="100">
<!--日志删除策略,自动删除30天前的日志-->
<Delete basePath="${log.path}" maxDepth="2">
<IfFileName glob="*/*.log" />
<IfLastModified age="100d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<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.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="File" />
</Root>
</Loggers>
</Configuration>
引入pom变量
在模块多的情况下,笔者不想每个文件都要改,于是引用了pom里面的变量project.name,如果不做任何配置,会把这两个变量当成字符串,然后真的打到${project.name}目录下面
接下来我们解决这个问题
spring boot 2.0 默认的变量符号是@变量名@,我们将它改成${变量名},在pom文件build节点下引入maven-resource-plugin,然后设置useDefaultDelimiters = true,变量的符号就变成了${}
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
这样配置完后,笔者发现打包完成后的xml文件中,变量并没有被替换掉,还是${}的形式,还需要增加以下配置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
再次打包,project.name已经打入xml文件中了。(hostName会在运行时加入系统变量中,所以这个打完包仍然是${hostName},不影响最终的日志输出目录)
至于为什么在配置中增加了resource目录的过滤就好了,也许是这样才能在打包时处理一遍这个目录(猜的),希望有懂的大佬交流一下。