004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j

一、概述

  Jakarta Commons Logging (JCL)提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的日志实现工具。它提供给中间件/日志工具开发者一个简单的日志操作抽象,允许程序开发人员使用不同的具体日志实现工具。用户被假定已熟悉某种日志实现工具的更高级别的细节。JCL提供的接口,对其它一些日志工具,包括Log4J, Avalon LogKit, and JDK 1.4等,进行了简单的包装,此接口更接近于Log4J和LogKit的实现。

  在Logging系统中,目前框架都是基于相同的设计,即从一个LogFactory中取得一个命名的Log(Logger)实例,然后使用这个Log(Logger)实例打印debug、info、warn、error等不同级别的日志。作为两个门面日志系统,Commons Logging和SLF4J也同样采用这样的设计。 
所谓门面日志系统,是指它们本身并不实现具体的日志打印逻辑,它们只是作为一个代理系统,接收应用程序的日志打印请求,然后根据当前环境和配置,选取一个具体的日志实现系统,将真正的打印逻辑交给具体的日志实现系统,从而实现应用程序日志系统的“可插拔”,即可以通过配置或更换jar包来方便的更换底层日志实现系统,而不需要改变任何代码。个人感觉SLF4J的实现更加灵活,并且它还提供了Maker和MDC的接口。

1.1、pom依赖

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

1.2、配置

  创建commons-logging.properties文件,将其放在classpath下,如果是maven项目则将其放在src/main/resource目录下,配置内容如下

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

1.3、使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ApplicationMain {
    private static Log logger = LogFactory.getLog(ApplicationMain.class);

    public static void main(String[] args) {
        System.out.println(logger.getClass().getName());
        // 记录debug级别的信息
        logger.debug("This is debug message.");
        // 记录info级别的信息
        logger.info("This is info message.");
        // 记录error级别的信息
        logger.error("This is error message.");
    }
}

二、详细说明

    

2.1、LogFactory获取相对应的Log实现类逻辑

JCL有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。当commons-logging.jar被加入到 CLASSPATH之后,它会合理地猜测你想用的日志工具,然后进行自我设置,用户根本不需要做任何设置。默认的LogFactory是按照下列的步骤去发现并决定那个日志工具将被使用的(按照顺序,寻找过程会在找到第一个工具时中止): 
  1. 寻找当前factory中名叫org.apache.commons.logging.Log配置属性的值 
  2. 寻找系统中属性中名叫org.apache.commons.logging.Log的值 
  3. 如果应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger) 
  4. 如果存在Lumberjack版本的Logging系统,则使用Jdk13LumberjackLogger类。 
  5. 如果应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger) 
  6. 使用简易日志包装类(SimpleLog) 
  7. 以上步骤都失败,则抛出LogConfigurationException。

LogFactory使用动态查找机制进行日志实例化,执行顺序为:common-logging.properties---->系统环境变量------->log4j--->jul--->simplelog---->nooplog

org.apache.commons.logging.Log的具体实现:

  org.apache.commons.logging.Log的具体实现有如下: 
  - org.apache.commons.logging.impl.Jdk14Logger 使用JDK1.4。 
  - org.apache.commons.logging.impl.Log4JLogger 使用Log4J。 
  - org.apache.commons.logging.impl.LogKitLogger 使用 avalon-Logkit。 
  - org.apache.commons.logging.impl.SimpleLog common-logging自带日志实现类。它实现了Log接口,把日志消息都输出到系统错误流System.err 中。 
  - org.apache.commons.logging.impl.NoOpLog common-logging自带日志实现类。它实现了Log接口。 其输出日志的方法中不进行任何操作。

2.2、日志级别

1)fatal 非常严重的错误,导致系统中止。期望这类信息能立即显示在状态控制台上。

2)error 其它运行期错误或不是预期的条件。期望这类信息能立即显示在状态控制台上。

