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.
004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j的更多相关文章
- 使用Common.Logging+log4net规范日志管理【转载】
使用Common.Logging+log4net规范日志管理 Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大 ...
- 使用Common.Logging+log4net规范日志管理
Common.Logging+(log4net/NLog/) common logging是一个通用日志接口,log4net是一个强大的具体实现,也可以用其它不同的实现,如EntLib的日志.NLog ...
- 基于Common.Logging + Log4Net实现的日志管理
前言 Common.Logging 是Commons-Logging(apache最早提供的日志门面接口,提供了简单的日志实现以及日志解耦功能) 项目的.net版本.其目的是为 "所有的.n ...
- 在C#应用中使用Common Logging日志接口
我在C#应用中一般使用log4net来记录日志,但如果项目中有个多个工程,那么没有工程都需要引用log4neg,感觉很不爽.不过今日在开spring.net的时候,看到了有个通用日志接口Common ...
- SpringBoot整合日志log4j2
SpringBoot整合日志log4j2 一个项目框架中日志都是必不可少的,随着技术的更新迭代,SpringBoot被越来越多的企业所采用.这里简单说说SpringBoot整合log2j2日志. 一. ...
- Common.Logging log4net Common.Logging.Log4Net 配置
1.log4net 单独配置 log4net支持多种格式的日志输出,我这里只配置输出到本地的txt文件这种格式. <log4net> <root> <appender-r ...
- Common.Logging源码解析二
Common.Logging源码解析一分析了LogManager主入口的整个逻辑,其中第二步生成日志实例工厂类接口分析的很模糊,本随笔将会详细讲解整个日志实例工厂类接口的生成过程! (1).关于如何生 ...
- 【SpringBoot】整合日志框架
一.日志框架概述 1.1 日志框架的产生 1.2 市面上的日志框架 二.SLF4j 使用与整合 2.1 如何在系统中使用SLF4j 2.2 如何整合日志框架 2.3 SpringBoot中的日志关系 ...
- 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 ...
随机推荐
- DAY1注册店铺
- zabbix low-level discovery 监控mysql
当一台服务器上MySQL有多个实例的时候,MySQL占用多个不同端口.利用zabbix的low-level discovery可以轻松监控. 思路参考:http://dl528888.blog.51c ...
- css一个元素垂直居中的6种方法
方法一: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <titl ...
- Ubuntu系统---又显示nvidia-smi 未找到命令
Ubuntu系统---又显示nvidia-smi 未找到命令 本来nvidia驱动+CUDA安装好用,两次遇到开机发现字体异常,不用合计,是显卡驱动的问题.一查,确实是nvidia-smi 未找到命令 ...
- WPF多值绑定及多值转换(MultiBinding和IMultiValueConverter)
WPF可以使用MultiBinding进行多值绑定,使用IMultiValueConverter进行多值转换 例: (1)转换器 public class ContentConverter : IMu ...
- uhd镜像重新安装
USRP LW-X300连接网口,设置IP地址:192.168.10.1,子网验码:255.255.255.0 连接后uhd_usrp_probe提示更新镜像. 终端输入: uhd_image_loa ...
- Shiro 中的 SecurityUtils(转)
在 Shiro 中 SecurityUtils 是一个抽象类.并且没有任何子类.在其中声明了一个静态属性,三个静态方法. 静态属性 securityManager private static Sec ...
- 052_获取本机 MAC 地址
#!/bin/baship a s | awk 'BEGIN{print "本机 MAC 地址信息如下:"}/^[0-9]/{print $2;getline;if($0~/lin ...
- SQL Server Report Server
1.SQL Server Report Server是利用mircosoft的share point产品 在menu 打开Reporting Services Configuration进行配置,会自 ...
- python 序列通用操作
通用序列操作:索引:greeting=hellogreeting[0] 分片:number[1,2,3,4,5,6]number[3:6]number[3:6:1] 序列相加:[1,2,3] + [4 ...