Java常用日志框架+Logback的应用实例

12 篇文章 0 订阅
2 篇文章 0 订阅

一、Java常用日志框架

1)1996年左右,以Ceki Gulcu(切基·古尔库)为首的团队创建了Log4j,后被Apache收归麾下;
2)2002年Sun公司推出了日志库JUL(java util logging),基本照搬Log4j,后来Sun也被Google收购,JUL自然也成为Apache的一员;
3)后来Apache又推出了Commons Logging,组成了日志接口Commons Logging,实现可选Log4j或JUL的架构;
4)2006年Ceki Gulcu离开Apache,先后创建了Slf4j和Logback,组成了日志接口Slf4j,实现以Logback为主的架构;
5)至此,java界两大日志框架阵营形成,主流应用都选这两个组合中的一个,由于Slf4j在各项性能及接入方式上都优于Commons Logging,而且Slf4j完全开源、而Commons Logging部分开源,所以Slf4j大有后来者居上的趋势。
现在,如果接手老项目,就沿用以前的的日志框架;如果是新建项目,建议用Slf4j的组合。

二、Logback应用(Slf4j接口,Logback实现)

1、约定

<!--
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.4</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.0.6</version>
    </dependency>
-->

<!-- 该依赖包括了上面两个依赖,所以只要引入该依赖即可 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.0.6</version>
</dependency>

如果是springboot项目,spring-boot-starter这个依赖其中包含了 spring-boot-starter-logging,这种情况下就不用再另外加logback依赖了。

2、配置

1)默认配置

在用户没有对logback进行任何配置的情况下,logback会使用默认配置输出简单的日志到控制台。
但在实际工作中,我们通常对日志的输出有很多要求,比如设定日志的格式、要求日志文件按天分割、将日志文件按大小进行分割、定期删除旧日志等,所以一般都要建专门日志配置文件,用于管理logback的输出格式、级别等;这个文件一般放在resource文件夹下,一般命名为lockback.xml。
项目启动时,如果检测到在项目的classpath路径下存在logback.xml(或者logback-test.xml、logback.groovy),logback框架能够自动扫描到它、并读取配置。

2)根节点configuration

配置文件的根节点是configuration,它有三个属性,scan、scanPeriod、debug,一般都采用默认设置。

<configuration>
	...
</configuration>

configuration节点主要又包含appdender、logger、root三个标签,如下图:
在这里插入图片描述

3)一级子节点property

property标签,用来定义一些常用的变量,比如日志输出格式、很多地方会用到,而且一般格式都是一样的;用property配置以后,后面就可以用${name值}来引用自定义的配置。
当然,property设置了以后,其他各处还是可以不用。

<configuration>

	<!--配置日志文件格式-->
    <property name="pattern" value="%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger] %msg%n"/>
    <!--配置日志路径-->
    <property name="logPath" value="/backup/logs/jboss/bdp/log"/>
    <!--配置日志文件名-->
    <property name="appName" value="bdpadmin"/>
    
<configuration/>

4)一级子节点appender

appender标签,用来配置日志的输出位置、格式等等,标签主要有两个属性:name和class;
根据class不同,appender有不同功效,这里介绍几个常用的appender类型:

a、ch.qos.logback.core.ConsoleAppender

ConsoleAppender类型的appender标签,配置在控制台输出的日志。主要是设置它的二级子标签<encoder>的两个三级子标签:
<pattern>设置日志输出格式;
<charset>设置字符集,防止乱码

<configuration>

  	<!-- 输出到控制台 -->
    <appender name="print-on-console" class="ch.qos.logback.core.ConsoleAppender" >
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        	<!-- 输出的格式,这里使用property配置的常量 -->
            <!-- <pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger] %msg%n</pattern> -->
            <pattern>${pattern}</pattern>
            <!-- 字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

</configuration>
b、ch.qos.logback.core.rolling.RollingFileAppender

RollingFileAppender类型的appender标签,配置输出到文件的日志。
RollingFileAppender还提供了切割日志文件的功能,它首先将日志记录到一个自定义名称的文件中,一旦满足设置条件(一定大小、或者一定时间)之后,它会将新产生的日志记录到新文件中。

<configuration>

  	<!-- 输出到日志文件 -->
    <appender name="print-to-file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    	<!-- 配置日志地址、名称 -->
    	<file>${logPath}/${appName}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>${pattern}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 配置滚动的策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 配置滚动日志名称 -->
            <fileNamePattern>${logPath}/${appName}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每天生成新日志文件,如果文件超过30M,则再生成一个新的日志文件 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>3MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    
</configuration>

如果还要配置日志文件的保存时间,可以在<rollingPolicy>标签下加

	<!-- 保存的最长时间:天数 -->
    <MaxHistory>30</MaxHistory>

5)一级子节点logger、root——配置日志有效级别

a、有效级别

日志是有级别的,从低到高为:TRACE < DEBUG < INFO < WARN < ERROR
logback是否打印某条日志,取决于这条日志的级别:
如果这条日志等于或高于logger、root配置的级别,那这条日志就属于有效级别,logback就会打印这条日志;反之,如果这边日志低于logger、root配置的级别,那这条日志就属于无效级别,logback就不会打印它。
比如root配置有效级别为error,那么
log.info(“…”)就不会被打印,
而log.error(“…”)才会被打印。

那么,都是配置有效级别,root和logger有什么区别呢?
简单来说就是root配置的是大多数日志的有效级别;
而logger配置的是个别部分的日志级别。
需要特殊设置的部分就用logger配置,剩下的都看root配置。

b、logger

