在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用程序进行
统计分析工作,跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码
的调试信息。
在强调可重用组件开发的今天,Apache为我们提供了一个强有力的日志操作包-Log4j。
Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至
是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信
息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而
不需要修改应用的代码。
下面是网上看到的一个简单的客户/服务器端Java程序例子使用与不使用Log4j的区别。开始看这个例子的时候觉得很模糊,后来
动手实现,看到输出结果后便有了恍然大悟的感觉,然后再去理解自己不懂的地方。
开始不使用Log4j而使用一系列的打印语句。
不使用Log4j
客户端程序
public class ClientWithoutLog4j {
static Logger logger=Logger.getLogger(ClientWithoutLog4j.class.getName());
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;
PropertyConfigurator.configure(".//WebContent/WEB-INF/log4j_client.properties");
logger.setLevel(Level.DEBUG);
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.readIn()");
System.out.println(e);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
服务器端程序
public class ServerWithoutLog4j {
static Logger logger = Logger.getLogger(ServerWithoutLog4j.class.getName());
final static int SERVER_PORT = 8001;
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;
PropertyConfigurator
.configure(".//WebContent/WEB-INF/log4j_server.properties");
try {
server = new ServerSocket(SERVER_PORT);
System.out.println("info:ServerSocket before accept: "+server);
System.out.println("info:Java server without log4j,on-line");
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);
writer.println("Java server without log4j, " + new Date());
while (true) {
// read from client
try {
clientRequest = reader.readLine();
} catch (IOException e) {
System.out.println ( "error: IOException in Server " + e ) ;
System.exit(0);
}
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.");
}
}
}
}
}
使用Log4j之后:
客户端程序:
public class ClientWithLog4j {
static Logger logger=Logger.getLogger(ClientWithoutLog4j.class.getName());
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;
PropertyConfigurator.configure(".//WebContent/WEB-INF/log4j_client.properties");
logger.setLevel(Level.DEBUG);
try {
client=new Socket("localhost",8001);
logger.info("Client socket:"+client);
in=client.getInputStream();
out=client.getOutputStream();
} catch (IOException e) {
logger.error("IOException:"+e);
System.exit(0);
}
try {
reader=new BufferedReader(new InputStreamReader(in));
writer=new PrintWriter(new OutputStreamWriter(out),true);
welcome=reader.readLine();
logger.debug("Server says '"+welcome+"'");
logger.debug("HELLO");
writer.println("HELLO");
response=reader.readLine();
logger.debug("Server responds '"+response+"'");
logger.debug("HELP");
writer.println("HELP");
response=reader.readLine();
logger.debug("Server responds '"+response+"'");
logger.debug("QUIT");
writer.println("QUIT");
} catch (IOException e) {
logger.warn("IOException in client.in.readIn()");
System.out.println(e);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
服务器端程序
public class ServerWithoutLog4j {
static Logger logger = Logger.getLogger(ServerWithoutLog4j.class.getName());
final static int SERVER_PORT = 8001;
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;
PropertyConfigurator
.configure(".//WebContent/WEB-INF/log4j_server.properties");
try {
server = new ServerSocket(SERVER_PORT);
logger.info("ServerSocket before accept: " + server);
logger.info("Java server without log4j,on-line");
socket = server.accept();
logger.info(" ServerSocket after accept: " + server);
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException e) {
logger.error("Server constructor IOException: " + e);
System.exit(0);
}
reader = new BufferedReader(new InputStreamReader(in));
writer = new PrintWriter(new OutputStreamWriter(out), true);
writer.println("Java server without log4j, " + new Date());
while (true) {
// read from client
try {
clientRequest = reader.readLine();
} catch (IOException e) {
logger.error("IOException in Server " + e);
System.exit(0);
}
logger.debug("Client says:" + clientRequest);
if (clientRequest.startsWith("HELP")) {
logger.debug("OK!");
writer.println("Vocabulary: HELP QUIT");
} else {
if (clientRequest.startsWith("QUIT")) {
logger.debug("OK!");
System.exit(0);
} else {
logger.warn("warn: Command '" + clientRequest
+ "' not understood.");
writer.println("Command '" + clientRequest
+ "' not understood.");
}
}
}
}
}
注意这里的配置文件路径,因为我之前一直找不到配置文件
PropertyConfigurator.configure(".//WebContent/WEB-INF/log4j_server.properties");
客户端配置文件 log4j_client.properties
log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#%c ---full classname
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
服务器端的配置文件 log4j_server.properties
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
服务器端输出如下:
0 INFO [main] com.spring.log4j.ServerWithoutLog4j -ServerSocket before accept: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8001]
1 INFO [main] com.spring.log4j.ServerWithoutLog4j -Java server without log4j,on-line
32053 INFO [main] com.spring.log4j.ServerWithoutLog4j - ServerSocket after accept: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8001]
32061 WARN [main] com.spring.log4j.ServerWithoutLog4j -warn: Command 'HELLO' not understood.
客户端输出如下:
0 INFO [main] com.spring.log4j.ClientWithoutLog4j - Client socket:Socket[addr=localhost/127.0.0.1,port=8001,localport=11249]
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - Server says 'Java server without log4j, Sun Dec 14 16:37:33 CST 2014'
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - HELLO
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - Server responds 'Command 'HELLO' not understood.'
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - HELP
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - Server responds 'Vocabulary: HELP QUIT'
8 DEBUG [main] com.spring.log4j.ClientWithoutLog4j - QUIT
输出的日志信息由配置文件中的log4j.appender.A1.layout.ConversionPattern所规定的格式定义
Log4j基本使用方法
Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式。
日志信息的优先级从高到低有ERROR、WARN、INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;
而输出格式则控制了日志信息的显示内容。
定义配置文件
Log4j支持两种配置文件格式:XML格式的文件和Java特性文件(键=值)。下面介绍使用Java特性文件作为配置文件的方法:
1 配置根Logger ,语法
log4j.rootLogger = [ level ] , appenderName, appenderName, …
level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。
2、配置日志信息输出目的地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(将日志信息以流格式发送到任意指定的地方)
3、配置日志信息的格式(布局),其语法为:
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(包含日志产生的时间、线程、类别等等信息)
在代码中使用Log4j
1、得到记录器
使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:
public static Logger getLogger( String name),
通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
2、读取配置文件
当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:
BasicConfigurator.configure (): 自动快速地使用缺省Log4j环境。
PropertyConfigurator.configure ( String configFilename) :读取使用Java的特性文件编写的配置文件。
DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。
3、插入记录信息(格式化日志信息)
当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:
Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;