配置自己的FileFileAppender

本文档介绍了一个自定义的日志文件Appender——MyAppender,它是基于Apache Log4j的FileAppender扩展。MyAppender根据预设的文件名前缀、后缀和路径生成日志文件,并支持文件大小限制和日期翻转功能,确保日志文件不过大且按日期组织。此外,它还包含检查日期变化和文件大小的机制,以决定何时滚动到新的日志文件。

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

package study.log;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.spi.LoggingEvent;

public class MyAppender  extends FileAppender
{

    /** 文件名的模式,只能由字母、数字、下划线组成,且长度不超过32 */
    private static final String FILE_NAME_PATTERN = "^\\w{1,32}$";
    
    /** 日志文件默认的前缀名称*/
    private String fileNamePrefix = "Rum";
    
    /** 日志文件默认的后缀名称*/
    private String fileNameSuffix = "log";
    
    /** 文件大小*/
    private long maxFileSize;
    
    /** 日志文件存放的路径*/
    private String logPath = "D://log/run/";
    
    /** 
     * 文件翻转。先关闭当前日志文件,再新建下个日志文件。
     * 生成文件名,然后调用this.setFile方法翻转文件。
     */
    public void rollOver()
    {
        fileName = createFileName();
        try
        {
            this.setFile(fileName, false, bufferedIO, bufferSize);
        }
        catch (IOException e)
        {
        }
    }
    
    /**
     * 产生文件名。
     * 根据配置的文件名前缀、后缀加上路径,规则如下:
     * 路径 + 文件名前缀 + "_" + 时间(yyyyMMddHHmmss)+ "." + 文件名后缀
     * @return
     * @author w37000
     * @date 2006-2-18 16:55:02
     */
    public String createFileName()
    {
        //如果日志目录不存在,创建目录
        File dir = new File(logPath);
        if (!dir.exists())
        {
            boolean isMkdirOk = dir.mkdirs();
            if (!isMkdirOk)
            {
            }
        }
        
        //获得系统当前的时间
        SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHHmmss");
        
        String time = null;
    	if ("utc".equalsIgnoreCase(System.getProperty("umlog")))
        {
    		long offtime = TimeZone.getDefault().getOffset(new Date().getTime());
    		time = date.format(new Date(System.currentTimeMillis()-offtime));
        }
        else
        {
        	time = date.format(new Date());
        }
    	
        //String time = date.format(new Date());
        
        //构造日志文件名称
        StringBuffer sb = new StringBuffer();
        sb.append(logPath).append(fileNamePrefix).append('_');
        sb.append(time).append('.').append(fileNameSuffix);
        
        return sb.toString();
    }
    
    /**
     *  覆盖父类的activateOptions方法。log4j在初使化完毕(通过反射加载各配置属性)之后会
     *  调用activateOptions方法,该方法将新建以fileName命名的文件,MyAppender必须覆盖
     *  这个方法,先根据配置的文件名前缀、后缀等生成文件名,在调用super.activateOptions()。
     * @see org.apache.log4j.FileAppender#activateOptions()
     */
    public void activateOptions()
    {
        fileName = createFileName();
        super.activateOptions();
    }
    
    /**
     * 判断当前日期是否改变。
     * 比较文件名中的日期是否和系统日期为同一天,若不是则新建文件。此功能可能在acc日志
     * 上有用,保证一个acc日志中不包含两天的内容,OMC根据文件名称把acc日志入库到每一天的
     * 表中,供portal按日期统计。
     * @param fileName   文件名
     * @return
     * @author w37000
     * @date 2006-2-18 17:25:20
     */
    public boolean isDateChanged(String fileName)
    {
        //文件名为路径名加文件名../log/run/Rum_20040820170818.log
        //1、找到文件后缀名分隔符"."
        int index = fileName.lastIndexOf(".");
        if(1 == 2)
        {
            //2、"."号前面第14~6位为日期(20040820)
            String dateOfFileName = fileName.substring(index - 14, index - 4);
            SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHH");
            String sysDate = date.format(new Date());
            return !dateOfFileName.equals(sysDate);
        }
        else
        {
            //2、"."号前面第14~6位为日期(20040820)
            String dateOfFileName = fileName.substring(index - 14, index - 6);
            SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
            String sysDate = date.format(new Date());
            return !dateOfFileName.equals(sysDate);
        }
    }
    