logger用来为单独的包配置日志级别。
应用场景:生产环境root一般设置比较高,这样可以降低打印日志的资源消耗。
但是有些功能,又需要很详细的日志、以备将来定位问题;比如mybatis、sql相关的部分。
这时就可以通过logger为这些部分,设置专门的日志级别debug;如此一来,日志文件中就会出现mybatis的debug级别日志, 而其它包则会按root的级别输出日志

<configuration>

	<logger name="com.ibatis" level="DEBUG" />  
	<logger name="java.sql.Connection" level="DEBUG"/>
	<logger name="java.sql.Statement" level="DEBUG"/>
	<logger name="java.sql.PreparedStatement" level="DEBUG"/>
	<logger name="org.springframework" level="ERROR" />

<configuration/>
c、root

生产环境,应该配置合适的级别,以降低消耗

<configuration>

	<root level="debug">
        <!-- 控制台输出 -->
        <appender-ref ref="print-on-console" />
    </root>
    <root level="info">
        <!-- 文件输出 -->
        <appender-ref ref="print-to-file"/>
    </root>

<configuration/>

6)应用实例

将上述配置总结一下,就是logback.xml的应用实例

<configuration>

	<!--配置日志文件格式-->
    <property name="pattern" value="%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger] %msg%n"/>
    <!--配置日志路径-->
    <property name="logPath" value="/backup/logs/jboss/bdp/log"/>
    <!--配置日志文件名-->
    <property name="appName" value="bdpadmin"/>

	<!-- 输出到控制台 -->
    <appender name="print-on-console" class="ch.qos.logback.core.ConsoleAppender" >
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        	<!-- 输出的格式,这里使用property配置的常量 -->
            <!-- <pattern>%d{HH:mm:ss.SSS} [%-5level] [%thread] [%logger] %msg%n</pattern> -->
            <pattern>${pattern}</pattern>
            <!-- 字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

	<!-- 输出到日志文件 -->
    <appender name="print-to-file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    	<!-- 配置日志地址、名称 -->
    	<file>${logPath}/${appName}.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>${pattern}</Pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 配置滚动的策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 配置滚动日志名称 -->
            <fileNamePattern>${logPath}/${appName}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每天生成新日志文件,如果文件超过30M,则再生成一个新的日志文件 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>3MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

	<logger name="com.ibatis" level="DEBUG" />  
	<logger name="java.sql.Connection" level="DEBUG"/>
	<logger name="java.sql.Statement" level="DEBUG"/>
	<logger name="java.sql.PreparedStatement" level="DEBUG"/>
	<logger name="org.springframework" level="ERROR" />

	<root level="debug">
        <!-- 控制台输出 -->
        <appender-ref ref="print-on-console" />
    </root>
    <root level="info">
        <!-- 文件输出 -->
        <appender-ref ref="print-to-file"/>
    </root>

<configuration/>

三、Logback实际应用中遇到的一些问题

1、RollingFileAppender标签,试图对日志文件名动态配置%d{yyyy-MM-dd}不起作用

	<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}.%d{yyyy-MM-dd}.log</file>
        ...
    </appender>

在这里插入图片描述
原因:RollingFileAppender标签下的<file>标签并不支持日期pattern动态设置,不生效是正常的。应该将其改为

	<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logPath}/${appName}.log</file>
        ...
    </appender>

但是,日志文件触发切割条件后,切割日志文件名的动态配置是支持的
在这里插入图片描述
最终效果
在这里插入图片描述

2、tomcat、日志文件乱码

控制台看到打印日志乱码如下:
在这里插入图片描述
而日志文件用记事本打开不乱码:
在这里插入图片描述

用sublime打开乱码
在这里插入图片描述
关于这个问题,分析如下:

不同的文本编辑器默认的字符集不同,所以才会出现对同一文件,不同编辑器打开有的乱码、有的正常这种现象。

如果控制台logback输出的日志乱码,将ConsoleAppender中的字符集设为utf-8即可解决。
如果日志文件乱码,就将RollingFileAppender中的字符集设为utf-8。
在这里插入图片描述
logback.xml字符集都设置好了,再用某个编辑器、比如sublime打开,如果还是乱码,那就看一下sublime的字符集是啥?给改成utf-8,就不乱了。

3、java程序中获取logger日志对象

1)org.slf4j包下有个LoggerFactory类,LoggerFactory有个getLogger()方法,可以方便的获取一个Logger对象(org.slf4j包下的)。
getLogger()方法,入参填当前类的.calss,或者当前类的.class.getName()。

public class Abc {
    private static Logger logger = LoggerFactory.getLogger(Abc.class);
}

//或者

public class Abc {
    private static Logger logger = LoggerFactory.getLogger(Abc.class.getName());
}

2)接手旧项目、或者中途修改过项目日志框架(由log4j改为logback),注意修改获取日志对象的方法,对象创建工厂不要错用org.apache.log4j包的LogManager,下面这个是log4j的

private static Logger logger = LogManager.getLogger(PushController.class.getName());

4、springboot项目整合logback

1)实际开发中如果是springboot项目,不需要我们添加logback的依赖,这是因为spring-boot-starter这个依赖其中包含了 spring-boot-starter-logging,这个包下有所有日志框架需要的依赖(也包含log4j的依赖);

2)如果项目中使用了lombok插件,写日志时甚至都不用创建日志对象,只要在需要日志的类上加一个@Slf4j,就可以直接在方法中用 log.info();或者log.error();等写日志了,非常简单方便。
@Slf4j注解是lombok的一个注解,它会为类提供一个属性名为log的slf4j日志对象。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值