Spring Boot 中 Logback 实战
一直以来参与的项目都是老项目,由于历史原因,项目中一直在使用log4j纪录日至。
技术的更新日新月异,新技术层出不穷,都是奔着性能越来越强大,用法越来越简单,功能越来越丰富来的。
新项目中推荐使用新技术,于是寻找新技术时发现,在Java世界中,日至纪录这一小小领域的哪些框架实现jar包,多的足以让人眼花缭乱。
在梳理这些日至框架之前,稍微淡定的回想一下就会发现,按照Java的套路,一搬都是先有一些规范(也就是借口),然后各大机构厂商推出自己的实现。
比如JDBC,JMS和Servlet规范等等,现有接口,然后再有各种接口的实现,于是才有我等码农的幸福时光。
但是框架太多有时候也会给选择困难症患者带来困扰,迫切需要拨开迷雾。
1. 日志接口系列
参考 xingoo 博客 日志那点事儿——slf4j源码剖析
目前用于实现日志统一的框架apache的commons-logging、slf4j,供用户使用,而没有提供实现,log4j,logback等等才是日志的真正实现。
当我们调用接口时,接口的工厂会自动寻找恰当的实现,返回一个实现的实例给我服务。这些过程都是透明化的,用户不需要进行任何操作!
这里有个小故事,当年Apache说服log4j以及其他的日志来按照commons-logging的标准编写,但是由于commons-logging的类加载有点问题,
实现起来也不友好,因此log4j的作者就创作了slf4j,也因此而与commons-logging两分天下。至于到底使用哪个,由用户来决定吧。
这样,slf4j出现了,它通过简单的实现就能找到符合自己接口的实现类,如果不是满足自己标准的日志,可以通过一些中间实现比如上面的slf4j-log4j12.jar来进行适配。
2.选择logback
LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。
并且spring boot 默认使用logback,项目中使用spring boot时使用logback最方便。
另,Log4j2 是Log4j的重构版本,同时吸收了logback的优点,但是在srping boot中使用添加Maven依赖时略为繁琐,因此项目中选用logback纪录日志。
3.Spring boot 中引入 logback依赖
基于spring boot的web程序需要在Maven的pom文件中首先配置如下的parent
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent>
以及如下的 dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
4. logback配置文件
与使用log4j类似,实用logback也需要一个xml配置文件,用来配置日志文件的位置,每个日志的级别等。
配置文件logback.xml放到classpath中即可,系统启动时,logback可以自动查找然后加在配置。
logback查找配置文件的步骤(参考 http://logback.qos.ch/manual/configuration.html)
- 1)Logback tries to find a file called logback.groovy in the classpath.
- 2)If no such file is found, logback tries to find a file called logback-test.xml in the classpath.
- 3)If no such file is found, it checks for the file logback.xml in the classpath..
- 4)If no such file is found, service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of com.qos.logback.classic.spi.Configurator interface by looking up the file META-INF\services\ch.qos.logback.classic.spi.Configurator in the class path. Its contents should specify the fully qualified class name of the desired Configurator implementation.
- 5)If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console. The last step is meant as last-ditch effort to provide a default (but very basic) logging functionality in the absence of a configuration file.
5. 配置logback
配置logback主要是为了满足日志需求,包括,日志文件位置,日志级别,日志文件大小控制策略,日志格式等。
一般日志的需求有:
1) 日志需要 纪录到控制台 和 文件中
2) 不同的日志需要不同的日志级别
3) 日志文件不能太大,当日志文件达到一定大小时,能够自动生成一个新的日志文件,并将日志记录到这个新文件中
4) 可以每天生成一个新日志文件,并用当天日期给日志文件命名
5) 日志消息格式化,比如需要包含日志打印的时间,打印日志的位置,等,
使用%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{0} – %msg %caller{1}配置logback
实际打印出来的日志格式如下:
2017-01-12 14:11:46.962 [http-nio-8080-exec-1] ERROR ROLLINGFILE_LOG – ~~~~~~~~~~~~~~~~~~ROLLINGFILE_logger – error Caller+0 at com.jack.yin.spring.boot.web.controller.UserController.getUser(UserController.java:32)
下面配置文件实例基本可以满足以上需求,配置文件中,
appender标签配置日志文件的位置,以及控制日志文件的位置,文件大小等,rollingPolicy标签配置日志文件的大小控制策略,并且可以每天生成一个新的配置文件;
logger标签配置将日志记录器和日志文件关联起来,logger的name属性用于在程序中通过代码查找到配置的日志记录器,程序中使用
final static Logger FILE_logger = LoggerFactory.getLogger(“FILE_LOG”);
来获取一个已经配置好的已命名的日志记录器,然后调用FILE_logger.debug()方法就可以往配置的日志文件中记录日志了;
root 标签 用于配置一个默认的日志记录器,当LoggerFactory.getLogger(“Unknow_logger_name”);中传入的参数没有在logger的name中配置时,就会获取到root配置的默认的日志记录器。
另外,logger的additivity=”false”属性表示当前的日志之纪录到当前的logger中,不会再记录到root中,即不会再向上传递,如果additivity=”true”(默认值)表示,当前的日志除了记录到当前的
日志记录器以外,还会传递到root配置的日志中。
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <contextName>Logback Configuration</contextName> <property name="LOG_HOME" value="C:/logs/test" /> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoder默认配置为PartternLayoutEncoder --> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg %caller{1}</pattern> </encoder> </appender> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${LOG_HOME}/file-log.log</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg %caller{1}</pattern> </encoder> </appender> <!-- 按照每天生成日志文件 --> <appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>${LOG_HOME}/rolling-%d{yyyy-MM-dd}.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{0} - %msg %caller{1}</pattern> </encoder> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>1MB</MaxFileSize> </triggeringPolicy> </appender> <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" additivity="false" /> <logger name="FILE_LOG" level="DEBUG" additivity="false"> <appender-ref ref="FILE"/> </logger> <logger name="ROLLINGFILE_LOG" level="DEBUG"> <appender-ref ref="ROLLINGFILE"/> </logger> <root level="ERROR"> <appender-ref ref="STDOUT" /> <appender-ref ref="ROLLINGFILE" /> </root> </configuration>
赞 赏
微信赞赏 支付宝赞赏