1什么时slf4j
slf4j是一个日志接口,自己没有具体实现日志系统,只提供了一组标准的调用api,这样将调用和具体的日志实现分离,使用slf4j后有利于根据自己实际的需求更换具体的日志系统,比如,之前使用的具体的日志系统为log4j,想更换为logback时,只需要删除log4j相关的jar,然后加入logback相关的jar和日志配置文件即可,而不需要改动具体的日志输出方法,试想如果没有采用这种方式,当你的系统中日志输出有成千上万条时,你要更换日志系统将是多么庞大的一项工程。如果你开发的是一个面向公众使用的组件或公共服务模块,那么一定要使用slf4的这种形式,这有利于别人在调用你的模块时保持和他系统中使用统一的日志输出。
slf4j日志输出时可以使用{}占位符,如,logger.info("testlog: {}", "test"),而如果只使用log4j做日志输出时,只能以logger.info("testlog:"+"test")这种形式,前者要比后者在性能上更好,后者采用+连接字符串时就是new 一个String 字符串,在性能上就不如前者。
2.logback
logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现(即直接实现了slf4j的接口,而log4j并没有直接实现,所以就需要一个适配器slf4j-log4j12.jar),logback一共有以下几个模块:
logback-core:其它两个模块的基础模块
logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging
logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能
3.jar
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency
4.spring boot配置文件中
#系统日志配置 log: level: info #输出日志级别 tarce debug info wran error path: ./logs ##会在当前路径下创建一个logs文件夹
5.logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 这里引用的application.yml的配置,在最下面root标签里用到--> <springProperty scope="context" name="logLevel" source="log.level"/> <springProperty scope="context" name="logPath" source="log.path"/> <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"> ##控制台日志 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出,详细请参考log4j API --> <pattern>[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} - [%X{threadKey}] %C.%M: %m%n</pattern> </encoder> </appender> <!-- 所有日志 --> <appender name="rollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logPath}/yto_server.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> ##日志文件回滚 <!--日志文件输出的文件名 --> <FileNamePattern>${logPath}_server_%d{yyyy-MM-dd}_%i.log </FileNamePattern> <maxFileSize>10MB</maxFileSize> ## 10M 自动生成下一个文件 <maxHistory>10</maxHistory> ## 保存10天的 </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} - [%X{threadKey}] %C.%M: %m%n</pattern> </encoder> </appender> <!-- 系统日志 --> <appender name="syslog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 日志记录路径,可用绝对路径和相对路径 --> <file>${logPath}/_sys/_sys.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--日志文件输出的文件名 --> <FileNamePattern>${logPath}/_sys/_sys_%d{yyyy-MM-dd}_%i.log </FileNamePattern> <maxHistory>10</maxHistory> <maxFileSize>10MB</maxFileSize> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} - [%X{threadKey}] %C.%M: %m%n</pattern> </encoder> </appender> <!-- 操作日志 --> <appender name="optlog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logPath}/_opt/_opt.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <!--日志文件输出的文件名 --> <FileNamePattern>${logPath}/_opt/_opt_%d{yyyy-MM-dd}_%i.log </FileNamePattern> <maxHistory>10</maxHistory> <maxFileSize>10MB</maxFileSize> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>[%p] %d{yyyy-MM-dd HH:mm:ss.SSS} - [%X{threadKey}] %C.%M: %m%n</pattern> </encoder> </appender> <!-- 不同的业务逻辑日志打印到指定文件夹--> <logger name="systemLog" additivity="false" level="${logLevel}"> ##name 日志打印的类名 additivity 是否向上级root传日志(如果是true) 根节点root 会打印两遍日志 level 输出日志的等级 <appender-ref ref="syslog"/> ## 执行appenderName = syslog 中的方案
<!-- 如果没有下面的consoleAppender,并且additivity是false的情况下,日志不会打印到控制台,即使有了root根节点--> <appender-ref ref="consoleAppender"/> </logger> <logger name="operatorLog" additivity="false" level="${logLevel}"> <appender-ref ref="optlog"/>
<!-- 如果没有下面的话consoleAppender 并且additivity是false的情况下,日志不会打印到控制台,即使有了root--> <appender-ref ref="consoleAppender"/> </logger> <root level="${logLevel}"> ##根节点 logger 子节点 level 输出日志的等级 <appender-ref ref="consoleAppender" /> ## 打印控制台日志 <appender-ref ref="rollingFileAppender" /> </root> </configuration>
6.LogFileName:
public enum LogFileName {
//配置到logback.xml中的logger name="systemLog"
SYS_LOG("systemLog"),
OPT_LOG("operatorLog");
private String logFileName;
LogFileName(String fileName) {
this.logFileName = fileName;
}
public String getLogFileName() {
return logFileName;
}
public void setLogFileName(String logFileName) {
this.logFileName = logFileName;
}
public static LogFileName getAwardTypeEnum(String value) {
LogFileName[] arr = values();
for (LogFileName item : arr) {
if (null != item && StringUtils.isNotBlank(item.logFileName)) {
return item;
}
}
return null;
}
}
7.CustomLoggerFactory
public class CustomLoggerFactory { public static Logger SystemLogger(){ return CustomLoggerFactory.Logger(LogFileName.SYS_LOG); } public static Logger OperateLogger(){ return CustomLoggerFactory.Logger(LogFileName.OPT_LOG); } public static <T> Logger Logger(Class<T> clazz) { return LoggerFactory.getLogger(clazz); } /** * 打印到指定的文件下 * * @param desc 日志文件名称 * @return */ public static Logger Logger(LogFileName desc) { return LoggerFactory.getLogger(desc.getLogFileName()); } }