zoukankan      html  css  js  c++  java
  • [J2EE:中间件]LOG4J+Slf4J快速入门

    1 简述

    1.1 简述

    commons-logging和slf4j(slf4j-api.jar)都是日志类库的接口,供客户端使用,而没有提供实现!
    log4j,logback等等才是日志的真正实现。

    • 日志(类库)
      • 作用:可以调试程序,就像输出一样
    • Java语言的日志类库:
      • Log4J [Log For Java]
        • log4j 是Apache为java提供日志管理的工具
        • 真正实现日志功能的日志类库
      • Logback
      • java.util.logging
      • SLF4J [Simple Logging Facade(外观/表面) For Java]
        • 1个 日志标准/适配器
          • 通过调用slf4j的API统一打印日志,而可忽略其他日志的具体方法
    • slf4j只是1个日志标准,并不是日志系统的具体实现。如果项目只有slf4j的包,是没有办法实现日志功能的。
    • 而如果开发者已使用log4j,那么:开发者已经对于在if条件中使用debug语句这种变通方案十分熟悉了,但SLF4J的占位符就比这个好用得多。

    1.2 安装/依赖[slf4j+log4j]

    方式1:手动导入JAR包(slf4j-api-1.7.5.jar、slf4j-log4j-1.7.5.jar、log4j-1.2.16.jar)或配置如下Maven依赖:

    • slf4j-api:提供接口
    • slf4j-log4j[xx]:提供Log具体的实现
    <!-- Log4j 依赖包 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.9.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.9.1</version>
    </dependency>
    <!-- slf4j 依赖包 -->
    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.2</version>
    </dependency>
    

    1.3 配置文件

    log4j.properties
    log4j.xml
    log4j2.xml(log4j/org.apache.logging.log4j:log4j在2.0.0及以后,被拆分为 log4j-api与log4j-core,对应的配置文件为 log4j2.xml)

    2 LOG4J

    2.0 Log4J的配置

    如果没有调用BasicConfigurator.configure(),PropertyConfigurator.configure()或DOMConfigurator.configure()方法,Log4j会自动加载CLASSPATH下名为log4j.properties的配置文件。如果把此配置文件改为其他名字,例如my.properties,程序虽然仍能运行,但会报出不能正确初始化Log4j系统的提示。这时可以在程序中加上:PropertyConfigurator.configure("classes/my.properties");

    配置Log4j环境就是指配置root Logger,包括把Logger为哪个级别,为它增加哪些Appender,以及为这些Appender设置Layout,等等。因为所有其他的Logger都是root Logger的后代,所以它们都继承了root Logger的性质。这些可以通过设置系统属性的方法来隐式地完成,也可以在程序中调用XXXConfigurator.configure()方法来显式地完成。有以下几种方式来配置Log4j。

    • A:配置放在文件里,通过环境变量传递文件名等信息,利用Log4j默认的初始化过程解析并配置。
    • B:配置放在文件里,通过应用服务器配置传递文件甸等信息,利用一个特定的Servlet来完成配置。
    • C:配置放在文件里,通过命令行org.apache.log4j.PropertyConfigurator.configure(args[])解析log4j.properties文件并配置Log4j
    • D:配置放在文件里,在程序中直接调用org.apache.log4j.BasicConfigor.configure()方法,或在程序中完成相关配置(↓)
      • step1:用默认的方式创建PatternLayout对象p:
        • PatternLayout p = new PatternLayout("%-4r[%t]%-5p%c%x-%m%n");
      • step2: 用p创建ConsoleAppender对象a,目标是System.out,标准输出设备:
        • ConsoleAppender a = new CpnsoleAppender(p,ConsoleAppender.SYSTEM_OUT);
      • step3: 为root Logger增加一个ConsoleAppender p:
        • rootLogger.addAppender(p);
      • step4: 把rootLogger的log level设置为DUBUG级别
        • rootLogger.setLevel(Level.DEBUG);
    • E:org.apache.log4j.DOMConfigurator.configure(String filename);

    2.1 核心概念/3大组件

    Log4j有3大组件:

    • 【日志器(Logger)】:用来输出消息的类,可以输出不同级别的,比如错误消息,警告消息等
      • 创建日志器
        • Logger log = Logger.getLogger(calssNameX.class); log.info(); log.debug(); [log4J方式]
        • Logger logger = LoggerFactory.getLogger(calssNameX.class); log.info(); log.debug();[slf方式(推荐)]
      • 根日志器(rootLogger)
        • 若需要输出到多个位置的时候可用逗号隔开: log4j.rootLogger=info, A, B
    在配置文件里,需要为log4j.properties配置一个根日志器:
    log4j.rootLogger=DEBUG,AA
    log4j.rootLogger=WARN
    log4j.APPENDER.AA=org.apache.log4j.ConsoleAppender
    
    • 【输出源(Appender)】:日志输出的目标。日志输出到哪里去(文件、控制台)
      • org.apache.log4j.ConsoleAppender: 向控制台输出日志
      • org.apache.log4j.FileAppender: 向文件输出日志
      • org.apache.log4j.DailyRollingFileAppender
      • org.apache.log4j.RollingFileAppender
    log4j.appender.AA.File=../log.txt
    log4j.appender.AA.LAYOUT=org.apache.log4j.SimpleLayout
    log4j.appender.AA.DatePatten='yyyy-MM-dd'
    
    • 【格式化器(Layout)】:对输出消息进行格式化,比如添加日期
      • org.apache.log4j.PatternLayout
      • org.apache.log4j.SimpleLayout
      • org.apache.log4j.HTMLLayout
      • org.apache.log4j.TTCCLayout

    2.2 日志级别(从高到低)

    • OFF:最高等级,用于关闭所有日志记录
    • FATAL:重大错误级(系统有问题)
    • ERROR:错误级(一个模块有问题)
    • WARN:警告级
    • INFO:信息级。可以查看程序执行的流程
    • DEBUG:调试。用来调试程序的bug及显示
    • ALL:最低等级。用于打开所有日志记录

    debug,info,error等日志级别的方法都可传入多个可变参数:(以debug为例)

    2.3.1 日志器[Logger]

    • 特点
      • Logger(log4j)记录的是当前类的日志,不是每个实例的日志
        • 使用static修饰的属性
        • 只要有一个记录就可以了
      • private static final Logger logger = LoggerFactory.getLogger(Slf4jTest.class.getName());// slf4j日志记录器
      • 每个Logger都配有1个日志级别(Log Level):用来控制日志信息的输出。
    • rootLogger(根日志器)
      • root Logger(根Logger)是所有Logger的祖先
      • 它总是存在的
      • 它不可以通过名字获得
        • public static Logger Logger.getRootLogger();
        • public static Logger Logger.getLogger(Class clazz)

    2.3.2 输出源[Appender]

    org.apache.log4j.ConsoleAppender

    Threshold=WARN:指定日志信息的最低输出级别,默认DEBUG
    ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true
    Target=System.err:默认值是System.out
    

    org.apache.log4j.FileAppender

    Threshold=WARN:指定日志信息的最低输出级别,默认DEBUG
    ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认true
    Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认true
    File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件
    

    org.apache.log4j.DailyRollingFileAppender(常用)

    Threshold=WARN:指定日志信息的最低输出级别,默认DEBUG
    ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认true
    Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认true
    File=D:/logs/logging.log4j:指定当前消息输出到logging.log4j文件
    DatePattern='.'yyyy-MM:每月滚动一次日志文件,即每月产生一个新的日志文件。
                            当前月的日志文件名为logging.log4j,前一个月的日志文件名为logging.log4j.yyyy-MM
    另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:
    1)'.'yyyy-MM:每月
    2)'.'yyyy-ww:每周
    3)'.'yyyy-MM-dd:每天
    4)'.'yyyy-MM-dd-a:每天两次
    5)'.'yyyy-MM-dd-HH:每小时
    6)'.'yyyy-MM-dd-HH-mm:每分钟
    

    org.apache.log4j.RollingFileAppender

    Threshold=WARN:指定日志信息的最低输出级别,默认DEBUG
    ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认true
    Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认true
    File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件
    MaxFileSize=100KB:后缀可以是KB,MB或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件
    MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件
    

    2.3.3 日志格式化器[Layout]

    指定logger输出内容及格式: log4j.appender.appenderName.layout=className

    • org.apache.log4j.PatternLayout(最常用,可以灵活地指定布局模式)根据指定的转换模式格式化日志输出,或若未指定任何转换模式,就用默认的转化模式格式
      • ConversionPattern=%m%n:设定以怎样的格式显示消息
    • org.apache.log4j.HTMLLayout:(以HTML表格形式布局)格式化日志输出为HTML表格形式
      • LocationInfo=true:输出java文件名称和行号,默认false
      • Title=My Logging: 默认值是Log4J Log Messages
    • org.apache.log4j.SimpleLayout:(包含日志信息的级别和信息字符串)以一种非常简单的方式格式化日志输出,它打印三项内容:级别-信息
    • org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
    【patterm参数】
    %p: 日志级别<从高到低>(OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL)
    %c: 输出日志信息所属的类目,通常就是所在类的全名。可写为%c{num},表示取完整类名的层数,从后向前取,比如%c{2}取 "cn.qlq.exam"类为"qlq.exam"。
    %r: 输出自应用启动到输出该日志耗费的毫秒数
    %d: 输出日志时间点的日期或时间。默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},SSS为毫秒数(也可以写为SS,只不过SSS如果不足三位会补0),输出类似:2011-10-18 22:10:28,021
    %m: 输出代码中指定的消息,产生的日志具体信息
    %n: 输出一个回车换行符,Windows平台为"
    ",Unix平台为"
    "输出日志信息换行
    %t: 输出当前产生日志的线程名称
    %F: 输出日志消息产生时所在的文件名称 
    %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中 
    %%: 输出1个"%"字符
    %l: 输出日志事件的位置,相当于%c.%M(%F:L)的组合,包括类全名、方法、文件名以及在代码中行数。例如:cn.xm.test.PlainTest.main(PlanTest.java:12)
    

    3 Slf4J

    3.1 特点

    • 不同于其他日志类库,与其它日志类库有很大的不同
      • 不是1个真正的日志实现,而是1个抽象层
      • 它允许你在后台使用任意一个日志类库
    • 使代码独立于任一特定的日志API;
    • 无需忍受加载和维护新的日志框架的痛苦
    • 占位符(place holder):"{}"
      • 占位符非常类似于在String的format()方法中的%s
        • 因为它会在运行时被某个提供的实际字符串所替换
      • 不仅降低了代码中字符串连接次数,而且还节省了新建的String对象
      • 可以在运行时延迟字符串的建立。
        • 这意味着只有需要的String对象才被建立

    4 问题集

    1: log4j.properties 放置在/src/log4j.properties
    2: org.apache.log4j.BasicConfigurator.configure(); //自动快速地使用缺省Log4j环境
    

    5 实际项目开发中的日志应用

    1 一般是将捕捉到的Exception对象(e)作为日志记录的最后一个参数(会显示具体的出错信息以及出错位置),而且要放在{}可以格式化的参数之外。防止被{}转为e.toString()
    2 可使用e.toString(),而尽量不使用e.getMessage()。因为有的异常不一定有message,可以使用e.toString只会显示信息,不会显示出错的位置信息(不建议这种)

    //link - blog: https://www.cnblogs.com/qlqwjy/p/9275415.html
    package cn.johnnyzen.test;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.InputStream;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class Slf4jTest {
    
        private static Logger log = LoggerFactory.getLogger(Slf4jTest.class);
    
        public static void main(String[] args) {
            openFile("xxxxxx");
        }
    
        public static void openFile(String filePath) {
            File file = new File(filePath);
            try {
                InputStream in = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                //Exception对象(e)作为日志记录的最后一个参数(会显示具体的出错信息以及出错位置),而且要放在{}可以格式化的参数之外
                log.error("can found file [{}]", filePath, e);
            }
        }
    
    }
    
    2020-06-04 00:30:03 [cn.johnnyzen.test.Slf4jTest]-[ERROR] can found file [xxxxxx]
    java.io.FileNotFoundException: xxxxxx (系统找不到指定的文件。)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:146)
        at cn.xm.exam.test.Slf4jTest.openFile(Slf4jTest.java:22)
        at cn.xm.exam.test.Slf4jTest.main(Slf4jTest.java:16)
    

    6 参考文献

  • 相关阅读:
    四、创建多线程、数据共享
    operator函数操作符
    三、线程传参
    二、线程创建、结束
    一、并发、进程、线程概念
    bagging和boosting的区别
    ID3,C4.5和CART三种决策树的区别
    7创建型模式之建造者模式
    6创建型模式之工厂模式与抽象工厂模式
    5创建型模式之简单工厂模式
  • 原文地址:https://www.cnblogs.com/johnnyzen/p/13040356.html
Copyright © 2011-2022 走看看