日志简介
- 日志的作用的就是取代
System.out.println()
- 有如下优点:
- 可以设置输出样式,如添加信息类别(错误,备注信息…) ,自动添加时间信息,出错方法等信息
- 可以设置输出级别,禁止某些级别输出。例如,只输出错误日志;
- 可以被重定向到文件,这样可以在程序运行结束后查看日志;
- 可以按包名控制日志级别,只输出某些包打的日志;
- 可以…
- Jul (Java Util Logging):JDK中的日志记录工具,也常称为JDKLog、jdk-logging,自Java1.4以来的官方日志实现。
- Log4j:Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。
- Log4j2:一个具体的日志实现框架,是Log4j 1的下一个版本,与Log4j 1发生了很大的变化,Log4j 2不兼容Log4j 1。
- Logback:一个具体的日志实现框架,和Slf4j是同一个作者,但其性能更好(推荐使用)。
门面型日志框架
- 门面型日志框架是日志接口或者规范,使用时还是调用记录型日志。
- 有的门面型日志也提供了简单的日子实现功能,为了在无第三方记录日志可调时以使用日志
- JCL:Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging
- jcl默认的配置:如果能找到
Log4j
则默认使用log4j
实现,如果没有则使用jul
(jdk自带的) 实现,再没有则使用jcl内部提供的SimpleLog
实现。
- jcl默认的配置:如果能找到
- SLF4J:是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)
- slf4j自己也有一个简易的实现,但是需要额外引入
slf4j-simple
- slf4j自己也有一个简易的实现,但是需要额外引入
关系与选择
- log4j是最早的,之后sun公司为了竞争推出了jul
- 因为从一个日志框架切换到另外一个,可能需要修改大量的代码,为了减少更改,将这些日志api抽象出接口,这样以后调用的时候,就调用这些接口
- 由此诞生的就是
jcl
- 由此诞生的就是
- jul性能一般,log4j也有性能问题且停止维护,建议使用 Logback 或者 Log4j2。
因为logback与slf4j是同一个作者,兼容性很好。logback性能又强,**推荐使用logback+slf4j**
日志频繁爆漏洞,所以
- 一定要使用门面框架。
- 只添加一个日志实现
- 日志实现坐标应该设置 optional 并使⽤ runtime scope,如
- 设置 optional 为 true,依赖不会传递,这样如果你是个 lib 项⽬,然后别的项目使⽤了你这个 lib,不会被引入不想要的 Log Implementation 依赖;
- scope 设置为 runtime,是为了防⽌开发⼈员在项⽬中直接使⽤ Log Implementation 中的类,强制约束开发人员使⽤ Facade 接口。
- 更多…链接
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
JDK Logging (JUL)
Java标准库内置了日志包
java.util.logging
- 使用Java标准库内置的Logging有以下局限:
- Logging系统在JVM启动时读取配置文件并完成初始化,一旦开始运行main()方法,就无法修改配置;
- 配置不太方便,需要在JVM启动时传递参数-Djava.util.logging.config.file=
。
- 会额外输出
时间``类``方法名``日志类别
- JDK的Logging定义了7个日志级别,从严重到普通。默认级别是INFO,INFO级别以下的日志,不会被打印出来
- SEVERE
- WARNING
- INFO
- CONFIG
- FINE
- FINER
- FINEST
传入的类名是用于打印到输出日志的,貌似需要进行配置才生效,直接输出时都是输出日志语句当前类和当前方法
public class Hello {
public static void main(String[] args) {
Logger logger = Logger.getGlobal();
或者
Logger logger = Logger.getLogger(类名.class.getName());
logger.info("start process...");
logger.warning("memory is running out...");
logger.fine("ignored.");
logger.severe("process will be terminated...");
}
}
Mar 02, 2019 6:32:13 PM Hello main
信息: start process...
Mar 02, 2019 6:32:13 PM Hello main
警告: memory is running out...
Mar 02, 2019 6:32:13 PM Hello main
严重: process will be terminated...
JCL
这里提下JCL只是为了看到方法和类能更快的明白这是用的JCL ,不至于不认识
- 同sjlf4j用法差不多,不同之处就是Log变成了Logger,LogFactory变成了LoggerFactory
-
SLF4J
slf4j
使用方法和jcl
差不多,下面是sjf4j使用**日志对象必须在类里创建,否则**getClass()
报错- 可以在类上配置
@Slf4j
注解自动创建一个名称为log的Logger
- 可以在类上配置
- slf4j支持占位符拼接字符串
- sjf4j会自动寻找日志实现
- 在springboot项目中默认就集成了
**logback**
且是默认日志,无需引入。slf4j会自动使用logback - 平常springboot项目启动的信息其实就是logback信息格式
spring-boot-starter-test
中附带了slf4j
的包,也无需再引入- 多个实现日志时如果存在logback,会自动选择logback,其他日志实现的优先级不清楚
- 在springboot项目中默认就集成了
- 注意导入的
**Logger**
和**LoggerFactory**
都是**org.slf4j**
里的,不是**om.sun.org.slf4j**
里的
//@Slf4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class Main{
final Logger logger = LoggerFactory.getLogger(getClass());
main(){
int score = 99;
p.setScore(score);
logger.info("Set score {} for Person {} ok.", score, p.getName());
}
}
输出信息格式如下:
11:18:09.701 [main] INFO c.x.l.SpringBootDemoLogbackApplication - set score ........
LogBack
- springboot中logback可不配置就能使用,因为springboot默认的日志框架就是logback,集成了
如果要使用配置文件,需要在springboot的默认配置文件中添加如下配置
logging:
# 设置logback.xml位置
config: classpath:logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="FILE_ERROR_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} %file:%line: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> </filter> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>UTF-8</charset> </encoder> </appender> <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高, 所以我们使用下面的策略,可以避免输出 Error 的日志--> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!--过滤 Error,这一部没有看懂是什么作用--> <level>ERROR</level> <!--匹配到就禁止--> <onMatch>DENY</onMatch> <!--没有匹配到就允许--> <onMismatch>ACCEPT</onMismatch> </filter> <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。--> <!--<File>logs/info.demo-logback.log</File>--> <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间--> <FileNamePattern>logs/demo-logback/info.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern> <!--只保留最近90天的日志--> <maxHistory>90</maxHistory> <!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志--> <!--<totalSizeCap>1GB</totalSizeCap>--> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 --> <maxFileSize>2MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!--<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">--> <!--<maxFileSize>1KB</maxFileSize>--> <!--</triggeringPolicy>--> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> </appender> <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter--> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>Error</level> </filter> <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。--> <!--<File>logs/error.demo-logback.log</File>--> <!--滚动策略,按照时间滚动 TimeBasedRollingPolicy--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间,下面会生成一个以error.created_on_名称开头的--> <FileNamePattern>D:/logs/demo-logback/error.created_on_%d{yyyy-MM-dd}.part_%i.log</FileNamePattern> <!--只保留最近90天的日志--> <maxHistory>90</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 --> <maxFileSize>2MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder> <pattern>${FILE_ERROR_PATTERN}</pattern> <charset>UTF-8</charset> <!-- 此处设置字符集 --> </encoder> </appender> <root level="info"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE_INFO"/> <appender-ref ref="FILE_ERROR"/> </root> </configuration>
springboot控制台日志无颜色
在启动的configuration配置里的
vm option
设置为-Dspring.output.ansi.enabled=ALWAYS