平时写代码目前也开始慢慢体会到了日志的重要作用。日志算是java工具体系的一个知识点,但又是写代码的时候绕不过去的一个知识点,以故事的形式来对目前市场上常见的一些日志框架进行一个介绍和梳理。旨在从整个日志体系的角度进行一次梳理。

阶段一:

从前有一个程序员,名字叫张三,张三呢,每天矜矜业业,业务能力代码能力都很强。老板就让他负责一个比较复杂的系统。于是张三呢,每天使用System.out.println(),在控制台打印出来一些关键的信息。这时候麻烦来了,项目需要上线了,总不能还要把这些没用的信息输出到控制台吧,于是老板让张三把这些语句全部去掉。这么庞大的系统,张三找呀找,终于把所有的System.out语句全部注释掉了。

阶段二:

过了一段时间呢,项目遇到了一些问题,老板突然想起来张三之前写过System.out的相关语句,觉得有必要把一些关键信息打印出来,于是又让张三把所有的System.out语句添加进来,这下子又把张三忙活的不轻,累了一天终于又改过来了。在找出错误之后,然后再重新去掉。

阶段三:

就这样来回折腾了几次,把张三气的不轻,毕竟需求总是会不断的变化的,于是张三考虑做一个框架,记录系统运行的一些必要的信息,而且日志的内容可以随时打印,也可以随时关闭。这个框架就叫做日志框架,在这里且命名为logging-jar。于是开始投入了运行。

阶段四:

又过了一段时间,张三又发现了问题。在设计的第一代日志框架logging-jar中,总是会把各种各样的运行信息打印出来,这对于张三来说只想要找出一些错误信息,他必须要在很长的一个控制台去寻找。于是张三考虑着如何改进这个框架,比如说把输出信息分类,有异常信息,有错误信息,还有警告信息等等。这对于张三来说,开发起来太便利了。叫做logging-good-jar。

阶段五:

老板一看,张三业务能力这么强,干脆把其他的一些项目也让张三带吧,于是张三又负责了一些其他的项目,但是问题又来了,其他的项目使用的不是张三的日志框架,而是其他的日志框架,怎么办呢?张三考虑着把这个项目的去掉,换成自己的不就可以了嘛,于是张三去掉了别人的,换成了自己的,又废了半天功夫更改了大量的日志api代码。

阶段六:

随着张三业务能力的不断增强,负责的项目也越来越多,发现每次都要更改别人的日志框架换成自己的。实在是麻烦。于是张三考虑定义一些规则接口,其他的任何框架都要有相应的实现方法,这样做的好处就是每次张三就不需要去掉别人的,换成自己的。而是调用相应日志框架的相关实现即可。这个规则就叫做日志门面,也叫做日志框架的抽象层。实现这些规则接口的框架就叫做日志实现框架。

这种就好比是定义好一个接口,这个接口就是日志门面。而日志实现框架就是接口的实现类。

目前最受欢迎的就是这么几个。按照使用的角度来说,那就是左边选择一个日志门面,右边选择一个日志实现就好了。就这样他们之前进行了激烈的竞争。

Ceki Gülcü是一个java大佬,一开始发明了log4j,后来把这个捐给了Apache基金会,后来觉得这个功能不够牛,又发明了logback。后来又设计了slf4j。

阶段七:

随着时间的流逝,slf4j门面和logback日志实现框架脱颖而出。于是平时张三就用这个了。但是我们需要知道的是在使用的时候其实用的是日志门面slf4j的方法,而不用关心是哪一个实现的。springboot开发团队,一看这个搭配使用起来是真的好,于是就选用了他俩了。既然这么好,干脆我们使用springboot来整合一下他们俩。

第一步:添加依赖

 <dependency>
     <groupId>ch.qos.logback</groupId>
     <artifactId>logback-classic</artifactId>
</dependency>
<dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>jcl-over-slf4j</artifactId>
</dependency>
复制代码

第二步:配置日志

在  src\main\resources 路径下创建logback.xml配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="/home" />
    <!--控制台日志, 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!--文件日志, 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!--myibatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>
    <!-- 日志输出级别 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE"/>
    </root>
</configuration>
复制代码

上面的这些都是模板代码,你可以直接拿来用。下面我们就直接使用。

第三步:使用

@RestController
@RequestMapping("/logging")
public class Hello{
    @Autowired
    private HelloService helloService;
    private final static Logger logger
            = LoggerFactory.getLogger(Hello.class);
    @GetMapping("/test")
    public String test(){
        logger.info("这是日志框架的输出信息");
        return helloService.test();
    }

}
复制代码

运行结果就不展示了。