ITPub博客

首页 > IT基础架构 > 网络安全 > log4j配置详解

log4j配置详解

原创 网络安全 作者:polalisi 时间:2007-08-31 15:22:44 0 删除 编辑

一:配置
A:)
Web Application 中使用log4j
Step 1:
配置log4j配置文件

=========================
# Set root logger level to DEBUG and its only appender to A1
#log4j
中有五级logger
#FATAL0
#ERROR3
#WARN4
#INFO6
#DEBUG7
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
#log4j
Appender有几层

#ConsoleAppender
输出到控制台
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#
输出格式 具体查看log4j javadoc org.apache.log4j.PatternLayout
#d
时间
....
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

================================另外一种配置
log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
#R
输出到文件

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

Step 2:写启动的Servlet

public class InitServlet extends HttpServlet {

public void init() {
ServletContext sct = getServletContext();
String prefix = sct.getRealPath("/");
//log4j
配置文件存放目录

System.out.println("[....Log4j]: The Root Path: " + prefix);
System.out.println("[....Log4j]: InitServlet init start...");
String file = getInitParameter("log4j");
//log4j
配置文件
if (file != null) {
PropertyConfigurator.configure(prefix + file);
//
根据配置初始化log4j
}

System.out.println("[....Log4j]: InitServlet Init Sucess...");

}

public void doGet(HttpServletRequest req, HttpServletResponse res) {

}

public void doPost(HttpServletRequest req, HttpServletResponse res) {

}
}

B:在一般的IDE中使用log4j,因为使用log4j需要做一些初始化,在Web Application中这一部分初始化是有AppServer 启动是加载的。在IDE中,则我们在使用log4j之前需要自己配置一下。如下文件:
public final class Lo4jTest {
private static String CLASS_NAME = "com.bingo.test.Lo4jTest";
private static Logger log = Logger.getLogger(CLASS_NAME);
//
Web Application 中下面的pattern是在log4j的配置文件中配置的。
//
现在我们手动配置
private static String pattern="%-4r [%-t] [%p] [%c] [%x] - [%m]%n";
private static String pattern2="%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n";
//
设置输出层
//
private static ConsoleAppender consAppender =
new ConsoleAppender(
new PatternLayout(pattern2));
public static void main(String[] args) {
//
配置log4j
BasicConfigurator.configure(consAppender);
// void configure(Appender appender);
// void configure();
//
配置时log4j提供了两种方式

//
后一种比较简单,输出的信息不够详细
//
我们可以使用前一种输出我们希望的格式
log.debug("Log4j Debug.");
log.error("Log4j Error.");
log.info("Log4j Info.");
log.fatal("Log4j Fatal.");
}
}
//
使用pattern2上面的输出结果如下
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[DEBUG] Log4j Debug.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[ERROR] Log4j Error.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[INFO] Log4j Info.
2002-08-30 13:49:09 [com.bingo.test.Lo4jTest]-[FATAL] Log4j Fatal.
//
假如我们使用pattern输出如下:
0 [main] [DEBUG] [com.bingo.test.Lo4jTest] [] - [Log4j Debug.]
0 [main] [ERROR] [com.bingo.test.Lo4jTest] [] - [Log4j Error.]
0 [main] [INFO] [com.bingo.test.Lo4jTest] [] - [Log4j Info.]
0 [main] [FATAL] [com.bingo.test.Lo4jTest] [] - [Log4j Fatal.]

二:使用log4j在实际使用过程中其实非常简单

1:)如下定义log,log4j1.2以前使用Category,log4j1.2以后使用Logger代替
private static String CLASS_NAME = "com.bingo.test.Lo4jTest";
//log4j1.2
private static Logger log = Logger.getLogger(CLASS_NAME);
//lo4j1.2
以前
private static Category log =Category.getInstance(CLASS_NAME);
//
取得一个Category or Logger有几种方式,根据自己需要使用

2:)写日志
log.debug("Log4j Debug.");
log.error("Log4j Error.");
log.info("Log4j Info.");
log.fatal("Log4j Fatal.");
//void debug(Object message)
//Log a message object with the DEBUG level.
//void debug(Object message, Throwable t)
//Log a message object with the DEBUG level including the
//stack trace of the Throwable t passed as parameter.

三:注意事项
1:
在具体使用中注意不同的信息使用不同的log方式,选择debug,error,
info,fatal
中的一种,以后可以根据需要屏蔽部分输出

2:
开发过程中尽量输出到控制台,运行过程中则修改配置使其输出到文件.
3:
定义log尽量使用文件名作为参数,这样容易查找错误.

出处:http://www.javaunion.org/bbs/cgi-bin/topic.cgi?forum=36&topic=20&show=25'


==============================================================
以下是与Tomcat交互的:
log4j
的介绍(一)——log4jtomcat结合的简单配置

log4japacheibm联合弄得一个应用系统日志管理工具,利用它的api可以方便的管理和操纵日志。在调试程序的时候,是一个非常不错的调试帮手。有关log4j的一些介绍,大家可以参考apache的网站(http://jakarta.apache.org/log4j/docs/index.html

下面在开始介绍以前,首先推荐一点资料,大家看看,有助于了解。
(1)
Log4j delivers control over logging
http://www-106.ibm.com/developerworks/java/library/jw-log4j/
(2)http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
这里面介绍了有关layout.ConversionPattern中的转意字符的含义。

(一)与tomcat结合的简单配置
首先到 http://jakarta.apache.org/log4j/docs/download.html 下载一
log4j,目前版本是1.2.5。下载的文件中有详细的介绍和实例、apidoc,可以参考一下。
log4j-1.2.5.jar的放到系统classpath中。最好在%tomca_home%/lib/也方一份更好哦。(在此注意一个问题,据说log4j-1.2.5.jar这个文件的文件名,weblogic6.1不能识别,需要改一个名字)

1.1描写properties文件。
这个描述文件一般放在可以放在两个地方:(1WEB-INF/classes目录下,或者放在在/project_root/,也就是你的web_app的根目录下。利用这个控制日志纪录的配置,当然也可以通过xml文件配置,这里我们暂且说说properties的配置。

建立文件名log4j.properties文件。放在%tomca_home%/web_app/fcxtest/目录下。
文件内容如下:(fcxtest为自己建立的web app目录)

#--------------------------------
#
设定loggerroot levelDEBUG,指定的输出目的地(appender)为
A1
log4j.rootLogger=DEBUG, A1

# 设定调试信息的输出位置,此处设定输出为控制台
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# 设定调试信息的输出位置,此处设定输出为fcxtest.log文件
# log4j.appender.A1=org.apache.log4j.RollingFileAppender
# log4j.appender.A1.File=fcxtest.log
# log4j.appender.A1.MaxFileSize=1000KB

# 设定制定的A1使用的PatternLayout.
#
有关ConversionPattern中的转意字符的含义参考说明

log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
#--------------------------------


1.2
建立测试用的Servlet
这个测试的com.fcxlog.LogShow类主要是显示如何使用log4j

package com.fcxlog;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

public class LogShow extends javax.servlet.http.HttpServlet{

protected String configfile = "log4j.properties";

public void init() throws ServletException{
ServletContext sct = getServletContext();
System.out.println("[Log4j]: The Root Path: " + sct.getRealPath("/"));
//
指定自己的properties文件

//
以前使用的是BasicConfigurator.configure(),现在使用PropertyConfigurator替代

org.apache.log4j.PropertyConfigurator.configure(sct.getRealPath("/") + configfile);
}

public void service(javax.servlet.http.HttpServletRequest req,javax.servlet.http.HttpServletResponse res){

//
初始化Logger,以前使用Category,现在改用Logger替代

//org.apache.log4j.Category log = org.apache.log4j.Category.getInstance(LogShow.class);
org.apache.log4j.Logger log = ora.apache.log4j.Logger.getLogger(LogShow.class);
log.info("
调试信息
");

}
}


1.3
测试了
至于如何测试,发布,就不说了。

在此说明: 1)本篇可能错误不少,一方面是参考《Short introduction to log4j》着翻译了一点,有诸多言辞不妥之处,还望指正。一方面,凭借自己的理解,所以难免有不全的地方,还望各位补充。 2)因为时间有限,每天只能写一点,本文主要是介绍有关LoggerLogger level相关概念的 3)有关Log4j介绍(一),请参阅:http://www.javaren.com/bbs/cgi-bin/topic.cgi?forum=1&topic=12766&show=0#lastviewpost

概述:
本文主要是简要的介绍了Log4japi,以及其一些特征和设计原理。它本身是一个开源的软件,允许开发者任意的操纵应用系统日志信息。Log4j的使用通过外部配置文件进行配置。

任何大型应用系统都有其自己的系统日志管理或跟踪的API,所以在1996年的时候,E.U. SEMPER项目组(http://www.semper.org/)也开发其自己的日志管理API,后来经过无数次的修改和补充,发展成了现在的log4j,一个给予java的日志管理工具包。有关最新的版本信息和源码,请访问http://jakarta.apache.org/log4j/docs/index.html 把纪录语句放在代码之中,是一种低端的调试方法,不过有时却不得不说是很有效,也是必需的。毕竟很多时候,调试器并不见得很适用。特别是在多线程应用程序(multithread application)或分布式应用程序(distributed application

经验告诉我们,在软件开发生命周期中,日志系统是一个非常重要的组件。当然,日志系统也有其自身的问题,过多的日志纪录会降低系统运行的速度。

(一)Log4j的三个重要组件—— Loggers, Appenders, Layouts

这三个组件协同的工作,使得开发者能够依据信息类别和级别去纪录信息,并能够运行期间,控制信息记录的方式已经日志存放地点。

(二)记录器层次(Logger hierarchy

几乎任何纪录日志的API得功能都超越了简单的System.out.print语句。允许有选择控制的输出日志信息,也就是说,某的时候,一些日志信息允许输出,而另一些则不允许输出。这就假设日志纪录信息之间是有分别的,根据开发者自己定义的选择标准,可以对日志信息加以分类。


纪录器的命名是依据实体的。下面有一段有点绕口的解释,我就直抄了,各位可以看看:(Name Hierarchy
A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.
(形象的解释,比如存在记录器 a.b.c,记录器a.b,记录器a。那么a就是a.bancestor,而a.b就是a.b.cparent,而a.b.c就是a.bchild


根纪录器(root logger)是记录器层次的顶端。它有两个独特点:(1)总是存在的(2)能够被重新找回。可以通过访问类的静态方法 Logger.getRootLogger 重新得到。其他的纪录器通过访问静态方法 Logger.getLogger 被实例话或被得到,这个方法将希望获得的记录器的名称作为参数。一些Logger类的方法描述如下:

public class Logger {
// Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name);
// printing methods:
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);

// generic printing method:
public void log(Level l, Object message);
}

记录器被赋予级别,这里有一套预定的级别标准:DEBUG, INFO, WARN, ERROR and FATAL ,这些是在 org.apache.log4j.Level 定义的。你可以通过继承Level类定义自己的级别标准,虽然并不鼓励这么做。
如果给定的记录器没有被赋予级别,则其会从离其最近的拥有级别的ancestor处继承得到。如果ancestor也没有被赋予级别,那么就从根记录器继承。所以通常情况下,为了让所有的记录器最终都能够被赋予级别,跟记录器都会被预先设定级别的。比如我们在操作properties文件中,会写这么一句:log4j.rootLogger=DEBUG, A1 。实际上就这就指定了root Loggerroot Logger level

Appenders
Log4j
允许记录信息被打印到多个输出目的地,一个输出目的地叫做Appender。目前的Log4j存在的输出目的地包括:控制台(Console,文件(File),GUI ComponenntRemote Socket ServerJMSNT Event Loggerand Remote Unix Syslog daemons

多个Appender可以绑定到一个记录器上(Logger)。

通过方法 addAppenderLogger.addAppender)可以将一个Appender附加到一个记录器上。每一个有效的发送到特定的记录器的记录请求都被转送到那个与当前记录器所绑定的Appender上。(Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy),换句话说,Appender的继承层次是附加在记录器继承层次上的。举个例子:如果一个Console Appender被绑定到根记录器(root Logger),那么所有的记录请求都可以至少被打印到Console。另外,把一个file Appender绑定到记录器C,那么针对记录器C(或C的子孙)的记录请求都可以至少发送到Console Appenderfile Appender。当然这种默认的行为方式可以跟改,通过设定记录器的additivity flagLogger.setAdditivity)为false,从而可以使得Appender的不再具有可加性(Additivity)。

下面简要介绍一下Appender Additivity

Appender Additivity
:记录器C所记录的日志信息将被发送到与记录器C以及其祖先(ancestor)所绑定的所有Appender

但是,如果记录器C的祖先,叫做P,它的additivity flag被设定为false。那么,记录信息仍然被发送到与记录器C及其祖先,但只到达P这一层次,包括P在内的记录器的所有Appender。但不包括P祖先的。

通常,记录器的additivity flag的被设置为true


Layouts
这一块主要是介绍输出格式的。PatternLayoutLog4j标准的分配器,可以让开发者依照conversion patterns去定义输出格式。Conversion patterns有点像c语言的打印函数。
参看配置文件的java properties,如下面的两行:

log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
第一行就指定了分配器,第二行则指定了输出的格式。

有关输出格式的定义可以参考/org/apache/log4j/PatternLayout.html

============================================================

再贴一篇实例:使用Log4j进行日志操作

1. 概述

1.1. 背景

在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。

最普通的做法就是在代码中嵌入许多的打印语句,这些打印语句可以输出到控制台或文件中,比较好的做法就是构造一个日志操作类来封装此类操作,而不是让一系列的打印语句充斥了代码的主体。

1.2. Log4j简介

在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-Log4j

Log4jApache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

此外,通过Log4j其他语言接口,您可以在CC++.NetPL/SQL程序中使用Log4j,其语法和用法与在Java程序中一样,使得多语言分布式系统得到一个统一一致的日志组件模块。而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EEJINI甚至是SNMP应用中。

本文介绍的Log4j版本是1.2.3。作者试图通过一个简单的客户/服务器Java程序例子对比使用与不使用Log4j 1.2.3的差别,并详细讲解了在实践中最常使用Log4j的方法和步骤。在强调可重用组件开发的今天,相信Log4j将会给广大的设计开发人员带来方便。加入到Log4j的队伍来吧!

2. 一个简单的例子

我们先来看一个简单的例子,它是一个用Java实现的客户/服务器网络程序。刚开始我们不使用Log4j,而是使用了一系列的打印语句,然后我们将使用Log4j来实现它的日志功能。这样,大家就可以清楚地比较出前后两个代码的差别。

2.1. 不使用Log4j

2.1.1. 客户程序

package log4j ;

import java.io.* ;
import java.net.* ;

/**
*
*

Client Without Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ClientWithoutLog4j {

/**
*
* @param args
*/
public static void main ( String args [] ) {

String welcome = null;
String response = null;
BufferedReader reader = null;
PrintWriter writer = null;
InputStream in = null;
OutputStream out = null;
Socket client = null;

try {
client = new Socket ( "localhost", 8001 ) ;
System.out.println ( "info: Client socket: " + client ) ;
in = client.getInputStream () ;
out = client.getOutputStream () ;
} catch ( IOException e ) {
System.out.println ( "error: IOException : " + e ) ;
System.exit ( 0 ) ;
}

try{
reader = new BufferedReader( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

welcome = reader.readLine () ;
System.out.println ( "debug: Server says: '" + welcome + "'" ) ;

System.out.println ( "debug: HELLO" ) ;
writer.println ( "HELLO" ) ;
response = reader.readLine () ;
System.out.println ( "debug: Server responds: '" + response + "'") ;

System.out.println ( "debug: HELP" ) ;
writer.println ( "HELP" ) ;
response = reader.readLine () ;
System.out.println ( "debug: Server responds: '" + response + "'" ) ;

System.out.println ( "debug: QUIT" ) ;
writer.println ( "QUIT" ) ;
} catch ( IOException e ) {
System.out.println ( "warn: IOException in client.in.readln()" ) ;
System.out.println ( e ) ;
}
try{
Thread.sleep ( 2000 ) ;
} catch ( Exception ignored ) {}
}
}

2.1.2. 服务器程序

package log4j ;

import java.util.* ;
import java.io.* ;
import java.net.* ;

/**
*
*

Server Without Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ServerWithoutLog4j {

final static int SERVER_PORT = 8001 ; // this server's port

/**
*
* @param args
*/
public static void main ( String args [] ) {
String clientRequest = null;
BufferedReader reader = null;
PrintWriter writer = null;
ServerSocket server = null;
Socket socket = null;
InputStream in = null;
OutputStream out = null;

try {
server = new ServerSocket ( SERVER_PORT ) ;
System.out.println ( "info: ServerSocket before accept: " + server ) ;
System.out.println ( "info: Java server without log4j, on-line!" ) ;

// wait for client's connection
socket = server.accept () ;
System.out.println ( "info: ServerSocket after accept: " + server ) ;

in = socket.getInputStream () ;
out = socket.getOutputStream () ;

} catch ( IOException e ) {
System.out.println( "error: Server constructor IOException: " + e ) ;
System.exit ( 0 ) ;
}
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ) , true ) ;

// send welcome string to client
writer.println ( "Java server without log4j, " + new Date () ) ;

while ( true ) {
try {
// read from client
clientRequest = reader.readLine () ;
System.out.println ( "debug: Client says: " + clientRequest ) ;
if ( clientRequest.startsWith ( "HELP" ) ) {
System.out.println ( "debug: OK!" ) ;
writer.println ( "Vocabulary: HELP QUIT" ) ;
}
else {
if ( clientRequest.startsWith ( "QUIT" ) ) {
System.out.println ( "debug: OK!" ) ;
System.exit ( 0 ) ;
}
else{
System.out.println ( "warn: Command '" +
clientRequest + "' not understood." ) ;
writer.println ( "Command '" + clientRequest
+ "' not understood." ) ;
}
}
} catch ( IOException e ) {
System.out.println ( "error: IOException in Server " + e ) ;
System.exit ( 0 ) ;
}
}
}
}

