注意:部份代碼太長,可以通過文末的圖片快速查看對應位置
項目需求
- 用戶想自己配置日誌存放的位置,因此我們需要滿足提供可以配置的文件,用以滿足用戶的需求。
- 因此,我們主要通過 log4j2.xml 來讀取 application.yml 中的屬性值
項目實現
- 在eclipse 或者IDEA 中,新建一個 springboot 項目 ,只需要滿足基本要求即可。
- 初始化的pom.xml文件如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-
因爲我們需要使用 log4j2 來實現日誌記錄功能 ,因此,我們先完善日誌基礎配置
-
這其中有許多原理不做解釋,網上看一下,大家都能懂,不懂可以諮詢作者
- pom.xml 中加入相關依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency><!-- web 需要放在第一位,才能保證後面的jar包默認去除logback --> <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> <!-- log4j2 日誌 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!-- log4j2 日誌 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
- 將 src/main/source 下面新建一個 log4j2 文件夾 ,並在下面新建一個 log4j2.xml文件
<?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"/> </root> <!--記錄druid-sql的記錄--> <logger name="druid.sql.Statement" level="debug" additivity="false"> <appender-ref ref="druidSqlRollingFile"/> </logger> <logger name="druid.sql.Statement" level="debug" additivity="false"> <appender-ref ref="druidSqlRollingFile"/> </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>
- application.yml 中的初始化配置
logging: config: classpath:log4j2/log4j2.xml
-
按照上訴配置,我們完成了 log4j2 的基本配置,
-
啓動項目,日誌如下:就說明成功了
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.21.RELEASE)
[15:36:58.239] INFO org.springframework.boot.StartupInfoLogger 48 logStarting - Starting Log4j2xml1Application on DESKTOP-EMD1JN0 with PID 9520 (E:\zhongchebottom\log4j2xml-1\target\classes started by LMS in E:\zhongchebottom\log4j2xml-1)
[15:36:59.378] INFO org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer 216 start - Tomcat started on port(s): 8080 (http)
[15:36:59.380] INFO org.springframework.boot.StartupInfoLogger 57 logStarted - Started Log4j2xml1Application in 1.348 seconds (JVM running for 1.957)
項目實現 二
- 在 application.yml 中加入 部分代碼,進行測試
logging:
config: classpath:log4j2/log4j2.xml
test:
demo: D:/mylog
- 新建一個監聽類,內容如下
- 主要關注下面一段內容代碼 ,這一段代碼主要是獲取 application.yml中的值
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
ConfigurableEnvironment envi = ((ApplicationEnvironmentPreparedEvent) event).getEnvironment();
MutablePropertySources mps = envi.getPropertySources();
PropertySource<?> ps = mps.get("applicationConfigurationProperties");
if (ps != null && ps.containsProperty("test.demo")) {
String logs = (String) ps.getProperty("test.demo");
System.err.println("=========" + logs);
MDC.put("log", logs);
}
}
}
package com.example.demo;
import org.slf4j.MDC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
public class ApplicationStartedEventListener implements GenericApplicationListener {
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
private static Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class, ApplicationEnvironmentPreparedEvent.class,
ApplicationPreparedEvent.class, ContextClosedEvent.class, ApplicationFailedEvent.class };
private static Class<?>[] SOURCE_TYPES = { SpringApplication.class, ApplicationContext.class };
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
ConfigurableEnvironment envi = ((ApplicationEnvironmentPreparedEvent) event).getEnvironment();
MutablePropertySources mps = envi.getPropertySources();
PropertySource<?> ps = mps.get("applicationConfigurationProperties");
if (ps != null && ps.containsProperty("test.demo")) {
String logs = (String) ps.getProperty("test.demo");
System.err.println("=========" + logs);
MDC.put("log", logs);
}
}
}
@Override
public int getOrder() {
return DEFAULT_ORDER;
}
@Override
public boolean supportsEventType(ResolvableType resolvableType) {
return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return isAssignableFrom(sourceType, SOURCE_TYPES);
}
private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
if (type != null) {
for (Class<?> supportedType : supportedTypes) {
if (supportedType.isAssignableFrom(type)) {
return true;
}
}
}
return false;
}
}
- 修改啓動類中的啓動方式,然後啓動項目即可
package com.example.demo;
import java.util.Set;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableAsync
@EnableScheduling
@ComponentScan(basePackages = { "com.example.demo" })
public class Log4j2xmlApplication {
private String bootstrap;
public String getBootstrap() {
return bootstrap;
}
public void setBootstrap(String bootstrap) {
this.bootstrap = bootstrap;
}
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Log4j2xmlApplication.class);
Set<ApplicationListener<?>> ls = app.getListeners();
ApplicationStartedEventListener asel = new ApplicationStartedEventListener();
app.addListeners(asel);
app.run(args);
// SpringApplication.run(Log4j2xmlApplication.class, args);
}
}
- 在 log4j2.xml 調用application.yml 中的屬性值 ,只截取了部分代碼,要注意的地方請看圖
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<!--只接受程序中DEBUG級別的日誌進行處理-->
<ThresholdFilter level="INFO" 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="${ctx:log}/debug.log"
filePattern="${ctx:log}/$${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="2 MB"/>
<TimeBasedTriggeringPolicy/>
</Policies>
</RollingFile>
<!--處理INFO級別的日誌,並把該日誌放到logs/info.log文件中-->
<RollingFile name="RollingFileInfo" fileName="${ctx:log}/info.log"
filePattern="${ctx:log}/$${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>
。。。。。。。。。。。
參考文章
- SpringBoot+log4j2.xml使用application.yml屬性值 : https://www.cnblogs.com/extjava/p/7553642.html