SpringBoot+log4j2.xml使用application.yml属性值问题
作者:extjava
这篇文章主要介绍了SpringBoot+log4j2.xml使用application.yml属性值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
项目中有个需求,需要log4j2.xml加载application.yml的属性,折腾了半天,贴代码吧:
1.自定义启动监听ApplicationStartedEventListener
代码中标红的就是从yml中读取的属性,然后通过MDC设置到log4j2的上下文
package com.wm.dcm.utils; 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; /** * @ClassName: MyApplicationStartedEventListener * @Description:TODO * @author: SUN * @date: 2017年9月19日 下午5:51:04 * */ 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("spring.kafka.bootstrap-servers")) { String kafkaUrl = (String) ps.getProperty("spring.kafka.bootstrap-servers"); //System.out.println(kafkaUrl); MDC.put("host", kafkaUrl); } if (ps != null && ps.containsProperty("logging.file")) { String fileName = (String) ps.getProperty("logging.file"); //System.out.println(kafkaUrl); MDC.put("fileName", fileName); } } } /* * (non-Javadoc) * * @see org.springframework.core.Ordered#getOrder() */ @Override public int getOrder() { // TODO Auto-generated method stub return DEFAULT_ORDER; } /* * (non-Javadoc) * * @see org.springframework.context.event.GenericApplicationListener# * supportsEventType(org.springframework.core.ResolvableType) */ @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; } }
2.在Application启动类中添加
自定义的启动监听ApplicationStartedEventListener
package com.wm.dcm.db; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.logging.LoggingApplicationListener; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.ComponentScan; import org.springframework.core.env.Environment; import org.springframework.kafka.annotation.EnableKafka; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import com.wm.dcm.constant.LogTypeAndLevel; import com.wm.dcm.utils.ApplicationStartedEventListener; @SpringBootApplication @EnableScheduling @ComponentScan(basePackages = { "com.wm.dcm" }) @EnableKafka @EnableAsync public class DBApplication { private String bootstrap; public String getBootstrap() { return bootstrap; } public void setBootstrap(String bootstrap) { this.bootstrap = bootstrap; } /** * The main method. * * @param args * the arguments * @throws Exception */ public static void main(String[] args) throws Exception { // System.out.println(env); SpringApplication app = new SpringApplication(DBApplication.class); Set<ApplicationListener<?>> ls = app.getListeners(); ApplicationStartedEventListener asel = new ApplicationStartedEventListener(); app.addListeners(asel); app.run(args); } }
3.在log4j2.xml中使用MDC定义的属性
标红的就是使用方式
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="info"> <Appenders> <RollingFile name="RollingFile" fileName="logs/${ctx:fileName}" filePattern="logs/$${date:yyyy-MM}/${ctx:fileName}-%d{MM-dd-yyyy}-%i.log.gz" immediateFlush="true" append="true"> <PatternLayout charset="UTF-8" pattern="[%-5p] %d[%t] [%c] - %m%n" /> <SizeBasedTriggeringPolicy size="50MB" /> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 --> <DefaultRolloverStrategy max="20" /> </RollingFile> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout charset="UTF-8" pattern="[%-5p] %d[%t] [%c] - %m%n" /> </Console> <Kafka name="Kafka" topic="wmdcm_log"> <JSONLayout complete="false" compact="true" locationInfo="true" /> <Property name="bootstrap.servers" value="${ctx:host}"/> </Kafka> </Appenders> <Loggers> <!-- root loggers <AppenderRef ref="Console" /> --> <Root level="info" includeLocation="true"> <AppenderRef ref="RollingFile" /> <AppenderRef ref="Console" /> <AppenderRef ref="Kafka" /> </Root> <Logger name="org.apache.kafka" level="ERROR" /> <Logger name="org.springframework.kafka" level="ERROR" /> </Loggers> </Configuration>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。