2.2. 迁移到Log4j

2.2.1. 客户程序

package log4j ;

import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
*
*

Client With Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ClientWithLog4j {

/*
add for log4j: class Logger is the central class in the log4j package.
we can do most logging operations by Logger except configuration.
getLogger(...): retrieve a logger by name, if not then create for it.
*/
static Logger logger = Logger.getLogger
( ClientWithLog4j.class.getName () ) ;

/**
*
* @param args : configuration file name
*/
public static void main ( String args [] ) {

String welcome = null ;
String response = null ;
BufferedReader reader = null ;
PrintWriter writer = null ;
InputStream in = null ;
OutputStream out = null ;
Socket client = null ;

/*
add for log4j: class BasicConfigurator can quickly configure the package.
print the information to console.
*/
PropertyConfigurator.configure ( "ClientWithLog4j.properties" ) ;

// add for log4j: set the level
// logger.setLevel ( ( Level ) Level.DEBUG ) ;

try{
client = new Socket( "localhost" , 8001 ) ;

// add for log4j: log a message with the info level
logger.info ( "Client socket: " + client ) ;

in = client.getInputStream () ;
out = client.getOutputStream () ;
} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error ( "IOException : " + e ) ;

System.exit ( 0 ) ;
}

try{
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

welcome = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server says: '" + welcome + "'" ) ;

// add for log4j: log a message with the debug level
logger.debug ( "HELLO" ) ;

writer.println ( "HELLO" ) ;
response = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server responds: '" + response + "'" ) ;

// add for log4j: log a message with the debug level
logger.debug ( "HELP" ) ;

writer.println ( "HELP" ) ;
response = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Server responds: '" + response + "'") ;

// add for log4j: log a message with the debug level
logger.debug ( "QUIT" ) ;

writer.println ( "QUIT" ) ;
} catch ( IOException e ) {

// add for log4j: log a message with the warn level
logger.warn ( "IOException in client.in.readln()" ) ;

System.out.println ( e ) ;
}
try {
Thread.sleep ( 2000 ) ;
} catch ( Exception ignored ) {}
}
}

2.2.2. 服务器程序

package log4j;

import java.util.* ;
import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
*
*

Server With Log4j


*

Description: a sample with log4j


* @version 1.0
*/
public class ServerWithLog4j {

final static int SERVER_PORT = 8001 ; // this server's port

/*
add for log4j: class Logger is the central class in the log4j package.
we can do most logging operations by Logger except configuration.
getLogger(...): retrieve a logger by name, if not then create for it.
*/
static Logger logger = Logger.getLogger
( ServerWithLog4j.class.getName () ) ;

/**
*
* @param args
*/
public static void main ( String args[]) {
String clientRequest = null ;
BufferedReader reader = null ;
PrintWriter writer = null ;
ServerSocket server = null ;
Socket socket = null ;

InputStream in = null ;
OutputStream out = null ;

/*
add for log4j: class BasicConfigurator can quickly configure the package.
print the information to console.
*/
PropertyConfigurator.configure ( "ServerWithLog4j.properties" ) ;

// add for log4j: set the level
// logger.setLevel ( ( Level ) Level.DEBUG ) ;

try{
server = new ServerSocket ( SERVER_PORT ) ;

// add for log4j: log a message with the info level
logger.info ( "ServerSocket before accept: " + server ) ;

// add for log4j: log a message with the info level
logger.info ( "Java server with log4j, on-line!" ) ;

// wait for client's connection
socket = server.accept() ;

// add for log4j: log a message with the info level
logger.info ( "ServerSocket after accept: " + server ) ;

in = socket.getInputStream() ;
out = socket.getOutputStream() ;

} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error ( "Server constructor IOException: " + e ) ;
System.exit ( 0 ) ;
}
reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

// send welcome string to client
writer.println ( "Java server with log4j, " + new Date () ) ;

while ( true ) {
try {
// read from client
clientRequest = reader.readLine () ;

// add for log4j: log a message with the debug level
logger.debug ( "Client says: " + clientRequest ) ;

if ( clientRequest.startsWith ( "HELP" ) ) {

// add for log4j: log a message with the debug level
logger.debug ( "OK!" ) ;

writer.println ( "Vocabulary: HELP QUIT" ) ;
}
else {
if ( clientRequest.startsWith ( "QUIT" ) ) {

// add for log4j: log a message with the debug level
logger.debug ( "OK!" ) ;

System.exit ( 0 ) ;
}
else {

// add for log4j: log a message with the warn level
logger.warn ( "Command '"
+ clientRequest + "' not understood." ) ;

writer.println ( "Command '"
+ clientRequest + "' not understood." ) ;
}
}
} catch ( IOException e ) {

// add for log4j: log a message with the error level
logger.error( "IOException in Server " + e ) ;

System.exit ( 0 ) ;
}
}
}
}

