commons-logging 与 log4j的灵活使用

本文介绍了在Java项目中如何使用commons-logging作为日志接口,并详细阐述了其查找日志实现的策略。同时,文章讲解了如何配置log4j作为日志实现,并提供了相关配置示例,帮助读者理解日志的配置和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

在工作中,日志功能是必不可少的组件,它为我们提供了方便快捷的日志记录功能。借此机会,总结下java项目中常用的第三方日志接口与实现。

1.commons-logging:

commons-logging 是Apache基金会下开发的一款日志系统接口,通过其API可以整合不同的日志系统实现,其主要用于为整个软件系统提供统一抽象的日志操作,避免由于不同日志系统实现所带来的学习与迁移成本。从广义的角度来说,即是面向接口开发理念。

既然谈到commons-logging是一个接口,那么我们如何在java项目中为其指定对应的日志实现呢。从官方文档中,我们可以看到commons-logging一共提供了五种查找日志实现的策略,优先级从上到下依次递减:

  1. 查找LogFactory(后文提到,其是一个日志对象工场)名为org.apache.commons.logging.Log的配置属性。针对该属性可以通过Java代码显式设置配置属性,但是更常见的是通过在类路径中放置一个名为commons-logging.properties的文件来进行设置。当存在这样的文件时,属性文件中的每个条目都将成为LogFactory的“属性”。如果类路径中有多个此类文件,则1.1版本之前的commons-logging版本仅使用找到的第一个文件。从版本1.1开始,每个文件都可以定义优先级密钥,并且使用优先级最高的文件(没有优先级定义表示优先级为零)。当多个文件具有相同的优先级时,将使用找到的第一个文件。

    建议在commons-logging.properties文件中定义此属性,以明确选择Log实现。

  2. 查找一个名为org.apache.commons.logging.Log的系统属性 ,并以该属性值作为日志实现。
  3. 查看类路径中是否有 Log4j 的包,如果发现,则自动使用 Log4j 作为日志实现类。
  4. 如果应用程序在JDK 1.4系统上执行,则使用相应的包装器类(即采用Java语言自带的日志实现)。
  5. 退回到默认的简单日志记录包装器(Simple日志,commons-logging自带的日志实现)。  

通过以上5种方式,commons-logging便完成了接口与实现的衔接。

接着,我们来谈下commons-logging接口的使用方法。由于其是第三方组件,所以第一件事便是通过Maven将其引入到项目依赖中。其配置如下所示:

<dependency>  
    <groupId>commons-logging</groupId>  
    <artifactId>commons-logging</artifactId>  
    <version>1.2</version>  
</dependency>  

然后,便可以采用LogFactory创建一个Log对象,开启日志之旅,如下所示:

package org.example;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Commons-logging
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        Log log = LogFactory.getLog(App.class);
        log.info("this is info!");
    }
}

Commons Logging定义了6个日志级别:

  • FATAL
  • ERROR
  • WARNING
  • INFO
  • DEBUG
  • TRACE

默认级别是INFO,在项目中,我们可以根据实际需求选择我们需要的日志登记。

2.log4j:

log4j 全称为log for(4) java, 即一个java日志组件。从使用者角度来看,log4j主要由三大部分组成:Logger, Appender, Formatter。

为了使用log4j,同样需要在maven中引入其依赖:

<dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
</dependency>
  • Logger:简而言之,logger就是一个用于获取日志对象,并写入日志的类,获取该对象的方法也有多种,如下所示:

    //Shorthand for getLogger(clazz.getName()).
    static Logger getLogger(Class clazz)
        
    //Retrieve a logger named according to the value of the name parameter.      
    static Logger getLogger(String name)
    
    
    //Like getLogger(String) except that the type of logger instantiated depends on the type returned by the           
    static Logger getLogger(String name, LoggerFactory factory)
    
    // method of the factory parameter.
    LoggerFactory.makeNewLoggerInstance(java.lang.String)
    
    //Return the root logger for the current logger repository.
    static Logger getRootLogger()
    

    Logger类是日志包的核心,Logger的名称是大小写敏感的,并且名称之间有继承关系。子名由父名做前缀,用点号“.”分隔,如x.y是x.y.z的父亲Logger。

    Logger系统中有个根logger,是所有logger的祖先,它总是存在的,并且不可以通过名字获取,可以通过Logger.getRootLogger()来获取。

并且一个Logger可以拥有多个Appender,这样同一条日志消息可以输出到多个地方。每个logger都有一个日志级别,用来控制日志的         输出。未分配级别的logger将自动继承它最近的父logger的日志级别。Logger的由低到高级别如下:

       ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF

  • Appender:在编程语言中,append方法往往出现在容器类中,用于给容器添加特定对象。同样,在log4j中,可以将不同的日志输出目的地看作不同的日志容器,比如控制台、文件、邮箱、数据库等。这样当给一个logger对象指定相应的appender时,便可以将相关日志输出到对应的目的地中。Log4j提供了以下几个实现:

    org.apache.log4j.ConsoleAppender(控制台)
    org.apache.log4j.FileAppender(文件)
    org.apache.log4j.DailyRollingFileAppender(每天都产生一个日志文件)
    org.apache.log4j.RollingFileAppender(文件大小达到指定尺寸时产生一个新的日志文件,文件名称上会自动添加数字序号。)
    org.apache.log4j.WriterAppender(将日志信息以流的格式发送到任意指定的地方)

    默认情况下,子logger将继承父logger的所有appenders。rootlogger拥有目标为system.out的consoleAppender,故默认情况下,所有的logger都将继承该appender。

  • Formatter:为了便于阅读,那么格式化便是必不可少的工作,而这部分功能便由Formatter来提供。log4j提供了以下几种formatter实现:

    org.apache.log4j.HTMLLayout(以HTML表格形式布局)
    org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
     

     

