java日志
日志
1.日志的概述
2.日志的发展历程
3.日志框架
4.日志实现
5.桥接器
6.日志的使用
7.日志框架的选择
8.springboot日志
9.疑问
一.日志是什么?
日志:说明系统实时运行状态的信息。
比如:System.out.println()语句就是一种最低级的日志。
二.java日志的发展历史:https://blog.csdn.net/wang0907/article/details/118675549
1.概述
各种日志的时间轴关系:
log4j -->JUL-->JCL--> slf4j --> logback --> log4j2
log4j日志实现
JUL日志实现
JCL日志接口:是Apache提供的一个通用日志API,自身提供日志实现SimpleLog(不推荐)。它允许开发人员使用不同的具体日志实现工具: Log4j, Jdk自带的日志(JUL)。
slf4j日志接口
logback日志实现
log4j2日志实现
2.详述
Java中的第一个日志框架是apache提出来的log4j,如下:
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
后来呢,sun公司认为自己作为java的开发主体,日志肯定是需要自己来给出方案的,为了打压log4j,于是在jdk4中制定了JULjava util logging,
在rt.jar的java.util.logging包中。
与此同时,又有一些其他的日志框架也被提了出来,比如simplelog,此时java日志体系如下:
log4j,jul(java.util.logging),simplelog,其他
但是众多的毫无关系的日志框架,势必在我们的项目中造成混乱,比如项目中使用的是log4j,依赖的库A使用的是JUL,依赖的库B使用的是simplelog,这样一个项目中各种日志框架混杂,项目会越来越不好维护,越来越混乱,此时这个问题就亟需解决。这个时候,apache社区提出了commons-logging即JCL的日志抽象来适配各种日志框架,此时java日志体系就变成下图:
之后呢,log4j的作者提出了一个对标JCL的日志抽象适配接口SLF4J(simple logging facade for Java),不仅如此还直接开发一个基于SLF4J的日志框架实现logback,与此同时呢,又继续维护并升级了log4j,形成了其升级版本log4j2,此时Java日志体系变为下图红色框为本部分新介绍的:
所以,在Java程序中常用日志框架可以分为两类:
无具体实现的抽象门面框架,如:Commons Logging、SLF4J
具体实现的框架,如:Log4j,Log4j 2,Logback,Jul
常用日志框架之间的关系
Log4j2与Log4j1发生了很大的变化,log4j2不兼容log4j1
Commons Logging和Slf4j是日志门面(门面模式是软件工程中常用的一种软件设计模式,也被称为正面模式、外观模式。它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用)。log4j和Logback则是具体的日志实现方案。可以简单的理解为接口与接口的实现,调用这只需要关注接口而无需关注具体的实现,做到解耦
比较常用的组合使用方式是Slf4j与Logback组合使用,Commons Logging与Log4j组合使用
Logback必须配合Slf4j使用。由于Logback和Slf4j是同一个作者,其兼容性不言而喻
三.日志框架:是日志实现的抽象层,(也叫日志门面,门面模式)
日志门面:是门面模式的一个典型的应用,门面模式,也称外观模式,请参照我的博文设计模式之外观模式,日志门面框架就使一套提供了日志相关功能的接口而无具体实现的框架,其调用具体的实现框架来进行日志记录。也就是说日志门面天然的兼容日志实现框架。典型的日志门面就是Commons Logging、SLF4J
使用日志门面的优点:
日志门面是介于具体的日志框架与系统之间的桥梁,通过日志门面框架的应用实现了系统与具体实现日志框架的解耦。无论具体实现的日志框架如何变化,都不会影响系统日志的记录功能,更无须更改系统代码,符合“开放-闭合原则”
JCL(Apache Commons Logging)是一个基于Java的日志记录实用程序,是用于日志记录和其他工具包的编程模型。它通过其他一些工具提供API,日志实现和包装器实现,最后一次版本更新停在了2014年,后来没有继续维护更新,一般不考虑选用
SLF4J:Java简易日志门面(Simple Logging Facade for Java,缩写SLF4J),是一套包装Logging 框架的界面程式,以外观模式实现。可以在软件部署的时候决定要使用的 Logging 框架,目前主要支援的有Java Logging API、Log4j及logback等框架。以MIT 授权方式发布。SLF4J 的作者就是 Log4j和Logback 的作者 Ceki Gülcü。
这里提一下日志实现里面的log4j和logback,这两个实现和门面slf4j都是同一个人写的,他先写了log4j后,觉得性能可以再做优化,又写了logback,为了有更加适配的门面,
自己又为log4j和logback量身打造了门面slf4j。所以这三者里面最优的搭配当然是slf4j+logback。
四.日志实现:具体的日志功能的实现。
JUL:是java.util.logging包下提供的日志实现,自Java1.4以来的官方日志实现
log4j:Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目
log4j2:在log4j问世之后,apache公司发现了日志市场,自家也开发了一款叫log4j2的产品,不兼容Log4j
Logback:Logback是一个日志框架,Log4j是同一作者,都出自Ceki Gülcü之手
五.桥接器(桥接模式)
思考一个问题?这么描述,我们想要写一个SpringBoot项目,日志框架组合我们打算使用Slf4j+logback,然后项目中集成了Spring,Hibernate,MyBatis等等组件依赖,这个时候会有一个问题,就是我们集成的组件框架中存在自己的日志框架,比如Spring自带commons-logging、Hibernate(jboss-logging)等等,那么这个时候,我们的项目里面就像一个日志框架的大杂烩一样,非常的乱,那么我们就需要给我们项目中日志框架做统一,也就是说,不管我依赖的组件自带了什么日志框架,我只要配置我的Slf4j+logback就可以了。slf4j桥接器就可以解决这个问题:
slf4j 桥接器:https://www.slf4j.org/legacy.html 这个里面的图可以放大
注意:
一.Jul日志转为Slf4j输出
java.util.logging.Logger打印出来的日志,如果要转为slf4j输出,要做以下两步:
1.在maven依赖里面加上jul-to-slf4j包(https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j)
2.main函数里面添加下列语句:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
参考资料:https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html
六.使用
1.jcl的使用:如果使用的时候,没有安装log4j的依赖,那么默认使用jdk14自带的JUL日志框架,如果log4j依赖配置了,那么就会使用log4j
https://blog.csdn.net/a232884c/article/details/121157039
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
2.LOG4j
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
日志的使用https://www.cnblogs.com/caozx/p/11585239.html
3.slf4j:日志门面
对于commons-logging来说,无需在pom.xml文件中单独引入日志实现框架,便可进行日志打印。但是,slf4j并不支持此功能,必须在pom.xml中单独引入底层日志实现。
slf4j的使用:http://www.javashuo.com/article/p-gwicgxoc-mo.html
slf4j的简单使用以及桥接旧的日志框架:https://zhuanlan.zhihu.com/p/366776412
<!--slf4j 日志门面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
搭配方案1:slf4j + jdk.jul
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
</dependency>
搭配方案2:slf4j + slf4j 内置简单实现
<!--slf4j 内置简单实现-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
搭配方案3:slf4j + log4j2 https://www.jianshu.com/p/e3b2de9e418b
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
搭配方案4:slf4j + logback
<!-- logback依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
如何在项目中打日志:
1.在类中写一个常量:
private static final Logger logger =LoggerFactory.getLogger(GlobalTransactionAop.class);
注意
LoggerFactory.getLogger(HelloConntroller.class);是为了定位日志
2.在方法里打日志
LOGGER.info("日志信息");
2.2如何将日志信息存储到文件中
两种方式不能同时存在---使用其中的一种即可
1.logging.file.path:
指定日志文件的路径,不指定名称,默认的名称是spring.log
logging:
file:
path: C:\demo\hello3 #日志文件路径
2.logging.file.name:
可以指定指定日志文件的路径和日志文件的称
logging:
file:
name: C:\demo\hello3\hello.log #日志文件名带路径
在此盘的路径中就会存储日志文件信息
2.3如何设置日志级别
日志的级别
TRACE<DEBUG<INFO<WARN<ERROR<FATAL 优先级别
2.4如何设置自己的日志格式
日志格式有哪些??
#%d{yyyy/MM/dd-HH:mm:ss:SSS}日志输出时间
#[%thread]:输出日志的线程名字
#%-5level :日志级别 并且使用5个字符靠左对齐
#%logger-:日志输出者的名字
#%msg :日志消息 %n换行
七.Java 日志框架的选择
成本考虑:Logback文档免费。Logback的所有文档是全面免费提供的,不象Log4J那样只提供部分免费文档而需要用户去购买付费文档
资源开销:Commons Logging相比较与SLF4J开销更高
性能:Logback相比Log4j、Log4j2拥有更好的性能。Logback声称:某些关键操作,比如判定是否记录一条日志语句的操作,其性能得到了显著的提高。这个操作在Logback中需要3纳秒,而在Log4J中则需要30纳秒。LogBack创建记录器(logger)的速度也更快:13毫秒,而在Log4J中需要23毫秒。更重要的是,它获取已存在的记录器只需94纳秒,而Log4J需要2234纳秒,时间减少到了1/23。跟JUL相比的性能提高也是显著的
SpringBoot中默认选择的搭配是:slf4j+logback
八.springboot日志
1.springboot中如何集成日志
ioc和aop?类似springmvc拦截器以及springboot security
2.springboot使用什么日志以及默认日志级别,如何单独指定某个包或者某个文件的日志级别
Springboot默认日志级别:INFO,比INFO级别小的日志不显示,比INFO级别大的显示
3.开启Springboot详细日志
logging.level
两种级别
1.root级别
logging:
level:
root: warn #root:代表的是项目所有日志
如果我们将root日志级别设为warn,则项目的所有INFO日志不再显示,只能显示warn及以上级别的日志
2.package级别
代表指定包下的日志对应的日志级别,不是这个包下才用的是默认的INFO日志级别
两种级别可以同时设置
实例:
在application.properties文件中添加以下代码
logging.level.root=debug #root:代表的是项目所有日志
或者
# 日志配置
logging:
#指定不同目录下的日志的级别
level:
root: warn #root:代表的是项目所有日志
cn.rntd.oauth2.mapper : INFO
cn.rntd.gis.mapper.GridMapper : INFO
cn.rntd: DEBUG
4.文件保存
默认情况下,SpringBoot仅将日志输出到控制台,不会写入到日志文件中去。如果除了控制台输出之外还想写日志文件,则需要在application.properties设置logging.file或logging.path属性。
logging.file:将日志写入到指定的文件中,默认为相对路径,可以设置成绝对路径。
如:logging.file=my.log
logging.path:将名为spring.log写入到指定的文件夹中,如(/var/log)
如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log
日志文件在达到10MB时进行切割,产生一个新的日志文件(如:spring.1.log、spring.2.log),新的日志依旧输出到spring.log中去,默认情况下会记录ERROR、WARN、INFO级别消息。
logging.file.max-size:限制日志文件大小
logging.file.max-history:限制日志保留天数
5.tomcat的catalina.out日志按自定义时间格式进行分割的操作方法: https://www.yingsoo.com/news/servers/72344.html
默认情况下,tomcat的catalina.out日志文件是没有像其它日志一样,按日期进行分割,而是全部输出全部写入到一个catalina.out,这样日积月累就会造成.out日志越来越大,给管理造成了不便,为了实现像其它日志文件一样按日期归档,这里我采用cronolog来完成日志分割。
Tomcat日志自动分割的三种方法:https://www.jb51.net/article/256999.htm
6.springboot内嵌tomcat日志配置及优化:https://www.cnblogs.com/Vincent-yuan/p/15734684.html
九.疑问
1.问题:为什么不直接使用日志实现,而是又弄了一个叫日志门面的东西?
因为日志实现,可能会有一些代码的优化和改动,避免影响用户在项目中的使用,使用日志门面这些统一的接口,假设在实现层代码做了更改,用户在项目中使用日志而调用的接口等等都是不会受影响的。
日志体系:
1.b站讲解地址:黑马程序员java日志框架教程,全面深入学习多种java日志框架_哔哩哔哩_bilibili
资料:链接:https://pan.baidu.com/s/1O0dOPHqQQZfx6Y5vr4RKgQ 提取码:mqeg
2.https://www.cnblogs.com/chenhongliang/p/5312517.html
3.最后:工作总结!日志打印的15个建议
https://blog.csdn.net/qq_43255017/article/details/122725877
桥接器: