LogFactory来自common-logging包。如果用LogFactory.getLog,你可以用任何实现了通用日志接口的日志记录器替换log4j,而程序不受影响。apache的common-logging包是通用日志接口,通过这个中间层,你可以随便指定到底用哪个日志系统。增加系统的灵活性。若log4j它不存在, commons-logging 会另行选择其它的日志实现类。 这样保证了程序中不一定要使用log4j这个日志文件了
增强灵活性的理由:
1)首先在 classpath 下寻找自己的配置文件 commons-logging.properties ,如果找到,则使用其中定义的 Log 实现类;
2)如果找不到 commons-logging.properties 文件,则在查找是否已定义系统环境变量 org.apache.commons.logging.Log ,找到则使用其定义的 Log 实现类;
3)否则,查看 classpath 中是否有 Log4j 的包,如果发现,则自动使用 Log4j 作为日志实现类;
4)否则,使用 JDK 自身的日志实现类( JDK1.4 以后才有日志实现类);
5)否则,使用 commons-logging 自己提供的一个简单的日志实现类SimpleLog ;
为了简化配置 commons-logging ,一般不使用 commons-logging 的配置文件,也不设置与 commons-logging 相关的系统环境变量,而只需将 Log4j 的 Jar 包放置到 classpash 中就可以了。这样就很简单地完成了 commons-logging 与 Log4j 的融合。
根据不同的性质,日志信息通常被分成不同的级别,从低到高依次是:“调试( DEBUG )”“信息( INFO )”“警告( WARN )”“错误(ERROR )”“致命错误( FATAL )”。
==基于common-logging的运行方式==:
package org;
import org.apache.commons.logging.Log;
import org.apache.log4j.Logger;
public class Test extends TagSupport{
public static Log log=LogFactory.getLog(Test.class);
public static void test()
{
log.debug("111");
log.info("125");
log.warn("485");
log.error("error");
}
public static void main(String[] a)
{
Test.test();
}
}
==基于log4j的运行方式==:
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class TestLog4j {
static Logger logger = Logger.getLogger(TestLog4j.class);
public static void main(String args[]) {
PropertyConfigurator.configure("log4j.properties");
logger.debug("Here is some DEBUG");
logger.info("Here is some INFO");
logger.warn("Here is some WARN");
logger.error("Here is some ERROR");
logger.fatal("Here is some FATAL");
}
}
##commons-logging 仅仅对 Log4j( 当然还包括其它 LOG 实现 ) 作了一层包装,具体的日志输出还是在内部转交给身后的 Log4j 来处理,还有log4j会默认的去classes目录下去寻找log4j.properties 文件
从JDK1.4开始即引入与日志相关的类java.util.logging.Logger,但由于Log4J的存在,一直未能广泛使用,大致认为: (1)Logger:适用于小型系统,当日志量过大时性能有待提升。好处在于JDK集成了此类,无需引入新包。且性能也在逐步改善当中,我认为一般而言,使用Logger即可。 (2)Log4J:并发性较好,性能较强,适用于大型系统。 基本概念 Logger中有2个比较重要的概念,分别是记录器(Logger)与处理器(Handler),二者分别完成以下功能: (1)Logger:记录日志,设置日志级别等。 (2)Handler:确定输出位置等 一、创建Logger对象 static Logger getLogger(String name) 为指定子系统查找或创建一个 logger。 static Logger getLogger(String name, String resourceBundleName) 为指定子系统查找或创建一个 logger。 注意:name是Logger的名称,当名称相同时候,同一个名称的Logger只创建一个。 二、Logger的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面。 各级别按降序排列如下: •SEVERE(最高值) •WARNING •INFO •CONFIG •FINE •FINER •FINEST(最低值) 此外,还有一个级别 OFF,可用来关闭日志记录,使用级别 ALL 启用所有消息的日志记录。 logger默认的级别是INFO,比INFO更低的日志将不显示。 Logger的默认级别定义是在jre安装目录的lib下面。 # Limit the message that are printed on the console to INFO and above. java.util.logging.ConsoleHandler.level = INFO 简单实例 public class TestLogger { public static void main(String[] args) { Logger log = Logger.getLogger("lavasoft"); log.setLevel(Level.INFO); Logger log1 = Logger.getLogger("lavasoft"); System.out.println(log==log1); //true Logger log2 = Logger.getLogger("lavasoft.blog"); log2.setLevel(Level.WARNING); log.info("aaa"); log2.info("bbb"); log2.fine("fine"); } } ------------------- true 2009-7-28 20:00:30 TestLogger main 信息: aaa ------------------- 当注释掉 --->log2.setLevel(Level.WARNING); 输出结果: ------------------- true 2009-7-28 20:02:02 TestLogger main 信息: aaa 2009-7-28 20:02:02 TestLogger main 信息: bbb ------------------- 从这里可以看出,logger的名字是有层级关系的。这和log4j的控制方式完全一致。 下面是API文档的原文: 一般使用圆点分隔的层次命名空间来命名Logger。Logger名称可以是任意的字符串,但是它们一般应该基于被记录组件的包名或类名,如 java.net 或 javax.swing。此外,可以创建“匿名”的 Logger,其名称未存储在 Logger 命名空间中。 可通过调用某个getLogger 工厂方法来获得 Logger 对象。这些方法要么创建一个新 Logger,要么返回一个合适的现有 Logger。 三、Logger的Handler 1.Handler 对象从 Logger 中获取日志信息,并将这些信息导出。例如,它可将这些信息写入控制台或文件中,也可以将这些信息发送到网络日志服务中,或将其转发到操作系统日志中。 2.可通过执行 setLevel(Level.OFF) 来禁用 Handler,并可通过执行适当级别的 setLevel 来重新启用。 3.Handler 类通常使用 LogManager 属性来设置 Handler 的 Filter、Formatter 和 Level 的默认值。 java.util.logging.Handler java.util.logging.MemoryHandler java.util.logging.StreamHandler java.util.logging.ConsoleHandler java.util.logging.FileHandler java.util.logging.SocketHandler 例子: public class TestLogger { public static void main(String[] args) throws IOException { Logger log = Logger.getLogger("lavasoft"); log.setLevel(Level.INFO); Logger log1 = Logger.getLogger("lavasoft"); System.out.println(log==log1); //true Logger log2 = Logger.getLogger("lavasoft.blog"); // log2.setLevel(Level.WARNING); ConsoleHandler consoleHandler =new ConsoleHandler(); consoleHandler.setLevel(Level.ALL); log.addHandler(consoleHandler); FileHandler fileHandler = new FileHandler("C:/testlog%g.log"); fileHandler.setLevel(Level.INFO); log.addHandler(fileHandler); log.info("aaa"); log2.info("bbb"); log2.fine("fine"); } } 默认的日志方式是xml格式,最好自定义下logger的格式,需要用Formatter来定义. 四、Logger的Formatter Formatter 为格式化 LogRecords 提供支持。 一般来说,每个日志记录 Handler 都有关联的 Formatter。Formatter 接受 LogRecord,并将它转换为一个字符串。 有些 formatter(如 XMLFormatter)需要围绕一组格式化记录来包装头部和尾部字符串。可以使用 getHeader 和 getTail 方法来获得这些字符串。 LogRecord 对象用于在日志框架和单个日志 Handler 之间传递日志请求。 LogRecord(Level level, String msg) 用给定级别和消息值构造 LogRecord。 看个例子就明白了: public class TestLogger { public static void main(String[] args) throws IOException { Logger log = Logger.getLogger("lavasoft"); log.setLevel(Level.INFO); Logger log1 = Logger.getLogger("lavasoft"); System.out.println(log == log1); //true Logger log2 = Logger.getLogger("lavasoft.blog"); // log2.setLevel(Level.WARNING); ConsoleHandler consoleHandler = new ConsoleHandler(); consoleHandler.setLevel(Level.ALL); log.addHandler(consoleHandler); FileHandler fileHandler = new FileHandler("C:/testlog%g.log"); fileHandler.setLevel(Level.INFO); fileHandler.setFormatter(new MyLogHander()); log.addHandler(fileHandler); log.info("aaa"); log2.info("bbb"); log2.fine("fine"); } } class MyLogHander extends Formatter { @Override public String format(LogRecord record) { return record.getLevel() + ":" + record.getMessage()+"\n"; } } ========================== Logging.java: public class Logging { private static Logger logger = null; private Logging(){} public static Logger getLogger(){ if (null == logger) { InputStream is = Logging.class.getClass().getResourceAsStream("/logger.properties"); try { LogManager.getLogManager().readConfiguration(is); } catch (Exception e) { logging.warning("input properties file is error.\n" + e.toString()); }finally{ try { is.close(); } catch (IOException e) { logging.warning("close FileInputStream a case.\n" + e.toString()); } } logger = Logger.getLogger("LOGGER"); } return logger; } private static Logger logging = Logger.getLogger(Logging.class.getName()); } logger.properties: handlers = java.util.logging.ConsoleHandler,java.util.logging.FileHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = INFO java.util.logging.FileHandler.pattern = c:/my.log%g.log java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.FileHandler.limit = 104857600 java.util.logging.FileHandler.count = 3 java.util.logging.FileHandler.append = true java.util.logging.FileHandler.level = INFO LOGGER.level = FINEST LoggerTest.java public class LoggerTest extends TestCase{ @Test public void testLogger() throws Exception { Logger logger = Logging.getLogger(); logger.finest("finest"); logger.finer("finer"); logger.fine("fine"); logger.info("info"); logger.config("config"); logger.warning("warning"); logger.severe("severe"); } } ========================== -------------------------- import java.io.IOException; import java.io.InputStream; import java.util.logging.Logger; /** * @author * @date * */ public class LogManager { // 初始化LogManager static { // 读取配置文件 ClassLoader cl = LogManager.class.getClassLoader(); InputStream inputStream = null; if (cl != null) { inputStream = cl.getResourceAsStream("logging.properties"); } else { inputStream = ClassLoader .getSystemResourceAsStream("loggging.properties"); } java.util.logging.LogManager logManager = java.util.logging.LogManager .getLogManager(); try { // 重新初始化日志属性并重新读取日志配置。 logManager.readConfiguration(inputStream); } catch (SecurityException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } } /** * 获取日志对象 * * @param clazz * @return */ public static Logger getLogger(Class clazz) { Logger logger = Logger.getLogger(clazz.getName()); return logger; } } loggging.properties: #Level的五个等级SEVERE(最高值) 、WARNING 、INFO 、CONFIG 、FINE 、FINER 、FINEST(最低值) #为 Handler 指定默认的级别(默认为 Level.INFO)。 java.util.logging.ConsoleHandler.level=INFO # 指定要使用的 Formatter 类的名称(默认为 java.util.logging.SimpleFormatter)。 java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter # 为 Handler 指定默认的级别(默认为 Level.ALL)。 java.util.logging.FileHandler.level=INFO # 指定要使用的 Formatter 类的名称(默认为 java.util.logging.XMLFormatter)。 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter # 指定要写入到任意文件的近似最大量(以字节为单位)。如果该数为 0,则没有限制(默认为无限制)。 java.util.logging.FileHandler.limit=1024000 # 指定有多少输出文件参与循环(默认为 1)。 java.util.logging.FileHandler.count=1 # 为生成的输出文件名称指定一个模式。有关细节请参见以下内容(默认为 "%h/java%u.log")。 java.util.logging.FileHandler.pattern=C:/Test%u.log # 指定是否应该将 FileHandler 追加到任何现有文件上(默认为 false)。 java.util.logging.FileHandler.append=true #指定handler handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler --------------------------