那么用户该怎么配置来获取自己想要的日志输出对象呢?Log4j为我们提供来一个叫做log4j.properties文件(需要放在class-path下)让我们配置我们想要的日志功能。首先来看看一个典型的配置文件:

1 ### logger的配置 ###
 2 #配置根logger
 3 log4j.rootLogger=INFO,stdout
 4 #配置子logger:org.lavasoft(在org.lavasoft包中类的日志在没有指定子logger名的情况下使用这个logger)
 5 log4j.logger.org.lavasoft=ERROR,file
 6 #配置子logger:org.lavasoft.test(在org.lavasoft.test包中类的日志在没有指定子logger名的情况下使用这个logger)
 7 log4j.logger.org.lavasoft.test=ERROR,file1,stdout
 8
 9 ### direct log messages to stdout ### (标准的终端输出)
10 #控制台输出
11 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
12 #自定义输出布局
13 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
14 #输出的格式
15 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
16
17 ### direct messages to file ttt.log ### (输入到文件ttt.log的配置)
18 #输出到滚动文件
19 log4j.appender.file=org.apache.log4j.RollingFileAppender
20 #输出文件最大为10M
21 log4j.appender.file.MaxFileSize=10MB
22 #输出文件最大序号为10
23 log4j.appender.file.MaxBackupIndex=10
24 #输出文件路径
25 log4j.appender.file.File=C:/ttt.log
26 #自定义输出布局
27 log4j.appender.file.layout=org.apache.log4j.PatternLayout
28 #输出格式
29 log4j.appender.file.layout.ConversionPattern=%d %-5p [%t] (%13F:%L) %3x - %m%n
30
31 ### direct messages to file ttt.log ### (输入到文件ttt1.log的配置)
32 #输出到滚动文件
33 log4j.appender.file1=org.apache.log4j.RollingFileAppender
34 #输出文件最大为10M
35 log4j.appender.file1.MaxFileSize=10MB
36 #输出文件最大序号为10
37 log4j.appender.file1.MaxBackupIndex=10
38 #输出文件路径
39 log4j.appender.file1.File=C:/ttt1.log
40 #自定义输出布局
41 log4j.appender.file1.layout=org.apache.log4j.PatternLayout
42 #输出格式
43 log4j.appender.file1.layout.ConversionPattern=%d %-5p [%t] (%13F:%L) %3x - %m%n

下面对以上的文件解说,并给出一个应用例子:

logger的配置语法为:级别,输入终端1,输出终端2,…

根logger的配置项为:log4j.rootLogger

子logger的配置项为:

log4j.logger.<子logger名>

在上面的配置项中,配置了一个根logger和两个子logger,名称为:org.lavasoft和org.lavasoft.test,通过该名称,利用Logger.getLogger(String name)可以获取这两个logger对象。

子logger的名字一般都以包名来配置,这样当在程序通过类名获取logger的对象就是与本类包名相同的子logger,这样可以方便控制某个包下面logger的输出。

但是一般不建议设置子logger,一个通用的根logger足够用了。由于继承关系,并且可以在任何地方通过子logger的名字获取logger对象,这样容易导致混乱,比如在org.lavasoft包下的类直接获取了名为org.lavasoft.test子logger的对象,这是不合理的(虽然日志可以打印出来),因为如果直接在类中用Logger.getLogger(Class clazz)方式来获取Logger对象,则获取到的应该是名为org.lavasoft的logger对象,而不会得到名为org.lavasoft.test的logger对象。

以上的配置文件纯粹是为了说明问题才那么写的。

最后再列出一个典型的配置文件,以供大家实际项目中使用:

### 配置根 debug level,后面均为定义的appender###
log4j.rootLogger = debug,console ,fileAppender,dailyRollingFile,ROLLING_FILE,MAIL,DATABASE

### 设置输出sql的级别,其中logger后面的内容全部为jar包中所包含的包名,这样logger的appender继承于rootlogger ###
log4j.logger.org.apache=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug
### 配置输出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n

### 配置输出到文件 ###
log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = logs/log.log
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG
log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 配置输出到文件,并且每天都创建一个文件 ###
log4j.appender.dailyRollingFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.File = logs/log.log
log4j.appender.dailyRollingFile.Append = true
log4j.appender.dailyRollingFile.Threshold = DEBUG
log4j.appender.dailyRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyRollingFile.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n### 配置输出到文件,且大小到达指定尺寸的时候产生一个新的文件 ###log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender log4j.appender.ROLLING_FILE.Threshold=ERROR log4j.appender.ROLLING_FILE.File=rolling.log log4j.appender.ROLLING_FILE.Append=true log4j.appender.ROLLING_FILE.MaxFileSize=10KB log4j.appender.ROLLING_FILE.MaxBackupIndex=1 log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

### 配置输出到邮件 ###
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=chenyl@yeqiangwei.com
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=chenyl@yeqiangwei.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

### 配置输出到数据库 ###
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值