Logger来自log4j自己的包。如果用Logger.getLogger,需要一个log4j的jar包.
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
--------------------------