(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