3)warn 使用了不赞成使用的API、非常拙劣使用API, ‘几乎就是‘错误, 其它运行时不合需要和不合预期的状态但还没必要称为 "错误"。期望这类信息能立即显示在状态控制台上。

4)info 运行时产生的有意义的事件。期望这类信息能立即显示在状态控制台上。

5)debug 系统流程中的细节信息。期望这类信息仅被写入log文件中。

6)trace 更加细节的信息。期望这类信息仅被写入log文件中。

如上述配置了SimpleLog,增加simplelog.properties配置文件,放到classpath下,如果是maven则放到src/main/resource目录下,配置内容参考:

org.apache.commons.logging.simplelog.defaultlog=TRACE

2.3、LogFactory实现原理

  LogFactory作为log的工厂存在,使用动态查找机制进行log实例的获取,具体执行步骤如下:

  ①首先在classpath下寻找commons-logging.properties文件。如果找到,则使用其中定义的Log实现类;如果找不到,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类;

  ②查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类;

  ③使用JDK自身的日志实现类(JDK1.4以后才有日志实现类);

  ④使用commons-logging自己提供的一个简单的日志实现类SimpleLog;

  上述步骤当LogFactory成功找到一个日志实现之后就会停止

  LogFactory的核心步骤在于discoverLogImplementation方法,源码分析如下:

if (isDiagnosticsEnabled()) {
            this.logDiagnostic("Discovering a Log implementation...");
        }

        this.initConfiguration();
        Log result = null;
        //从common-logging.properties文件中提取org.apache.commons.logging.Log这个变量的value
        String specifiedLogClassName = this.findUserSpecifiedLogClassName();

        //配置文件中存在该变量则实例化
        if (specifiedLogClassName != null) {
            if (isDiagnosticsEnabled()) {
                this.logDiagnostic("Attempting to load user-specified log class ‘" + specifiedLogClassName + "‘...");
            }

            //核验相应日志对象是否存在
            result = this.createLogFromClass(specifiedLogClassName, logCategory, true);

            //如果日志对象不存在,则报错
            if (result == null) {
                StringBuffer messageBuffer = new StringBuffer("User-specified log class ‘");
                messageBuffer.append(specifiedLogClassName);
                messageBuffer.append("‘ cannot be found or is not useable.");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Log4JLogger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk14Logger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.Jdk13LumberjackLogger");
                this.informUponSimilarName(messageBuffer, specifiedLogClassName, "org.apache.commons.logging.impl.SimpleLog");
                throw new LogConfigurationException(messageBuffer.toString());
            } else {
                return result;
            }
        } else {
            //当日志文件中不存在该变量时,按照机制遍历classesToDiscover字符串数组

            if (isDiagnosticsEnabled()) {
                this.logDiagnostic("No user-specified Log implementation; performing discovery using the standard supported logging implementations...");
            }

            //遍历classesToDiscover字符串数组获取日志实例(动态查找机制)
            for(int i = 0; i < classesToDiscover.length && result == null; ++i) {
                result = this.createLogFromClass(classesToDiscover[i], logCategory, true);
            }

            //到最后仍旧找不到匹配的日志实例,则抛错
            if (result == null) {
                throw new LogConfigurationException("No suitable Log implementation");
            } else {
                return result;
            }
        }

三、common-logging+log4j应用

3.1、POM依赖

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

3.2、配置文件

  在commons-logging.properties文件,将log指向log4j,可以不加因为默认的,没有的话会先加载log4j

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

  配置log4j.properties配置【可以参看002-log-log4j

### 设置###
log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

3.2、java代码依旧使用logging代码即可

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ApplicationMain {
    private static Log logger = LogFactory.getLog(ApplicationMain.class);

    public static void main(String[] args) {
        System.out.println(logger.getClass().getName());
        // 记录debug级别的信息
        logger.debug("This is debug message.");
        // 记录info级别的信息
        logger.info("This is info message.");
        // 记录error级别的信息
        logger.error("This is error message.");
    }
}

输出

