zoukankan      html  css  js  c++  java
  • 面试题:应用中很多jar包,比如spring、mybatis、redis等等,各自用的日志系统各异,怎么用slf4j统一输出?(上)

    一、问题概述

    如题所说,后端应用(非spring boot项目)通常用到了很多jar包,比如spring系列、mybatis、hibernate、各类连接数据库的客户端的jar包。可能这个jar包用的是logback、那个用的是log4j、那个又是log4j2,

    这时候,怎么才能保证各jar包的日志都能输出,且能以统一的格式输出呢?

    为什么要强调非spring boot项目,可参考第四节。

    二、几种日志框架的简单介绍

    来源:https://juejin.im/post/5a7c5d575188254e76179c0f

    Java中的日志框架分如下几种:

    1.Log4j   

     Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。

    2.Log4j 2

    Apache Log4j 2是apache开发的一款Log4j的升级产品。

    3.Commons Logging

    Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging。

    4.Slf4j

    Slf4j 类似于Commons Logging,是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)。

    5.Logback

    一套日志组件的实现(slf4j阵营)。

    6.Jul (Java Util Logging)

    自Java1.4以来的官方日志实现。

    上面这几个框架,又分为了两类:一类是接口,包括了slf4j、commons logging;剩下的几个是具体实现,包括了jul、logback、log4j、log4j2。

    现在,讲究针对接口编程,而不是针对具体实现,方便移植。而现在最通用的就是slf4j。就我待过的几家公司来说,全都都用的是slf4j作为日志门面,具体的实现一般直接采用默认的logback。

    下面就具体讲讲,怎么将其他框架五花八门的日志一统为slf4j。

    三、统一的思路

    我们先分析下。

    假设有个jar采用了JUL,即java自带的日志系统。我们要怎么才能将其适配到slf4j去呢?

    在JUL的logger的方法被调用时,因为Logger所在的包位于java.util,默认就被加载了,不太方便以假乱真。

    想要覆盖其实现,我能想到的是,通过aop切面,直接将参数传给slf4j的api,不调用原来的日志实现。

    再来,假设有个jar采用了log4j,即写日志用的是org.apache.log4j.Logger,该类是来源于log4j的相关jar包,那么,

    我可以排除掉log4j相关的jar包,代码里报错了,对吧?那我再建一个相同package名、相同类名的class。在这个假的

    class里,我去调用slf4j的api。

    那么,这些功能需要我自己去写吗?不需要!slf4j已经给我们提供了从各类日志框架九九归一到slf4j的转换包。

    源日志框架 目标日志框架 所需转换用jar包 maven(这里缺了version字段,请参考下一节)  备注
    jul   slf4j
    jul-to-slf4j
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    </dependency>
     需要排除掉原有依赖。
    Commons Logging slf4j
    jcl-over-slf4j
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

    需要排除掉原有依赖。

    log4j slf4j
    log4j-over-slf4j
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    </dependency>
    需要排除掉原有依赖。
    log4j2 slf4j  
    log4j-to-slf4j
    <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.8.2</version>
    </dependency>

    需要排除掉原有依赖。

    注意这里使用的为

    log4j-to-slf4j

    这里给一张slf4j官方手册里的,也是漏了log4j2的。

    四、如何选择以上转换jar包的版本

    在spring boot中,其实根本不需要以上的麻烦工作,只需要引用以下组件:

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    <version>1.5.9.RELEASE</version>
    </dependency>
    我们看看这个组件里,包含了什么:
    可以看到,log4j、jul、jcl(即commons-logging)的转换包都有了。

    那么,在非spring boot项目中,我们只要去mvnrepository.com查询:spring-boot-starter-logging.
    然后,选择对应的版本,就可以在下图看到该组件依赖的包:

    怎么样,应该是个比较简单的办法吧?

    五、未完成的统一之路

    这一篇里面,我们还只讲了如何将各日志框架统一到slf4j来。

    但是slf4j只是个门面,具体的实现呢(比如log4j等)又被我们排除掉了。

    那么slf4j没有实现,也是不能完成输出日志的任务的。

    所以我们还需要一个实现。这份留到下篇仔细讲。

    六、github代码(已实现上述的统一问题,默认实现采用了logback)

    代码路径:

    https://github.com/cctvckl/logtest

    这里演示下效果:

    下面是统一后的:

    其中jul为什么日志未统一,等有时间了我再看看。这两天时间有点紧,要开发需求。。。

    
    
  • 相关阅读:
    数据科学工作中存在的7大问题与解决方案
    搞定SEO,看这一篇就够了
    李宏毅老师机器学习课程笔记_ML Lecture 3-1: Gradient Descent
    李宏毅老师机器学习课程笔记_ML Lecture 2: Where does the error come from?
    李宏毅老师机器学习课程笔记_ML Lecture 1: ML Lecture 1: Regression
    李宏毅老师机器学习课程笔记_ML Lecture 1: 回归案例研究
    python爬取中国大学排名
    爬虫实战_爬取静态单张图片
    李宏毅老师机器学习课程笔记_ML Lecture 0-2: Why we need to learn machine learning?
    多线程基础(一)
  • 原文地址:https://www.cnblogs.com/grey-wolf/p/9884565.html
Copyright © 2011-2022 走看看