    /**
     * 覆盖父类的方法,写日志之前先判断是否已达到翻转条件,有两个翻转条件:
     * 1、日期已改变
     * 2、文件大小加上将要写的这条记录的大小大于maxFileSize
     * 二者满足其一即关闭当前文件,写到新文件中
     * @see org.apache.log4j.WriterAppender#subAppend(org.apache.log4j.spi.LoggingEvent)
     */
    protected void subAppend(LoggingEvent event)
    {
        if (isDateChanged(fileName)
            || ((CountingQuietWriter)qw).getCount() + event.getRenderedMessage().length() >= maxFileSize)
        {
            this.rollOver();
        }
        super.subAppend(event);
    }
    
    /**
     * 翻转文件。如果文件是以append的方式打开,则CountingQuietWriter要加上文件的大小
     * @param fileName   文件名
     * @param append     是否以增加的形式打开文件
     * @param bufferedIO 是否缓存输出
     * @param bufferSize 缓存大小
     */
    public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
        throws IOException
    {
        super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
        if (append)
        {
            File f = new File(fileName);
            ((CountingQuietWriter)qw).setCount(f.length());
        }
    }
    
    /**
     * 重载父类方法,把writer设置为可以记录当前写的字节数的CountingQuietWriter。windows
     * 操作系统并非实时更新文件的大小属性,因此在判断文件大小的翻转条件时不能调用File.length方法
     * 来判断当前文件大小是否大于maxFileSize,在writer中用一个变量来记录当前文件中已写入的文件大小,
     * 因此在设置writer时需把writer包装为可记录当前写字节数的CountingQuietWriter。
     * @param writer The writer to set.
     */
    protected void setQWForFiles(Writer writer)
    {
        this.qw = new CountingQuietWriter(writer, errorHandler);
    }
    
    /**
     * @return Returns the fileNamePrefix.
     */
    public String getFileNamePrefix()
    {
        return fileNamePrefix;
    }
    
    /**
     * 只允许字母、数字、下划线,且长度不能超过32,否则采用默认值Rum
     * @param fileNamePrefix The fileNamePrefix to set.
     */
    public void setFileNamePrefix(String fileNamePrefix)
    {
        Pattern p = Pattern.compile(FILE_NAME_PATTERN);
        if (p.matcher(fileNamePrefix).matches())
        {
            this.fileNamePrefix = fileNamePrefix;
        }
    }
    
    /**
     * @return Returns the fileNameSuffix.
     */
    public String getFileNameSuffix()
    {
        return fileNameSuffix;
    }
    
    /**
     * 只允许字母、数字、下划线,且长度不能超过32,否则采用默认值log
     * @param fileNameSuffix The fileNameSuffix to set.
     */
    public void setFileNameSuffix(String fileNameSuffix)
    {
        Pattern p = Pattern.compile(FILE_NAME_PATTERN);
        if (p.matcher(fileNameSuffix).matches())
        {
            this.fileNameSuffix = fileNameSuffix;
        }
    }
    
    /**
     * @return Returns the maxFileSize.
     */
    public long getMaxFileSize()
    {
        return maxFileSize;
    }
    
    /**
     * 配置文件中的单位是KB,要转换为Byte
     * @param maxFileSize The maxFileSize to set.
     */
    public void setMaxFileSize(long maxFileSize)
    {
        this.maxFileSize = maxFileSize * 1024;
    }
    
    /**
     * @return Returns the logPath.
     */
    public String getLogPath()
    {
        return logPath;
    }
    
    /**
     * @param logPath The logPath to set.
     */
    public void setLogPath(String logPath)
    {
        this.logPath = logPath;
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值