自己定义的log4j_logging.properties内容如下
同时要在bin目录里建立一个LOG的文件夹来保存日志信息
ArchivedDailyRollingFileAppender在最后付上全部代码,你可以直接拿来使用
### direct log messages to stdout ###
#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.out
#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.logger.DEL=WARN,Del
### ???????????delLog.log?? ###
log4j.appender.Del=edu.jlu.logger.ArchivedDailyRollingFileAppender
log4j.appender.Del.File=LOG/deleteLog
log4j.appender.Del.DatePattern='_'yyyyMMdd'.log'
#log4j.appender.Del.MaxFileSize=1KB
#log4j.appender.Del.MaxBackupIndex=1
log4j.appender.Del.layout=org.apache.log4j.PatternLayout
log4j.appender.Del.layout.ConversionPattern=%-d [%c]-[%p] %m %-d{yyyy-MM-dd HH:mm:ss}%n
log4j.logger.ADD=INFO,Add
###???????????addLog.log??###
log4j.appender.Add=edu.jlu.logger.ArchivedDailyRollingFileAppender
log4j.appender.Add.File=LOG/createLog
log4j.appender.Add.DatePattern='_'yyyyMMdd'.log'
#log4j.appender.Add.MaxFileSize=100KB
#log4j.appender.Add.MaxBackupIndex=1
log4j.appender.Add.layout=org.apache.log4j.PatternLayout
log4j.appender.Add.layout.ConversionPattern=%-d [%c]-[%p] %m %-d{yyyy-MM-dd HH:mm:ss}%n
log4j.logger.LOG=INFO,Log
###???????????loginLog.log?? ###
log4j.appender.Log=edu.jlu.logger.ArchivedDailyRollingFileAppender
log4j.appender.Log.File=LOG/loginLog
log4j.appender.Log.DatePattern='_'yyyyMMdd'.log'
#log4j.appender.Log.MaxFileSize=100KB
#log4j.appender.Log.MaxBackupIndex=1
log4j.appender.Log.layout=org.apache.log4j.PatternLayout
log4j.appender.Log.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
log4j.logger.ACT=INFO,Act
### ?????????actLog.log?? ###
log4j.appender.Act=edu.jlu.logger.ArchivedDailyRollingFileAppender
log4j.appender.Act.File=LOG/actLog
log4j.appender.Act.DatePattern='_'yyyyMMdd'.log'
#log4j.appender.Act.MaxFileSize=100KB
#log4j.appender.Act.MaxBackupIndex=1
log4j.appender.Act.layout=org.apache.log4j.PatternLayout
log4j.appender.Act.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
log4j.logger.EXC=ERROR,Exc
### ??????????excLog.log?? ###
log4j.appender.Exc=edu.jlu.logger.ArchivedDailyRollingFileAppender
log4j.appender.Exc.File=LOG/exceptionLog
log4j.appender.Exc.DatePattern='_'yyyyMMdd'.log'
#log4j.appender.Exc.MaxFileSize=100KB
#log4j.appender.Exc.MaxBackupIndex=1
log4j.appender.Exc.layout=org.apache.log4j.PatternLayout
log4j.appender.Exc.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
#log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast=debug
### log just the SQL
#log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug
### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
-------------------------------------------------------------------------------------------------------------
首先
web.xml中配置log4j的servlet初始化
<servlet>
<servlet-name>log4jinit</servlet-name>
<servlet-class>edu.jlu.tools.Log4jInit</servlet-class>
<init-param>
<param-name>log4jproperties</param-name>
<param-value>/WEB-INF/log4j_logging.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
其中调用了一个初始化的servlet
package edu.jlu.tools;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/
public class Log4jInit extends HttpServlet {
//Initialize global variables
public void init() throws ServletException {
String prefix = getServletContext().getRealPath("/");
String file = getInitParameter("log4jproperties");
// if the log4j-init-file is not set, then no point in trying
System.out.println("................log4j start"+file);
if(file != null) {
System.out.println("log4j start successed");
System.out.println("path is "+MainListener.getContext().getRealPath("/")+file);
org.apache.log4j.PropertyConfigurator.configure(MainListener.getContext().getRealPath("/")+file);
}
else
System.out.println("log4j start failed");
}
//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response) {
}
//Clean up resources
public void destroy() {
}
}
---------------------------------------------------------------------------------------------------------------
log4j的servlet初始化后
自己定义记录方式的类,同时定义一些静态的记录方式
package edu.jlu.logger;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class LoggerMethods {
/** default constructor */
private LoggerMethods() {
}
//SA删除用户(who)
public static void delLogger(String who) {
Logger logger = Logger.getLogger("DEL");
logger.info("SA deleted " + who + " at ");
}
public static void delLogger(String who, String did)
{
Logger logger = Logger.getLogger("DEL");
logger.info( who + " "+ did);
}
//添加用户日志
public static void addLogger(String who, String did) {
Logger logger = Logger.getLogger("ADD");
logger.info(who + " created " + did + " at ");
}
//登录系统日志
public static void loginLogger(String who) {
Logger logger = Logger.getLogger("LOG");
logger.info(who + " log in ");
}
//动作日志,例如修改操作
public static void actLogger(String who, String did, String toWho) {
Logger logger = Logger.getLogger("ACT");
logger.info(who + " " + did + " " + toWho);
}
//动作日志,没有对象的操作
public static void actLogger(String who, String did) {
Logger logger = Logger.getLogger("ACT");
logger.info(who + " " + did);
}
//异常日志
public static void excLogger(String exception) {
Logger logger = Logger.getLogger("EXC");
logger.error(exception);
}
//这是测试的方式,你可以在你处理请求的servlet或action中直接通过LoggerMethods来调用你想使用的static记录方式
public static void main(String args[]) {
//PropertyConfigurator.configure
//("D:/workspace/csweb/src/log4j.properties");
String name="1";
//delLogger(name,name);
addLogger(name,name);
// loginLogger(name);
// actLogger(name,name,name);
// excLogger(name);
}
}
//还有一个工具类,它的内容注释的很详细,自己看吧!
package edu.jlu.logger;
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
* distribution in the LICENSE.APL file. */
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* This file is adapted directly from the standard DailyRollingFileAppender
* except that it archives the rolled file in a zip format after rolling it.<P>
*
* I would've used inheritance here and then overriden the rollup() method, but some
* of the fields which are required in rollup() are not visible to subclasses.
* Hence the lovely cut-n-paste extension pattern ;)
*
*/
public class ArchivedDailyRollingFileAppender extends FileAppender
{
// The code assumes that the following constants are in a increasing
// sequence.
static final int TOP_OF_TROUBLE = -1;
static final int TOP_OF_MINUTE = 0;
static final int TOP_OF_HOUR = 1;
static final int HALF_DAY = 2;
static final int TOP_OF_DAY = 3;
static final int TOP_OF_WEEK = 4;
static final int TOP_OF_MONTH = 5;
/**
A string constant used in naming the option for setting the
filename pattern. Current value of this string constant is
<strong>DatePattern</strong>.
<at> deprecated Options are now handled using the JavaBeans paradigm.
This constant is not longer needed and will be removed in the
<em>near</em> term.
*/
static final public String DATE_PATTERN_OPTION = "DatePattern";
/**
The date pattern. By default, the pattern is set to
"'.'yyyy-MM-dd" meaning daily rollover.
*/
private String datePattern = "'.'yyyy-MM-dd";
/**
The actual formatted filename that is currently being written to.
*/
private String scheduledFilename;
/**
The timestamp when we shall next recompute the filename.
*/
private long nextCheck = System.currentTimeMillis() - 1;
Date now = new Date();
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar();
int checkPeriod = TOP_OF_TROUBLE;
/**
The default constructor does nothing. */
public ArchivedDailyRollingFileAppender()
{
}
/**
Instantiate a <code>ArchivedDailyRollingFileAppender</code> and open the
file designated by <code>filename</code>. The opened filename will
become the ouput destination for this appender.
*/
public ArchivedDailyRollingFileAppender(Layout layout,
String filename,
String datePattern) throws IOException
{
super(layout, filename, true);
this.datePattern = datePattern;
activateOptions();
}
/**
The <b>DatePattern</b> takes a string in the same format as
expected by { <at> link SimpleDateFormat}. This options determines the
rollover schedule.
*/
public void setDatePattern(String pattern)
{
datePattern = pattern;
}
/** Returns the value of the <b>DatePattern</b> option. */
public String getDatePattern()
{
return datePattern;
}
/**
<at> deprecated We now use JavaBeans introspection to configure
components. Options strings are no longer needed.
*/
public String[] getOptionStrings()
{
return new String[0]; // this is deprecated...
}
/**
Set the options for the { <at> link org.apache.log4j.DailyRollingFileAppender}
instance.
<p>The <b>DatePattern</b> takes a string in the same format as
expected by { <at> link SimpleDateFormat}. This options determines the
rollover schedule.
<p>Be sure to refer to the options in the super classes { <at> link
FileAppender}, { <at> link org.apache.log4j.WriterAppender} and in particular the
<b>Threshold</b> option in { <at> link org.apache.log4j.AppenderSkeleton}.
</ul>
<at> deprecated Use the setter method for the option directly instead
of the generic <code>setOption</code> method.
*/
public void setOption(String key, String value)
{
throw new RuntimeException(getClass().getName() + ".setOption is NOT implemented");
}
public void activateOptions()
{
super.activateOptions();
if(datePattern != null && fileName != null)
{
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
scheduledFilename = fileName + sdf.format(now);
}
else
{
LogLog.error("Either Filename or DatePattern options are not set for [" +
name + "].");
}
}
void printPeriodicity(int type)
{
switch(type)
{
case TOP_OF_MINUTE:
LogLog.debug("Appender [" + name + "] to be rolled every minute.");
break;
case TOP_OF_HOUR:
LogLog.debug("Appender [" + name
+ "] to be rolled on top of every hour.");
break;
case HALF_DAY:
LogLog.debug("Appender [" + name
+ "] to be rolled at midday and midnight.");
break;
case TOP_OF_DAY:
LogLog.debug("Appender [" + name
+ "] to be rolled at midnight.");
break;
case TOP_OF_WEEK:
LogLog.debug("Appender [" + name
+ "] to be rolled at start of week.");
break;
case TOP_OF_MONTH:
LogLog.debug("Appender [" + name
+ "] to be rolled at start of every month.");
break;
default:
LogLog.warn("Unknown periodicity for appender [" + name + "].");
}
}
int computeCheckPeriod()
{
RollingCalendar c = new RollingCalendar();
// set sate to 1970-01-01 00:00:00 GMT
Date epoch = new Date(0);
if(datePattern != null)
{
for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++)
{
String r0 = sdf.format(epoch);
c.setType(i);
Date next = new Date(c.getNextCheckMillis(epoch));
String r1 = sdf.format(next);
//LogLog.debug("Type = "+i+", r0 = "+r0+", r1 = "+r1);
if(r0 != null && r1 != null && !r0.equals(r1))
{
return i;
}
}
}
return TOP_OF_TROUBLE; // Deliberately head for trouble...
}
/**
Rollover the current file to a new file.
*/
void rollOver() throws IOException
{
/* Compute filename, but only if datePattern is specified */
if(datePattern == null)
{
errorHandler.error("Missing DatePattern option in rollOver().");
return;
}
String datedFilename = fileName + sdf.format(now);
if(scheduledFilename.equals(datedFilename))
return;
// close current file, and rename it to datedFilename
this.closeFile();
File target = new File(scheduledFilename);
if(target.exists())
{
target.delete();
}
File file = new File(fileName);
file.renameTo(target);
LogLog.debug(fileName + " -> " + scheduledFilename);
// This will also close the file. This is OK since multiple
// close operations are safe.
// LWH: Recent change...
this.setFile(fileName);
this.activateOptions();
//--- archive the file...
this.archiveFile(target);
//--- HACK: we can't delete the file immediately, so we're spawning a thread to
// delete it five minutes later...
String targetPath = target.getAbsolutePath();
target = null;
file = null;
Thread deleteThread = new Thread(new DeleteFileLater(targetPath, 5 * 60 * 1000), "DeleteOldLogFileThread");
deleteThread.start();
scheduledFilename = datedFilename;
}
/**
* for some reason we can't delete the file immediately...
*/
private static class DeleteFileLater implements Runnable
{
private String targetFilePath;
private long timeToSleepInMillis;
public DeleteFileLater(String aTargetFilePath, long aTimeToSleepInMillis)
{
targetFilePath = aTargetFilePath;
timeToSleepInMillis = aTimeToSleepInMillis;
}
public void run()
{
try
{
Thread.sleep(timeToSleepInMillis);
File target = new File(targetFilePath+".zip");
System.out.println("/n/n*** deleting [" + targetFilePath + "]/n/n");
if(target.delete())
{
System.out.println("*** Successfully deleted [" + targetFilePath + "]");
}
else
{
System.out.println("*** Failed to delete [" + targetFilePath + "]");
}
}
catch(InterruptedException e)
{
LogLog.debug("Interrupted", e);
}
}
}
/**
* create a zip file which contains the target file, then delete the target...
* <at> param target
*/
void archiveFile(File target)
{
FileOutputStream fos = null;
ZipOutputStream zos = null;
try
{
// Init Zip file stream.
fos = new FileOutputStream(target.getAbsolutePath() + ".zip");
zos = new ZipOutputStream(fos);
// Create a file input stream and a buffered input stream.
FileInputStream fis = new FileInputStream(target.getAbsolutePath());
BufferedInputStream bis = new BufferedInputStream(fis);
// Create a Zip Entry and put it into the archive (no data yet).
ZipEntry fileEntry = new ZipEntry(target.getName());
zos.putNextEntry(fileEntry);
// Create a byte array object named data and declare byte count variable.
byte[] data = new byte[4096];
int byteCount;
// Create a loop that reads from the buffered input stream and writes
// to the zip output stream until the bis has been entirely read.
while ((byteCount = bis.read(data, 0, 4096)) > -1)
{
zos.write(data, 0, byteCount);
}
// Close Zip output Stream
zos.flush();
zos.close();
fos.close();
}
catch(IOException e)
{
LogLog.error(e.getMessage(), e);
}
}
/**
This method differentiates DailyRollingFileAppender from its
super class.
*/
protected void subAppend(LoggingEvent event)
{
long n = System.currentTimeMillis();
if(n >= nextCheck)
{
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try
{
rollOver();
}
catch(IOException ioe)
{
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
}
/**
RollingCalendar is a helper class to
DailyRollingFileAppender. Using this class, it is easy to compute
and access the next Millis().
It subclasses the standard { <at> link GregorianCalendar}-object, to
allow access to the protected function getTimeInMillis(), which it
then exports.
<at> author <a HREF="mailto:eirik.lygre <at> evita.no">Eirik Lygre</a> */
class RollingCalendar extends GregorianCalendar
{
int type = ArchivedDailyRollingFileAppender.TOP_OF_TROUBLE;
void setType(int type)
{
this.type = type;
}
public long getNextCheckMillis(Date now)
{
return getNextCheckDate(now).getTime();
}
public Date getNextCheckDate(Date now)
{
this.setTime(now);
switch(type)
{
case ArchivedDailyRollingFileAppender.TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case ArchivedDailyRollingFileAppender.TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case ArchivedDailyRollingFileAppender.HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if(hour < 12)
{
this.set(Calendar.HOUR_OF_DAY, 12);
}
else
{
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case ArchivedDailyRollingFileAppender.TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case ArchivedDailyRollingFileAppender.TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case ArchivedDailyRollingFileAppender.TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}
}