欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

控制台的输出为: 2018-03-26 22:57:48.779 [main] INFO java.lang.Objec

点击: 次  来源:宝鼎软件 时间:2018-04-09

原文出处: 五月的仓颉

为什么利用logback

记得前几年岁情的时候,公司利用的日志框架照旧log4j,约莫从16年中到此刻,不管是我参加的别人已经搭建好的项目照旧我本身主导的项目,日志框架根基都换成了logback,总结一下,logback约莫有以下的一些利益:

  • 内核重写、测试充实、初始化内存加载更小,这一切让logback机能和log4j对比有诸多倍的晋升
  • logback很是自然地直接实现了slf4j,这个严格来说算不上利益,只是这样,再领略slf4j的前提下会很容易领略logback,也同时很容易用其改日志框架替换logback
  • logback有较量齐全的200多页的文档
  • logback当设置文件修改了,支持自动从头加载设置文件,扫描进程快且安详,它并不需要别的建设一个扫描线程
  • 支持自动去除旧的日志文件,可以节制已经发生日志文件的最大数量
  • 总而言之,假如各人的项目内里需要选择一个日志框架,那么我小我私家很是发起利用logback。 

    logback加载

    我们简朴阐明一下logback加载进程,当我们利用logback-classic.jar时,应用启动,那么logback会凭据如下顺序举办扫描:

  • 在系统设置文件System Properties中寻找是否有logback.configurationFile对应的value
  • 在classpath下寻找是否有logback.groovy(即logback支持groovy与xml两种设置方法)
  • 在classpath下寻找是否有logback-test.xml
  • 在classpath下寻找是否有logback.xml
  • 以上任何一项找到了,就不举办后续扫描,凭据对应的设置举办logback的初始化,详细代码实现可见ch.qos.logback.classic.util.ContextInitializer类的findURLOfDefaultConfigurationFile要领。

    当所有以上四项都找不到的环境下,logback会挪用ch.qos.logback.classic.BasicConfigurator的configure要领,结构一个ConsoleAppender用于向节制台输出日志,默认日志输格外式为”%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} – %msg%n”。

    logback的configuration

    logback的重点该当是Appender、Logger、Pattern,在这之前先简朴相识一下logback的<configuration>,<configuration>只有三个属性:

  • scan:当scan被配置为true时,当设置文件产生改变,将会被从头加载,默认为true
  • scanPeriod:检测设置文件是否有修改的时距离断,假如没有给出时间单元,默认为毫秒,当scan=true时这个值生效,默认时距离断为1分钟
  • debug:当被配置为true时,将打印出logback内部日志信息,及时查察logback运行信息,默认为false
  • <logger>与<root>

    先从最根基的<logger>与<root>开始。

    <logger>用来配置某一个包可能详细某一个类的日志打印级别、以及指定<appender>。<logger>可以包括零个可能多个<appender-ref>元素,标识这个appender将会添加到这个logger。<logger>仅有一个name属性、一个可选的level属性和一个可选的additivity属性:

  • name:用来指定受此logger约束的某一个包可能详细的某一个类
  • level:用来配置打印级别,五个常用打印级别从低至高依次为TRACE、DEBUG、INFO、WARN、ERROR,假如未配置此级别,昆山软件开发,那么当前logger会担任上级的级别
  • additivity:是否向上级logger通报打印信息,默认为true
  • <root>也是<logger>元素,可是它是根logger,只有一个level属性,因为它的name就是ROOT,关于这个处所,有伴侣微信上问起,源码在LoggerContext中:

    public LoggerContext() {
        super();
        this.loggerCache = new ConcurrentHashMap<String, Logger>();
    
        this.loggerContextRemoteView = new LoggerContextVO(this);
        this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
        this.root.setLevel(Level.DEBUG);
        loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
        initEvaluatorMap();
        size = 1;
        this.frameworkPackages = new ArrayList<String>();
    }

    Logger的结构函数为:

    Logger(String name, Logger parent, LoggerContext loggerContext) {
        this.name = name;
        this.parent = parent;
        this.loggerContext = loggerContext;
    }

    看到第一个参数就是Root的name,而这个Logger.ROOT_LOGGER_NAME的界说为final public String ROOT_LOGGER_NAME = “ROOT”,由此可以看出<root>节点的name就是”ROOT”。

    接着写一段代码来测试一下:

    public class Slf4jTest {
    
        @Test
        public void testSlf4j() {
            Logger logger = LoggerFactory.getLogger(Object.class);
            logger.trace("=====trace=====");  
            logger.debug("=====debug=====");  
            logger.info("=====info=====");  
            logger.warn("=====warn=====");  
            logger.error("=====error=====");  
        }
        
    }