前言 Java发展至今已经形成了一套完整的日志体系,分为日志门面和日志具体实现。日志门面相当于一个接口,日志各种实现其实就是日志门面的不同实现。
Java的日志加载依赖于SPI ,不同于API, SPI模式下接口处于调用者一侧,开发者一侧只拥有具体的实现。而API模式下接口和具体实现都处于开发者一侧,调用者无需关心具体实现,只管调用开发者提供的接口即可。
SPI机制给予了程序动态加载的能力,程序运行的过程中根据接口去动态扫描对应的接口实现类并加载。
举个例子,Java的日志门面Slf4j对应的具体实现有Spring Boot自带的也是默认的logback,还有log4j,log4j2等,在使用时会动态加载classpath中存在的slf4j对应的实现类并把它加载使用,这就是SPI机制。
Logback logback是Spring Boot默认使用的日志实现,即使不配置也可以直接使用。
1 2 3 4 5 6 7 8 9 10 @SpringBootApplication public class RedisUsageApplication { public static void main (String[] args) { SpringApplication.run(RedisUsageApplication.class, args); Logger log = LoggerFactory.getLogger("RedisUsageApplication.class" ); log.warn("Easy bro, this is a fake warn lol." ); log.error("Easy bro, this is a fake error lol." ); } }
也可以使用Lombok提供的注解@Slf4j
来输出log,这样简洁一些。
1 2 3 4 5 6 7 8 9 10 @SpringBootApplication @Slf4j public class RedisUsageApplication { public static void main (String[] args) { SpringApplication.run(RedisUsageApplication.class, args); log.warn("Easy bro, this is a fake warn lol." ); log.error("Easy bro, this is a fake error lol." ); } }
但是默认的配置还是不能够更加精准的满足各种需求,需要进行自定义设置。
在classpath下创建logback.xml或者logback-spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <configuration > <include resource ="org/springframework/boot/logging/logback/defaults.xml" /> <property name ="APP_NAME" value ="log-files" /> <property name ="LOG_PATH" value ="${user.home}/${APP_NAME}" /> <property name ="LOG_FILE" value ="${LOG_PATH}/redis-usage.log" /> <appender name ="APPLICATION" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <file > ${LOG_FILE}</file > <rollingPolicy class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > <fileNamePattern > ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern > <maxHistory > 7</maxHistory > <timeBasedFileNamingAndTriggeringPolicy class ="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" > <maxFileSize > 50MB</maxFileSize > </timeBasedFileNamingAndTriggeringPolicy > </rollingPolicy > <layout class ="ch.qos.logback.classic.PatternLayout" > <pattern > %d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern > </layout > </appender > <appender name ="CONSOLE" class ="ch.qos.logback.core.ConsoleAppender" > <layout class ="ch.qos.logback.classic.PatternLayout" > <pattern > %green(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%magenta(%thread)] %highlight(%-5level) %yellow(%logger{36}): %msg%n</pattern > </layout > </appender > <root level ="info" > <appender-ref ref ="CONSOLE" /> <appender-ref ref ="APPLICATION" /> </root > </configuration >
log的配置中有这么几个标签
property: 可以自定义变量名和变量值,方便拼接路径等。
appender: 每一个appender对应一个日志的输出地点
layout: 日志的输出格式
rollingPolicy: 日志的滚动策略
通过这些标签可以实现日志的完全自定义。
使用logback时可以在application.yml或者application.properties中加入logback的配置,但也可以不配置,因为Spring Boot的默认行为是扫描classpath下是否有logback.xml或者logback-spring.xml。
1 2 logging: config: classpath:logback-spring.xml
同时日志文件也可以在对应的目录下找到
Log4j2 log4j2和logback都是slf4j的具体实现,但在实际应用中二者不能同时存在,否则会报错,导致无法正常加载日志的实现类。
所以在使用log4j2时需要在pom中显示的剔除logback依赖,同时加入log4j2的依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <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 >
在classpath下创建log4j2.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 <?xml version="1.0" encoding="UTF-8" ?> <Configuration > <properties > <property name ="LOG_HOME" > ./service-logs</property > </properties > <Appenders > <Console name ="consoleAppender" target ="SYSTEM_OUT" > <PatternLayout pattern ="%style{%d{ISO8601}}{bright,green} %highlight{%-5level} [%style{%t}{bright,blue}] %style{%C{}}{bright,yellow}: %msg%n%style{%throwable}{red}" disableAnsi ="false" noConsoleNoAnsi ="false" /> </Console > <RollingFile name ="allFileAppender" fileName ="${LOG_HOME}/all.log" filePattern ="${LOG_HOME}/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log.gz" > <PatternLayout > <pattern > %d %p %C{} [%t] %m%n</pattern > </PatternLayout > <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy /> </Policies > <DefaultRolloverStrategy max ="100" /> </RollingFile > <RollingFile name ="debugFileAppender" fileName ="${LOG_HOME}/debug.log" filePattern ="${LOG_HOME}/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz" > <Filters > <ThresholdFilter level ="info" onMatch ="DENY" onMismatch ="NEUTRAL" /> </Filters > <PatternLayout > <pattern > %d %p %C{} [%t] %m%n</pattern > </PatternLayout > <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy /> </Policies > <DefaultRolloverStrategy max ="100" /> </RollingFile > <RollingFile name ="infoFileAppender" fileName ="${LOG_HOME}/info.log" filePattern ="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz" > <Filters > <ThresholdFilter level ="warn" onMatch ="DENY" onMismatch ="NEUTRAL" /> </Filters > <PatternLayout > <pattern > %d %p %C{} [%t] %m%n</pattern > </PatternLayout > <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy interval ="1" modulate ="true" /> </Policies > </RollingFile > <RollingFile name ="warnFileAppender" fileName ="${LOG_HOME}/warn.log" filePattern ="${LOG_HOME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz" > <Filters > <ThresholdFilter level ="error" onMatch ="DENY" onMismatch ="NEUTRAL" /> </Filters > <PatternLayout > <pattern > %d %p %C{} [%t] %m%n</pattern > </PatternLayout > <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy /> </Policies > <DefaultRolloverStrategy max ="100" /> </RollingFile > <RollingFile name ="errorFileAppender" fileName ="${LOG_HOME}/error.log" filePattern ="${LOG_HOME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz" > <PatternLayout > <pattern > %d %p %C{} [%t] %m%n</pattern > </PatternLayout > <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy /> </Policies > <DefaultRolloverStrategy max ="100" /> </RollingFile > <RollingFile name ="errorJsonAppender" fileName ="${LOG_HOME}/error-json.log" filePattern ="${LOG_HOME}/error-json-%d{yyyy-MM-dd}-%i.log.gz" > <JSONLayout compact ="true" eventEol ="true" locationInfo ="true" /> <Policies > <SizeBasedTriggeringPolicy size ="100 MB" /> <TimeBasedTriggeringPolicy interval ="1" modulate ="true" /> </Policies > </RollingFile > </Appenders > <Loggers > <Root level ="debug" > <AppenderRef ref ="allFileAppender" level ="all" /> <AppenderRef ref ="consoleAppender" level ="debug" /> <AppenderRef ref ="debugFileAppender" level ="debug" /> <AppenderRef ref ="infoFileAppender" level ="info" /> <AppenderRef ref ="warnFileAppender" level ="warn" /> <AppenderRef ref ="errorFileAppender" level ="error" /> <AppenderRef ref ="errorJsonAppender" level ="error" /> </Root > <Logger name ="org.springframework" level ="info" /> <Logger name ="druid.sql.Statement" level ="warn" /> <Logger name ="com.mybatis" level ="warn" /> </Loggers > </Configuration >
同样也可以通过appender和patternLayout等标签来设置日志的输出。
然后在application.properties中加上log4j2的配置
1 logging.config =classpath:log4j2.xml
测试一下,可以通过Lombok的@Log4j2
注释使用日志
1 2 3 4 5 6 7 8 9 @SpringBootApplication @Log4j2 public class Log4j2UsageApplication { public static void main (String[] args) { SpringApplication.run(Log4j2UsageApplication.class, args); log.warn("this is form log4j2." ); } }
同时按照log4j2.xml的配置对应的目录下可以找到按照日志级别分类的记录