(1)、下载组件,引入jar包
(2)、配置
(3)、使用API
1、下载组件,引入jar包
| jar包 | 下载地址 |
| log4j-1.2.17.jar | http://logging.apache.org/log4j/1.2/ |
| commons-logging-1.2.jar | http://commons.apache.org/proper/commons-logging/download_logging.cgi |
2、配置
在项目的src目录下添加log4j.properties文件,配置如下:
log4j.rootLogger=debug, console, file log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=%d %p %c.%M() -%m%n log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File= ./logs/MyLog.log log4j.appender.file.MaxFileSize=5KB log4j.appender.file.MaxBackupIndex=100 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d %p %c.%M() -%m%n
3、使用API
App.java
package com.rk.log;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
public class App {
@Test
public void test()
{
Log log = LogFactory.getLog(App.class);
log.isDebugEnabled();
log.debug("debug信息");
log.info("info信息");
log.warn("warn信息");
log.error("error信息");
}
}输出
2016-08-03 21:00:03,661 DEBUG com.rk.test.App.test() -debug信息1 2016-08-03 21:00:03,666 INFO com.rk.test.App.test() -info信息2 2016-08-03 21:00:03,666 WARN com.rk.test.App.test() -warn信息3 2016-08-03 21:00:03,667 ERROR com.rk.test.App.test() -error信息4
4、配置详解
# 通过根元素指定日志输出的级别、目的地: # 日志输出优先级: debug < info < warn < error log4j.rootLogger=info,console,file ############# 日志输出到控制台 ############# # 日志输出到控制台使用的api类 log4j.appender.console=org.apache.log4j.ConsoleAppender # 指定日志输出的格式: 灵活的格式 log4j.appender.console.layout=org.apache.log4j.PatternLayout # 具体格式内容 log4j.appender.console.layout.ConversionPattern=%d %p %c.%M()-%m%n ############# 日志输出到文件 ############# log4j.appender.file=org.apache.log4j.RollingFileAppender # 文件参数: 指定日志文件路径 log4j.appender.file.File=../logs/MyLog.log # 文件参数: 指定日志文件最大大小 log4j.appender.file.MaxFileSize=5kb # 文件参数: 指定产生日志文件的最大数目 log4j.appender.file.MaxBackupIndex=100 # 日志格式 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d %c.%M()-%m%n
log4j.appender.file.File
对于log4j.appender.file.File这个配置,有几点需要注意:
(1)可以配置一个绝对路径的值,例如“E:/Temp/logs/MyLog.log”
(2)一般情况下使用相对路径,即使用“.”开头,但是对于普通的Java项目和JavaWeb项目之间,有一点需要注意:“.”代表的是Java命令的执行目录,但在普通Java项目中,“.”是指项目的根目录%project%;在JavaWeb项目中,“.”是指%tomat%/bin目录。
在JavaWeb项目中,一般将日志保存到tomcat的logs目录下:
可以使用
../logs/MyLog.log
由于在JavaWeb项目中,“.”代表%tomcat%/bin目录,而“..”代表返回到%tomcat%目录中,那么“../logs/MyLog.log”就代表%tomcat%/logs目录下的MyLog.log文件。
在Java项目中,使用“./logs/MyLog.log”代表%project%/logs目录下的MyLog.log文件。
5、commons logging和log4j的关系?
Apache的Common Logging只是一个高层的日志框架,本身并没有实现真正的写日志能力,而是依赖其它的日志系统如Log4j或者java本身的java.util.logging。可以通过配置文件来设定最终使用log4j还是java.util.logging.没有配置log4j的时候,就会调用java.util.logging包。
换句话说,我们上面使用的日志API,其实是由commons logging提供的,而非log4j提供的。在真正写日志的时候,commons logging会调用log4j的日志输出功能。
参考: commons-logging 和 log4j 之间的关系http://zachary-guo.iteye.com/blog/361177 我们在做项目时,日志的记录是必不可少的一项任务,而我们通常是使用 apache 的 log4j 日志管理工具。然而,在项目中,我们经常会看到两个 jar 包:commons-logging.jar 和 log4j.rar。为什么我们在使用 log4j 的同时还要引入 commons-logging.jar 呢,或者说不用 commons-logging.jar 可不可以,这两者之间到底是怎么的一种关系呢? 作为记录日志的工具,它至少应该包含如下几个组成部分(组件): 1. Logger 记录器组件负责产生日志,并能够对日志信息进行分类筛选,控制什么样的日志应该被输出,什么样的日志应该被忽略。它还有一个重要的属性 - 日志级别。不管何种日志记录工具,大概包含了如下几种日志级别:DEBUG, INFO, WARN, ERROR 和 FATAL。 2. Level 日志级别组件。 3. Appender 日志记录工具基本上通过 Appender 组件来输出到目的地的,一个 Appender 实例就表示了一个输出的目的地。 4. Layout Layout 组件负责格式化输出的日志信息,一个 Appender 只能有一个 Layout。 我们再来看看 log4j.jar,打开 jar 包,我们可以看到 Logger.class(Logger),Level.class(Level), FileAppender.class(Appender), HTMLLayout.class(Layout)。其它的我们先忽略不看,这几个字节码文件正好是记录日志必不可少的几个组件。 接下来看看 commons-logging 中的 org.apache.commons.logging.Log.java 源码: package org.apache.commons.logging;
/**
* 这是一个抽象接口
* A simple logging interface abstracting logging APIs. In order to be
* instantiated successfully by {@link LogFactory}, classes that implement
* this interface must have a constructor that takes a single String
* parameter representing the "name" of this Log.
* <p>
* logging的6个级别
* The six logging levels used by <code>Log</code> are (in order):
* <ol>
* <li>trace (the least serious)</li>
* <li>debug</li>
* <li>info</li>
* <li>warn</li>
* <li>error</li>
* <li>fatal (the most serious)</li>
* </ol>
* 这些logging level依赖于uderlying logging system的实现
* The mapping of these log levels to the concepts used by the underlying
* logging system is implementation dependent.
* The implementation should ensure, though, that this ordering behaves
* as expected.
*
* logging对于性能的影响
* Performance is often a logging concern.
* By examining the appropriate property,
* a component can avoid expensive operations (producing information
* to be logged).
*
* For example,
*
* if (log.isDebugEnabled()) {
* ... do something expensive ...
* log.debug(theResult);
* }
*
* 配置和API是分离的
* Configuration of the underlying logging system will generally be done
* external to the Logging APIs, through whatever mechanism is supported by
* that system.
*
*/
public interface Log {
// ----------------------------------------------------- Logging Properties
/**
* 使用此方法有助于提高性能
* Is debug logging currently enabled?
* <p>
* Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than debug.
*
* @return true if debug is enabled in the underlying logger.
*/
public boolean isDebugEnabled();
public boolean isErrorEnabled();
public boolean isFatalEnabled();
public boolean isInfoEnabled();
public boolean isTraceEnabled();
public boolean isWarnEnabled();
// -------------------------------------------------------- Logging Methods
public void trace(Object message);
public void trace(Object message, Throwable t);
public void debug(Object message);
public void debug(Object message, Throwable t);
public void info(Object message);
public void info(Object message, Throwable t);
public void warn(Object message);
public void warn(Object message, Throwable t);
public void error(Object message);
public void error(Object message, Throwable t);
public void fatal(Object message);
public void fatal(Object message, Throwable t);
}很显然,只要实现了 Log 接口,它就是一个名副其实的 Logger 组件,也验证了 Logger 组件具有日志级别的属性。 继续看 commons-logging org.apache.commons.logging.impl 包下的几个类的源码片段: package org.apache.commons.logging.impl;
import org.apache.commons.logging.Log;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.apache.log4j.Level;
import ......
public class Log4JLogger implements Log, Serializable {
// 对 org.apache.commons.logging.Log 的实现
......
}
------------------------------------------------------------------
package org.apache.commons.logging.impl;
import org.apache.commons.logging.Log;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Jdk14Logger implements Log, Serializable {
// 对 org.apache.commons.logging.Log 的实现
......
}好了,分析到这里,我们应该知道,真正的记录日志的工具是 log4j 和 sun 公司提供的日志工具。而 commons-logging 把这两个(实际上,在 org.apache.commons.logging.impl 包下,commons-logging 仅仅为我们封装了 log4j 和 sun logger)记录日志的工具重新封装了一遍(Log4JLogger.java 和 Jdk14Logger.java),可以认为 org.apache.commons.logging.Log 是个傀儡,它只是提供了对外的统一接口。因此我们只要能拿到 org.apache.commons.logging.Log,而不用关注到底使用的是 log4j 还是 sun logger。 既然如此,我们向构建路径加了 commons-logging.jar 和 log4j.jar 两个 jar 包,那我们的应用程序到底使用的 log4j 还是 sun logger 呢?(关于这个问题的解答,查看下一个参考) 。。。。。中间一段省略,可查看原文。。。 可是问题又来了,org.apache.commons.logging.Log 和 org.apache.log4j.Logger 这两个类,通过包名我们可以发现它们都是 apache 的项目,既然如下,为何要动如此大的动作搞两个东西(指的是 commons-logging 和 log4j)出来呢?事实上,在 sun 开发 logger 前,apache 项目已经开发了功能强大的 log4j 日志工具,并向 sun 推荐将其纳入到 jdk 的一部分,可是 sun 拒绝了 apache 的提议,sun 后来自己开发了一套记录日志的工具。可是现在的开源项目都使用的是 log4j,log4j 已经成了事实上的标准,但由于又有一部分开发者在使用 sun logger,因此 apache 才推出 commons-logging,使得我们不必关注我们正在使用何种日志工具。 |
参考: log4j+commons-logging结合使用http://www.cnblogs.com/xwdreamer/archive/2011/12/28/2304598.html Common Logging有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。当commons-logging.jar被加入到CLASSPATH(通常将commons-logging.jar放在web project下的WebContent\WEB-INF\lib目录中)之后,它会合理地猜测你想用的日志工具,然后进行自我设置,用户根本不需要做任何设置。默认的LogFactory是按照下列的步骤去发现并决定那个日志工具将被使用的(按照顺序,寻找过程会在找到第一个工具时中止,这个顺序非常重要): 1、寻找当前factory中名叫org.apache.commons.logging.Log配置属性的值 2、寻找系统中属性中名叫org.apache.commons.logging.Log的值 3、如果应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger) 4、如果应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger) 5、使用简易日志包装类(SimpleLog) 上述的加载顺序可以通过commons-logging中LogSource.java的源代码可以看出,源代码如下,具体可以参考注释: package org.apache.commons.logging;
import java.lang.reflect.Constructor;
import java.util.Hashtable;
import org.apache.commons.logging.impl.NoOpLog;
/**
* By default, calling <code>getInstance()</code> will use the following
* algorithm:
* <ul>
* <li>If Log4J is available, return an instance of
* <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li>
* <li>If JDK 1.4 or later is available, return an instance of
* <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li>
* <li>Otherwise, return an instance of
* <code>org.apache.commons.logging.impl.NoOpLog</code>.</li>
* </ul>
* <p>
* You can change the default behavior in one of two ways:
* <ul>
* <li>On the startup command line, set the system property
* <code>org.apache.commons.logging.log</code> to the name of the
* <code>org.apache.commons.logging.Log</code> implementation class
* you want to use.</li>
* <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li>
* </ul>
*
* 不推荐使用这个LogSource类(@deprecated),推荐使用LogFactory类,
* 但LogSource类 和 LogFactory类 使用了相同的算法。
* @deprecated Use {@link LogFactory} instead - The default factory
* implementation performs exactly the same algorithm as this class did
*
* @version $Id: LogSource.java 1432675 2013-01-13 17:53:30Z tn $
*/
public class LogSource {
// ------------------------------------------------------- Class Attributes
static protected Hashtable logs = new Hashtable();
/** Is log4j available (in the current classpath) */
static protected boolean log4jIsAvailable = false;
/** Is JDK 1.4 logging available */
static protected boolean jdk14IsAvailable = false;
/** Constructor for current log class */
static protected Constructor logImplctor = null;
// ----------------------------------------------------- Class Initializers
static {
// Is Log4J Available?
/**
* 通过Class.forName("org.apache.log4j.Logger"))来查找Log4J,
* 只有将log4j.jar添加到classpath以后才能找到,
* 这也是为什么默认情况下只要将log4j.jar文件放在lib文件夹中
* 而不需要在common-logging.properties配置文件中进行配置就能自动使用log4j的原因
*/
try {
log4jIsAvailable = null != Class.forName("org.apache.log4j.Logger");
} catch (Throwable t) {
log4jIsAvailable = false;
}
// Is JDK 1.4 Logging Available?
try {
jdk14IsAvailable = null != Class.forName("java.util.logging.Logger") &&
null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger");
} catch (Throwable t) {
jdk14IsAvailable = false;
}
// Set the default Log implementation 通过common-logging.properties配置文件来决定日志实现方式
String name = null;
try {
name = System.getProperty("org.apache.commons.logging.log");
if (name == null) {
name = System.getProperty("org.apache.commons.logging.Log");
}
} catch (Throwable t) {
}
if (name != null) {
try {
setLogImplementation(name);
} catch (Throwable t) {
try {
setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
} catch (Throwable u) {
// ignored
}
}
} else {
try {
if (log4jIsAvailable) {//如果log4j可用,默认优先使用Log4JLogger
setLogImplementation("org.apache.commons.logging.impl.Log4JLogger");
} else if (jdk14IsAvailable) {//第二优先使用Jdk14Logger
setLogImplementation("org.apache.commons.logging.impl.Jdk14Logger");
} else {//最后使用commoms-logging中的自带的实现,但它不进行任何操作
setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
}
} catch (Throwable t) {
try {
setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
} catch (Throwable u) {
// ignored
}
}
}
}
/**
* Set the log implementation/log implementation factory
* by the name of the class. The given class must implement {@link Log},
* and provide a constructor that takes a single {@link String} argument
* (containing the name of the log).
*/
static public void setLogImplementation(String classname)
throws LinkageError, NoSuchMethodException, SecurityException, ClassNotFoundException {
try {
Class logclass = Class.forName(classname);
Class[] argtypes = new Class[1];
argtypes[0] = "".getClass();
logImplctor = logclass.getConstructor(argtypes);
} catch (Throwable t) {
logImplctor = null;
}
}
// 其它代码省略。。。
}使用commons-logging结合log4j进行开发 (1)下载必要的jar包 下载commons-logging.jar和log4j.jar包,然后把它们放到工程的lib目录下,引入工程中。 (2)编写common-logging.properties配置文件 在属性文件common-logging.properties中设置实现接口的类。如下(这里设置Log4j为所使用的日志包): org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger (3)log4j.properties配置实现日志的不同输出形式 单独使用log4j的示例 package log.sample;
import org.apache.log4j.Logger;
public class Log4jTest {
private static Logger log = Logger.getLogger(Log4jTest.class);
public void log() {
log.debug("Debug info.");
log.info("Info info");
log.warn("Warn info");
log.error("Error info");
log.fatal("Fatal info");
}
public static void main(String[] args) {
Log4jTest test = new Log4jTest();
test.log();
}
}common logging和log4j结合的示例 package log.sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JCLTest {
private static Log log = LogFactory.getLog(JCLTest.class);
public void log(){
log.debug("Debug info.");
log.info("Info info");
log.warn("Warn info");
log.error("Error info");
log.fatal("Fatal info");
}
public static void main(String[] args) {
JCLTest test = new JCLTest();
test.log();
}
} |
日志组件系列:(2)commons logging和log4j实战
原文地址:http://lsieun.blog.51cto.com/9210464/1834146