一、概述

  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.

  

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

  1. 使用Common.Logging+log4net规范日志管理【转载】

    使用Common.Logging+log4net规范日志管理   Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大 ...

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

    Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大的具体实现,也可以用其它不同的实现,如EntLib的日志.NLog ...

  3. 基于Common.Logging + Log4Net实现的日志管理

    前言 Common.Logging 是Commons-Logging(apache最早提供的日志门面接口,提供了简单的日志实现以及日志解耦功能) 项目的.net版本.其目的是为 "所有的.n ...

  4. 在C#应用中使用Common Logging日志接口

    我在C#应用中一般使用log4net来记录日志,但如果项目中有个多个工程,那么没有工程都需要引用log4neg,感觉很不爽.不过今日在开spring.net的时候,看到了有个通用日志接口Common ...

  5. SpringBoot整合日志log4j2

    SpringBoot整合日志log4j2 一个项目框架中日志都是必不可少的,随着技术的更新迭代,SpringBoot被越来越多的企业所采用.这里简单说说SpringBoot整合log2j2日志. 一. ...

  6. Common.Logging log4net Common.Logging.Log4Net 配置

    1.log4net 单独配置 log4net支持多种格式的日志输出,我这里只配置输出到本地的txt文件这种格式. <log4net> <root> <appender-r ...

  7. Common.Logging源码解析二

    Common.Logging源码解析一分析了LogManager主入口的整个逻辑,其中第二步生成日志实例工厂类接口分析的很模糊,本随笔将会详细讲解整个日志实例工厂类接口的生成过程! (1).关于如何生 ...

  8. 【SpringBoot】整合日志框架

    一.日志框架概述 1.1 日志框架的产生 1.2 市面上的日志框架 二.SLF4j 使用与整合 2.1 如何在系统中使用SLF4j 2.2 如何整合日志框架 2.3 SpringBoot中的日志关系 ...

  9. 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 info ...

随机推荐

  1. 使用MySQL审计Plugin

    本文来源:http://blog.chinaunix.net/uid-20785090-id-5018977.html 越来越多的企业把应用往mysql上迁移,这时候对数据库的审计又成了一件紧急的事情 ...

  2. Computer Vision_18_Image Stitching:Automatic Panoramic Image Stitching using Invariant Features——2007

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...

  3. Java学习第二天之Java程序的基本规则

    一.Java程序的组织形式 Java程序是一种纯粹的面向对象的程序设计语言,因此Java程序必须以类(即class)的形式存在,类(class)是Java程序的最小程序单位.Java程序不允许可执行性 ...

  4. deep_learning_Github_初学者教程

    Github_link_from:https://github.com/lawlite19/MachineLearning_Python 机器学习算法Python实现 目录 机器学习算法Python实 ...

  5. Python内存数据序列化到硬盘上哪家强

    1. 闲扯一下:文件 磁盘上的数据,我们一般称为 “文件” ,一般不同的文件都有各自的后缀名,比如 .txt .docx .xlsx .jpg .mp3 .avi .这些不同类型的文件一般分为两大类: ...

  6. less混合

    混合(mixin)变量 .border{ border: 5px solid pink; } .box{ width: 300px;height:300px; .border; } => .bo ...

  7. python3 基础二——基本的数据类型三

    一.字符串str 1.创建字符串,为变量分配一个值 word='字符串' sentence="字符串\n" #python中单引号和双引号使用完全相同 paragraph=&quo ...

  8. linux下18种监测网络带宽方式

    1. nload nload是一个命令行工具,让用户可以分开来监控入站流量和出站流量.它还可以绘制图表以显示入站流量和出站流量,视图比例可以调整.用起来很简单,不支持许多选项. 所以,如果你只需要快速 ...

  9. SmtpClient 发送邮件

    利用SmtpClient 代码发送邮件. 简单测试代码: static void Main(string[] args) { MailMessage msg = new MailMessage(); ...

  10. IdentityServer(三)密码模式

    前言 用户名密码模式相较于客户端凭证模式,多了用户.通过用户的用户名和密码向Identity Server申请访问令牌.密码模式有两种实现方式. 1.把用户写进内存Identity从中读取账号密码验证 ...