logback配置以及整合到springmvc框架的方法

logback基础知识

logback介绍

参考:https://logback.qos.ch/manual/introduction.html

Logback是由log4j创始人Ceki Gülcü设计的另一个开源日志组件,官方网站: http://logback.qos.ch。The logback manual链接地址为:https://logback.qos.ch/manual/index.html

它当前分为下面几个模块:

logback-core:其它两个模块的基础模块

logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API,使你可以很方便地在logback和其它日志系统如log4j或JDK中的java.util.logging进行切换。

logback-access:访问模块与Servlet容器(如tomcat和jetty)集成,提供通过Http来访问日志的功能。

注意:你可以自己在logback-core之上轻松构建自己的模块

 

日志API比我们使用System.out.println高级在哪里呢?

就比如打印到控制台。通过logback,可以控制消息的格式、消息记录的位置,并且可以根据消息类型和级别来记录消息。如果我不想看到某些级别的消息,直接设置一下就可以了。以上这些都是System.out.println做不到的。

logback的结构

参考:https://logback.qos.ch/manual/architecture.html

Logback基于三个主要类:Logger,Appender和Layout。 这三种类型的组件协同工作,使开发人员能够根据消息类型级别记录消息,并在运行时控制这些消息的格式以及报告的位置

logger context

logger context:各个logger 都被关联到一个 LoggerContext,LoggerContext负责制造logger,也负责以树结构排列各logger。其他所有logger也通过org.slf4j.LoggerFactory 类的静态方法getLogger取得。 getLogger方法以 logger名称为参数。用同一名字调用LoggerFactory.getLogger 方法所得到的永远都是同一个logger对象的引用。

logger

logger:用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>。

作为日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。

<logger>有一个name属性,一个可选的level和一个可选的addtivity属性,可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger中。

root

子节点<root>:它也是<logger>元素,但是它是根logger,是所有<logger>的上级。只有一个level属性,因为name已经被命名为"root",且已经是最上级了。

level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。

appender

appender:主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog daemons。

给定logger的每个启用的日志记录请求都将转发到该logger中的所有appender以及层次结构中较高的appender。例如,如果将控制台appender添加到根记录器,则所有启用的日志记录请求将至少在控制台上打印。 如果另外将文件appender添加到记录器(例如L),则对L和L的子项启用的记录请求将打印在文件和控制台上。 通过将logger的additivity标志设置为false,可以覆盖此默认行为,以便不再添加appender累积。

有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。

ConsoleAppender 把日志输出到控制台

FileAppender:将日志输出到文件,适合java se程序

RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。适合java web程序

layouts

用户通常不仅要定制输出目的地,还要定制输出格式。 这是通过将layouts与appender相关联来实现的。 layouts负责根据用户的意愿格式化日志记录请求,而appender负责将格式化的输出发送到其目的地。 PatternLayout是标准logback分发的一部分,它允许用户根据类似于C语言printf函数的转换模式指定输出格式。

PatternLayoutEncoder

logback日志记录几个原则

遵循继承体系

1) 如果给定的logger没有分配级别,那么它将从具有指定级别的最近祖先继承一个级别

2) 如果所有logger都有一个指定的级别值,级别继承不起作用。

为logger分配级别

logger 可以被分配级别:级别包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定义于ch.qos.logback.classic.Level类。如果 logger没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。

打印方法决定记录请求的级别

打印方法决定记录请求的级别:例如,如果 LOGGER 是一个 logger 实例,那么,语句 LOGGER.info("..")是一条级别为 INFO的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger的有效级别为 q,只有则当 p>=q时,该请求才会被执行。该规则是 logback 的核心。级别排序为: TRACE < DEBUG < INFO < WARN < ERROR。

实际上,logback输出日志是从子节点开始,子节点如果有输出源直接输入。如果无,判断配置的addtivity,是否向上级传递,即是否向root传递,传递则采用root的输出源,否则不输出日志。

例如假设我们不再有兴趣查看属于“chapters.configuration”包的任何组件的任何DEBUG消息。

代码
在chapters.configuration类中LOGGER.debug(‘xxx’);
配置文件
<logger name="chapters.configuration" level="INFO"/>

注意,基本选择规则取决于被调用的LOGGER实例的有效级别,而不是附加了appender的logger的级别。 logback将首先确定是否启用了日志记录语句,如果启用,它将调用logger层次结构中找到的appender,而不管它们的级别如何。

配置文件格式

参考:https://logback.qos.ch/manual/configuration.html

配置configuration

配置文件的基本结构可以描述为<configuration>元素,包含零个或多个<appender>元素,后跟零个或多个<logger>元素,后跟最多一个<root>元素。

根节点<configuration>,包含下面三个属性

scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。

scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。

debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

Logback可以使用内置状态系统报告有关其内部状态的信息。 在logback的生命周期中发生的重要事件可以通过名为StatusManager的组件进行访问。 暂时,让我们通过调用StatusPrinter类的静态print()方法指示logback打印其内部状态。

    // print internal state
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    StatusPrinter.print(lc);

可以看到其内部执行情况

12:49:22.203 [main] DEBUG chapters.introduction.HelloWorld2 - Hello world.
12:49:22,076 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
12:49:22,078 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
12:49:22,093 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration.

配置property

子节点<property>

将默认配置文件的位置指定为系统属性

<property resource="db.properties" />

配置contextName

子节点<contextName>:用来设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用<contextName>设置成其他名字,用于区分不同应用程序使用同一日志文件(在pattern中使用%contextName)的记录。

 

配置logger

使用<logger>元素配置记录器。 <logger>元素只接受一个必需的name属性,一个可选的level属性和一个可选的additivity属性,允许值为true或false。 level属性的值允许一个不区分大小写的字符串值TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF。

<logger>元素可以包含零个或多个<appender-ref>元素; 这样引用的每个appender都被添加到指定的logger中。

 

<root>元素配置根记录器。 它支持单个属性,即level属性。 它不允许任何其他属性,因为additivity标志不适用于根记录器。 此外,由于根记录器已被命名为“ROOT”,因此它也不允许使用name属性。 level属性的值可以是不区分大小写的字符串TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF之一。

与<logger>元素类似,<root>元素可以包含零个或多个<appender-ref>元素; 这样引用的每个appender都被添加到根记录器中。

 

配置appender

appender使用<appender>元素配置,该元素采用两个必需属性name和class。 name属性指定appender的名称,而class属性指定要实例化的appender类的完全限定名称。 <appender>元素可以包含零个或一个<layout>元素,零个或多个<encoder>元素以及零个或多个<filter>元素。

LevelFilter根据精确的级别匹配过滤事件。 如果事件的级别等于配置的级别,则筛选器接受或拒绝该事件,具体取决于onMatch和onMismatch属性的配置。

例如下面这个appender,只显示error信息

<appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--日志文件输出的文件名 -->
        <fileNamePattern>${log.path}/%d{yyyyMMdd}/monitor-web.%d{yyyy-MM-dd}.error.log</fileNamePattern>
        <!--日志文件保留天数 -->
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
            %msg%n
        </pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>

默认情况下,appender是累积的:记录器将记录到自身附加的appender(如果有的话)以及附加到其祖先的所有appender。 因此,将相同的appender附加到多个记录器将导致日志记录输出重复。

解决方法为将指定logger的additivity标志设置为false,以使其日志记录输出将发送到名为FILE的appender,但不会发送到层次结构中较高的任何appender。

springmvc中实际使用

1. 配置maven依赖

注意:Logback-classic模块还需要存在slf4j-api.jar和logback-core.jar。而slf4j是一个单独的项目。

    <properties>
        <logback.version>1.1.3</logback.version>
    </properties>
	<!-- logback日志配置开始 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.logback-extensions</groupId>
            <artifactId>logback-ext-spring</artifactId>
            <version>0.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.12</version>
        </dependency>
    <!-- logback日志配置结束 -->

2. 在web.xml中配置logback

  <!--logback配置开始-->
  <!--尽管后面servlet也配置了contextConfigLocation,但这里是不能省略的-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
 <context-param>
    <param-name>logbackConfigLocation</param-name>
    <param-value>classpath:logback.xml</param-value>
  </context-param>
 <!--自定义监听器-->
  <listener>
    <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
  </listener>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
  <!--logback配置结束-->

3. 在classpath下新建logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 属性描述
	 scan:设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true
	 scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
     debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration debug="false">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
    <property resource="config.properties"/>

    <!-- 控制台输出日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
                %msg%n
            </pattern>
        </encoder>
    </appender>

    <!-- 按文件大小区分的滚动ALL-OUT日志 -->
    <appender name="ALL-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${log.path}/%d{yyyyMMdd}/monitor-web.%d{yyyy-MM-dd}-%i.log</FileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>


    <!-- 按照每天生成INFO-OUT日志文件 -->
    <appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名 -->
            <FileNamePattern>${log.path}/%d{yyyyMMdd}/monitor-web.%d{yyyy-MM-dd}.info.log</FileNamePattern>
            <!--日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
        </encoder>
        <!--在多数的Log工具中,级别是可以传递,例如如果指定了日志输出级别为DEBUG, 那么INFO、ERROR级别的log也会出现在日志文件。
            这种默认给程序的调试带来了很多的麻烦。通过配置Filter 来严格控制日志输入级别-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 按照每天生成WARN-OUT日志文件 -->
    <appender name="WARN-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名 -->
            <FileNamePattern>${log.path}/%d{yyyyMMdd}/monitor-web.%d{yyyy-MM-dd}.warn.log</FileNamePattern>
            <!--日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 按照每天生成ERROR-OUT日志文件 -->
    <appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名 -->
            <fileNamePattern>${log.path}/%d{yyyyMMdd}/monitor-web.%d{yyyy-MM-dd}.error.log</fileNamePattern>
            <!--日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
                %msg%n
            </pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

<!--logback设置第三方包中的日志显示-->
    <logger name="org.springframework" level="INFO"/>
    <logger name="net.sf.ehcache" level="WARN"/>
    <logger name="org.apache" level="INFO"/>
    <logger name="org.quartz.core" level="INFO"/>
    <logger name="org.springframework.web.servlet.view.JstlView" level="DEBUG"/>
    <logger name="httpclient.wire.content" level="WARN"/>
    <logger name="org.springframework.web.util.NestedServletException" level="FATAL"/>
    <logger name="com.mchange.v2" level="INFO"/>


    <!--JdbcTemplate的日志输出器 -->
    <logger name="org.springframework.jdbc.core.StatementCreatorUtils"
            additivity="false" level="TRACE">
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="org.springframework.jdbc.core.springframework.jdbc.core.BeanPropertyRowMapper"
            additivity="false" level="INFO">
        <appender-ref ref="STDOUT"/>
    </logger>

    <logger name="org.springframework.jdbc.core" additivity="true">
        <level value="INFO"/>
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="java.sql.Connection" additivity="true">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="java.sql.Statement" additivity="true">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="java.sql.PreparedStatement" additivity="true">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="java.sql.ResultSet" additivity="true">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
    </logger>
    <logger name="java.sql.ResultSet" additivity="true">
        <level value="DEBUG"/>
        <appender-ref ref="STDOUT"/>
    </logger>


    <!-- 日志输出级别 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="ALL-OUT"/>
        <appender-ref ref="INFO-OUT"/>
        <appender-ref ref="WARN-OUT"/>
        <appender-ref ref="ERROR-OUT"/>
    </root>
    <!--日志异步到数据库 -->

</configuration>

4. 使用,在Class类中写

private static final Logger logger = LoggerFactory.getLogger(SessionManager.class);
logger.debug("使用单用户单点登录模式");

我们说方法包含一个级别为DEBUG的日志语句,并带有消息“使用单用户单点登录模式”。

请注意,上面的示例不引用任何logback类。在大多数情况下,就日志记录而言,您的类只需要导入SLF4J类,因此,绝大多数(如果不是全部)类将使用SLF4J API,并且将忽略logback的存在。

总结

总结来说,logback可以实现以下需求

1. 如果appender不设置filter level,那么默认是debug,基本上可以把所有的日志都记录下来

2. 通过为appender设置filter level,可以将某个级别的日志过滤出来

3. 通过设置logger level级别,可以启用或关闭指定类的日志记录功能

4. 通过设置logger addtivity=false,避免logger和root重复记录日志功能

参考:logback的使用和logback.xml详解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值