2.2.3. 配置文件

2.2.3.1. 客户程序配置文件

log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

2.2.3.2. 服务器程序配置文件

log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

2.3. 比较

比较这两个应用可以看出,采用Log4j进行日志操作的整个过程相当简单明了,与直接使用System.out.println语句进行日志信息输出的方式相比,基本上没有增加代码量,同时能够清楚地理解每一条日志信息的重要程度。通过控制配置文件,我们还可以灵活地修改日志信息的格式,输出目的地等等方面,而单纯依靠System.out.println语句,显然需要做更多的工作。

下面我们将以前面使用Log4j的应用作为例子,详细讲解使用Log4j的主要步骤。

3. Log4j基本使用方法

Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。日志信息的优先级从高到低有ERRORWARNINFODEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。

3.1.定义配置文件

其实您也可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是Java特性文件(键=值)。下面我们介绍使用Java特性文件做为配置文件的方法:

配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, …其中,level 是日志记录的优先级,分为OFFFATALERRORWARNINFODEBUGALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERRORWARNINFODEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
appenderName
就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

配置日志信息输出目的地Appender,其语法为

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1

log4j.appender.appenderName.option = valueN
其中,Log4j提供的appender有以下几种:

org.apache.log4j.ConsoleAppender
(控制台),
org.apache.log4j.FileAppender
(文件),
org.apache.log4j.DailyRollingFileAppender
(每天产生一个日志文件),org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender
(将日志信息以流格式发送到任意指定的地方)

配置日志信息的格式(布局),其语法为:

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1

log4j.appender.appenderName.layout.option = valueN
其中,Log4j提供的layout有以下几种:

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

3.2.在代码中使用Log4j

下面将讲述在程序代码中怎样使用Log4j

3.2.1.得到记录器

使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:


public static Logger getLogger( String name)
通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:

static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
3.2.2.
读取配置文件

当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:
BasicConfigurator.configure ()
: 自动快速地使用缺省Log4j环境。
PropertyConfigurator.configure ( String configFilename)
:读取使用Java的特性文件编写的配置文件。
DOMConfigurator.configure ( String filename )
:读取XML形式的配置文件。

3.2.3.插入记录信息(格式化日志信息)

当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:

Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;

4. 参考资料

如果您想更深入地了解Log4j,请经常访问下面提及的相关链接。
Log4j
项目主页------------------------------------------------------www.log4j.org
Log4j FAQ -------------------------------------------------------www.log4j.org/log4j/faq.html

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10455649/viewspace-967240/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    59
  • 访问量
    56409