org.apache.commons.logging.impl.Log4JLogger
[DEBUG] 2019-06-21 14:07:37,823 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:13)
This is debug message.
[INFO ] 2019-06-21 14:07:37,826 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:15)
This is info message.
[ERROR] 2019-06-21 14:07:37,826 method:com.github.bjlhx15.common.study.log.ApplicationMain.main(ApplicationMain.java:17)
This is error message.

  

原文地址:https://www.cnblogs.com/bjlhx/p/11064167.html

时间: 2024-11-13 08:00:33

004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j的相关文章

使用Common.Logging+log4net规范日志管理

Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大的具体实现,也可以用其它不同的实现,如EntLib的日志.NLog等. Common.Logging可以通过修改配置,更换不同的日志实现类,而不需要修改任何代码. .net 项目使用CommonLogging: 1.添加必要的程序集:Common.Logging.dll.Common.Logging.Core.dll.Common.Logging.log4net1

common.logging和log4j比较

apache common logging是一种log的框架接口,它本身并不实现log记录的功能,而是在运行时动态查找目前存在的日志库,调用相关的日志函数,从而隐藏具体的日志实现 log4j是具体的日志实现,真正负责"写"日志的这个功能 common logging本身不是log,你可以把它看做是一个日志的接口 而log4j就是日志的实现 使用common logging方式实现日志,主要的原因在于可以忽略底层的日志实现,或者说为以后的日志实现库的更换提供透明界面 你可以考虑下,假设从

Common.Logging log4net Common.Logging.Log4Net 配置

1.log4net 单独配置 log4net支持多种格式的日志输出,我这里只配置输出到本地的txt文件这种格式. <log4net> <root> <appender-ref ref="RollingFileAppender" /> </root> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppende

How To Configure Logging And Log Rotation In Apache On An Ubuntu VPS

Introduction The Apache web server can be configured to give the server administrator important information about how it is functioning and what issues, if any, need to be addressed. The main avenue for providing feedback to the administrator is thro

logging模块及日志框架

logging模块及日志框架 logging模块 一.导入方式 import logging 二.作用 写日志 三.模块功能 3.1 经常使用 # V1 import logging logging .debug(('调试')) #10 logging.info('正常') #20 logging.critical('严重错误') #30 logging.error('错误') #40 logging.warning('警告') #50 #默认级别为30以上的可以打印 # V2 import l

Apache开源日志框架Log4j配置指南

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程等:我们也可以控制每一条日志的输出格式:通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程.最方便的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码.本篇指南主要介绍Log4j 1.x版本的配置与使用Log4j最新版下载地址:http://www.apache.org/dy

【改变mysql 日志位置Bug】Could not use mysql.log for logging (error 13)

今天手贱,看到mysql 的日志在/var/log/mysql下面.总是觉得别扭,于是就想改变日志的位置, 本人开发环境 vagrant  + ubuntu12.04 ,在/etc/mysql/mysql中修改了general_log的位置,放在/data/logs/mysql下面 然后重启服务,service mysql restart 查看错误日志发现说 /usr/sbin/mysqld: File '/data/logs/mysql/mysql.log' not found (Errcod

整合Struts2框架和Spring框架

-----------------------siwuxie095 整合 Struts2 框架和 Spring 框架 1.导入相关 jar 包(共 27 个) (1)导入 Struts2 的基本 jar 包(13 个) 其中: 在 Struts2 和 Hibernate 中,都有 javassist,会产生冲突, 选择高版本,删除低版本即可 (2)导入 Spring 的核心 jar 包和日志相关的 jar 包(6 个) Commons Logging 下载链接: http://commons.a

整合Spring框架和Hibernate框架

-------------------siwuxie095 整合 Spring 框架和 Hibernate 框架 1.导入相关 jar 包(共 28 个) (1)导入 Spring 的核心 jar 包和日志相关的 jar 包(6 个) Commons Logging 下载链接: http://commons.apache.org/proper/commons-logging/download_logging.cgi LOG4J 下载链接: https://www.apache.org/dist/