修改DailyRollingFileAppender类及其父类源码,解决以日期作为日志文件名时,当天的文件没有日期后缀

时间:2022-06-17 19:55:53

题记------学习别人的精髓,并加以总结,消化吸收,这就是提高!!! 

   DailyRollingFileAppender生成的文件是不带时间戳的,必须在某个时间点后,才对原来文件加上时间戳进行重命名,这样就有很大的问题,当天的日志,没有时间戳,而且如果在log4j.properties配置文件路径采用log4j.appender.dailyFile.File=E:/logs/log_或者log4j.appender.dailyFile.File=${webapp.root}/WEB-INF/logs/log_这种命名方式的,那么恭喜你,你生成的日志文件连后缀名都没有,想打开还得自己加后缀名,比如.log,.xml什么的总之很不方便。在此处说句题外话,就是解释下什么是${webapp.root},这个说简单点就是你项目运行环境的绝对路径,一般在web.xml中如果我们不配置webAppRootKey默认的缺省值就是${webapp.root},不过本人还是建议大家配置一下webAppRootKey,这样在同一服务器下运行多个项目就没冲突了。

  log4j真的是一款很强大的日志开源框架,免费且好用,当然也会略有瑕疵,如果项目允许,我建议小伙伴们还是采用logback框架吧,这个框架不仅效率高,而且还规避了本文谈及的一系列问题,更关键的是如果你会用log4j那么学会使用logback简直是小kiss,废话不多说,这次主要是重新了log4j的两个类,FileAppender及其子类DailyRollingFileAppender,由于篇幅太多我就不一一赘述代码改动了,同志们如果想知道改了哪些,可以采用代码比对工具Beyond Compare 4,下载地址http://download.****.net/download/gongxun344/9982938,附apache-log4j-1.2.17源码地址http://download.****.net/download/gongxun344/9982916。话不多说,上本人修改后的源码:

 1、修改FileAppender类 

  1 // Decompiled by DJ v3.12.12.100 Copyright 2015 Atanas Neshkov  Date: 2017-09-16 21:34:52
  2 // Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
  3 // Decompiler options: packimports(3) 
  4 // Source File Name:   FileAppender.java
  5 
  6 package com.gongli.log;
  7 
  8 import java.io.*;
  9 import java.util.Date;
 10 import java.text.SimpleDateFormat;
 11 
 12 import org.apache.log4j.Layout;
 13 import com.gongli.log.WriterAppender;
 14 import org.apache.log4j.helpers.LogLog;
 15 import org.apache.log4j.helpers.QuietWriter;
 16 
 17 // Referenced classes of package org.apache.log4j:
 18 //            WriterAppender, Layout
 19 
 20 public class FileAppender extends WriterAppender
 21 {
 22     private String datePattern = "yyyy-MM-dd";
 23 
 24     public FileAppender()
 25     {
 26         fileAppend = true;
 27         fileName = null;
 28         bufferedIO = false;
 29         bufferSize = 8192;
 30     }
 31 
 32     public FileAppender(Layout layout, String filename, boolean append, boolean bufferedIO, int bufferSize)
 33         throws IOException
 34     {
 35         fileAppend = true;
 36         fileName = null;
 37         this.bufferedIO = false;
 38         this.bufferSize = 8192;
 39         this.layout = layout;
 40         setFile(filename, append, bufferedIO, bufferSize);
 41     }
 42 
 43     public FileAppender(Layout layout, String filename, boolean append)
 44         throws IOException
 45     {
 46         fileAppend = true;
 47         fileName = null;
 48         bufferedIO = false;
 49         bufferSize = 8192;
 50         this.layout = layout;
 51         setFile(filename, append, false, bufferSize);
 52     }
 53 
 54     public FileAppender(Layout layout, String filename)
 55         throws IOException
 56     {
 57         this(layout, filename, true);
 58     }
 59 
 60     public void setFile(String file)
 61     {
 62         String val = file.trim();
 63         fileName = val;
 64     }
 65 
 66     public boolean getAppend()
 67     {
 68         return fileAppend;
 69     }
 70 
 71     public String getFile()
 72     {
 73         return fileName;
 74     }
 75 
 76     public void activateOptions()
 77     {
 78         SimpleDateFormat sdf = new SimpleDateFormat(datePattern);    
 79         Date now =  new Date();
 80         now.setTime(System.currentTimeMillis());
 81         //System.out.println(fileName.substring(fileName.lastIndexOf("_")+1,fileName.length())+"-+"); 
 82         fileName=fileName+sdf.format(now)+".log";
 83         //System.out.println(fileName+"-+");
 84         if(fileName != null)
 85         {
 86             try
 87             {
 88                 setFile(fileName, fileAppend, bufferedIO, bufferSize);
 89             }
 90             catch(IOException e)
 91             {
 92                 errorHandler.error("setFile(" + fileName + "," + fileAppend + ") call failed.", e, 4);
 93             }
 94         } else
 95         {
 96             LogLog.warn("File option not set for appender [" + name + "].");
 97             LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
 98         }
 99     }
100 
101     protected void closeFile()
102     {
103         if(qw != null)
104             try
105             {
106                 qw.close();
107             }
108             catch(IOException e)
109             {
110                 if(e instanceof InterruptedIOException)
111                     Thread.currentThread().interrupt();
112                 LogLog.error("Could not close " + qw, e);
113             }
114     }
115 
116     public boolean getBufferedIO()
117     {
118         return bufferedIO;
119     }
120 
121     public int getBufferSize()
122     {
123         return bufferSize;
124     }
125 
126     public void setAppend(boolean flag)
127     {
128         fileAppend = flag;
129     }
130 
131     public void setBufferedIO(boolean bufferedIO)
132     {
133         this.bufferedIO = bufferedIO;
134         if(bufferedIO)
135             immediateFlush = false;
136     }
137 
138     public void setBufferSize(int bufferSize)
139     {
140         this.bufferSize = bufferSize;
141     }
142 
143     public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
144         throws IOException
145     {
146         System.out.println("--==--"+fileName);
147         LogLog.debug("setFile called: " + fileName + ", " + append);
148         if(bufferedIO)
149             setImmediateFlush(false);
150         reset();
151         FileOutputStream ostream = null;
152         try
153         {
154             ostream = new FileOutputStream(fileName, append);
155         }
156         catch(FileNotFoundException ex)
157         {
158             String parentName = (new File(fileName)).getParent();
159             if(parentName != null)
160             {
161                 File parentDir = new File(parentName);
162                 if(!parentDir.exists() && parentDir.mkdirs())
163                     ostream = new FileOutputStream(fileName, append);
164                 else
165                     throw ex;
166             } else
167             {
168                 throw ex;
169             }
170         }
171         Writer fw = createWriter(ostream);
172         if(bufferedIO)
173             fw = new BufferedWriter(fw, bufferSize);
174         setQWForFiles(fw);
175         this.fileName = fileName;
176         fileAppend = append;
177         this.bufferedIO = bufferedIO;
178         this.bufferSize = bufferSize;
179         writeHeader();
180         LogLog.debug("setFile ended");
181     }
182 
183     protected void setQWForFiles(Writer writer)
184     {
185         qw = new QuietWriter(writer, errorHandler);
186     }
187 
188     protected void reset()
189     {
190         closeFile();
191         fileName = null;
192         super.reset();
193     }
194 
195     protected boolean fileAppend;
196     protected String fileName;
197     protected boolean bufferedIO;
198     protected int bufferSize;
199 }

 2、修改DailyRollingFileAppender类 

  1 /*
  2  * Licensed to the Apache Software Foundation (ASF) under one or more
  3  * contributor license agreements.  See the NOTICE file distributed with
  4  * this work for additional information regarding copyright ownership.
  5  * The ASF licenses this file to You under the Apache License, Version 2.0
  6  * (the "License"); you may not use this file except in compliance with
  7  * the License.  You may obtain a copy of the License at
  8  * 
  9  *      http://www.apache.org/licenses/LICENSE-2.0
 10  * 
 11  * Unless required by applicable law or agreed to in writing, software
 12  * distributed under the License is distributed on an "AS IS" BASIS,
 13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  * See the License for the specific language governing permissions and
 15  * limitations under the License.
 16  */
 17 
 18 
 19 
 20 package com.gongli.log;
 21 
 22 import java.io.IOException;
 23 import java.io.File;
 24 import java.io.InterruptedIOException;
 25 import java.text.SimpleDateFormat;
 26 import java.util.Date;
 27 import java.util.GregorianCalendar;
 28 import java.util.Calendar;
 29 import java.util.TimeZone;
 30 import java.util.Locale;
 31 
 32 import org.apache.log4j.Layout;
 33 import org.apache.log4j.helpers.LogLog;
 34 import org.apache.log4j.spi.LoggingEvent;
 35 
 36 /**
 37    DailyRollingFileAppender extends {@link FileAppender} so that the
 38    underlying file is rolled over at a user chosen frequency.
 39    
 40    DailyRollingFileAppender has been observed to exhibit 
 41    synchronization issues and data loss.  The log4j extras
 42    companion includes alternatives which should be considered
 43    for new deployments and which are discussed in the documentation
 44    for org.apache.log4j.rolling.RollingFileAppender.
 45 
 46    <p>The rolling schedule is specified by the <b>DatePattern</b>
 47    option. This pattern should follow the {@link SimpleDateFormat}
 48    conventions. In particular, you <em>must</em> escape literal text
 49    within a pair of single quotes. A formatted version of the date
 50    pattern is used as the suffix for the rolled file name.
 51 
 52    <p>For example, if the <b>File</b> option is set to
 53    <code>/foo/bar.log</code> and the <b>DatePattern</b> set to
 54    <code>'.'yyyy-MM-dd</code>, on 2001-02-16 at midnight, the logging
 55    file <code>/foo/bar.log</code> will be copied to
 56    <code>/foo/bar.log.2001-02-16</code> and logging for 2001-02-17
 57    will continue in <code>/foo/bar.log</code> until it rolls over
 58    the next day.
 59 
 60    <p>Is is possible to specify monthly, weekly, half-daily, daily,
 61    hourly, or minutely rollover schedules.
 62 
 63    <p><table border="1" cellpadding="2">
 64    <tr>
 65    <th>DatePattern</th>
 66    <th>Rollover schedule</th>
 67    <th>Example</th>
 68 
 69    <tr>
 70    <td><code>'.'yyyy-MM</code>
 71    <td>Rollover at the beginning of each month</td>
 72 
 73    <td>At midnight of May 31st, 2002 <code>/foo/bar.log</code> will be
 74    copied to <code>/foo/bar.log.2002-05</code>. Logging for the month
 75    of June will be output to <code>/foo/bar.log</code> until it is
 76    also rolled over the next month.
 77 
 78    <tr>
 79    <td><code>'.'yyyy-ww</code>
 80 
 81    <td>Rollover at the first day of each week. The first day of the
 82    week depends on the locale.</td>
 83 
 84    <td>Assuming the first day of the week is Sunday, on Saturday
 85    midnight, June 9th 2002, the file <i>/foo/bar.log</i> will be
 86    copied to <i>/foo/bar.log.2002-23</i>.  Logging for the 24th week
 87    of 2002 will be output to <code>/foo/bar.log</code> until it is
 88    rolled over the next week.
 89 
 90    <tr>
 91    <td><code>'.'yyyy-MM-dd</code>
 92 
 93    <td>Rollover at midnight each day.</td>
 94 
 95    <td>At midnight, on March 8th, 2002, <code>/foo/bar.log</code> will
 96    be copied to <code>/foo/bar.log.2002-03-08</code>. Logging for the
 97    9th day of March will be output to <code>/foo/bar.log</code> until
 98    it is rolled over the next day.
 99 
100    <tr>
101    <td><code>'.'yyyy-MM-dd-a</code>
102 
103    <td>Rollover at midnight and midday of each day.</td>
104 
105    <td>At noon, on March 9th, 2002, <code>/foo/bar.log</code> will be
106    copied to <code>/foo/bar.log.2002-03-09-AM</code>. Logging for the
107    afternoon of the 9th will be output to <code>/foo/bar.log</code>
108    until it is rolled over at midnight.
109 
110    <tr>
111    <td><code>'.'yyyy-MM-dd-HH</code>
112 
113    <td>Rollover at the top of every hour.</td>
114 
115    <td>At approximately 11:00.000 o'clock on March 9th, 2002,
116    <code>/foo/bar.log</code> will be copied to
117    <code>/foo/bar.log.2002-03-09-10</code>. Logging for the 11th hour
118    of the 9th of March will be output to <code>/foo/bar.log</code>
119    until it is rolled over at the beginning of the next hour.
120 
121 
122    <tr>
123    <td><code>'.'yyyy-MM-dd-HH-mm</code>
124 
125    <td>Rollover at the beginning of every minute.</td>
126 
127    <td>At approximately 11:23,000, on March 9th, 2001,
128    <code>/foo/bar.log</code> will be copied to
129    <code>/foo/bar.log.2001-03-09-10-22</code>. Logging for the minute
130    of 11:23 (9th of March) will be output to
131    <code>/foo/bar.log</code> until it is rolled over the next minute.
132 
133    </table>
134 
135    <p>Do not use the colon ":" character in anywhere in the
136    <b>DatePattern</b> option. The text before the colon is interpeted
137    as the protocol specificaion of a URL which is probably not what
138    you want.
139 
140 
141    @author Eirik Lygre
142    @author Ceki G&uuml;lc&uuml;*/
143 public class DailyRollingFileAppender extends FileAppender {
144 
145 
146   // The code assumes that the following constants are in a increasing
147   // sequence.
148   static final int TOP_OF_TROUBLE=-1;
149   static final int TOP_OF_MINUTE = 0;
150   static final int TOP_OF_HOUR   = 1;
151   static final int HALF_DAY      = 2;
152   static final int TOP_OF_DAY    = 3;
153   static final int TOP_OF_WEEK   = 4;
154   static final int TOP_OF_MONTH  = 5;
155 
156 
157   /**
158      The date pattern. By default, the pattern is set to
159      "'.'yyyy-MM-dd" meaning daily rollover.
160    */
161   private String datePattern = "'.'yyyy-MM-dd";
162 
163   /**
164      The log file will be renamed to the value of the
165      scheduledFilename variable when the next interval is entered. For
166      example, if the rollover period is one hour, the log file will be
167      renamed to the value of "scheduledFilename" at the beginning of
168      the next hour. 
169 
170      The precise time when a rollover occurs depends on logging
171      activity. 
172   */
173   private String scheduledFilename;
174 
175   /**
176      The next time we estimate a rollover should occur. */
177   private long nextCheck = System.currentTimeMillis () - 1;
178 
179   Date now = new Date();
180 
181   SimpleDateFormat sdf;
182 
183   RollingCalendar rc = new RollingCalendar();
184 
185   int checkPeriod = TOP_OF_TROUBLE;
186 
187   // The gmtTimeZone is used only in computeCheckPeriod() method.
188   static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
189 
190 
191   /**
192      The default constructor does nothing. */
193   public DailyRollingFileAppender() {
194   }
195 
196   /**
197     Instantiate a <code>DailyRollingFileAppender</code> and open the
198     file designated by <code>filename</code>. The opened filename will
199     become the ouput destination for this appender.
200 
201     */
202   public DailyRollingFileAppender (Layout layout, String filename,
203                    String datePattern) throws IOException {
204     super(layout, filename, true);
205     this.datePattern = datePattern;
206     activateOptions();
207   }
208 
209   /**
210      The <b>DatePattern</b> takes a string in the same format as
211      expected by {@link SimpleDateFormat}. This options determines the
212      rollover schedule.
213    */
214   public void setDatePattern(String pattern) {
215     datePattern = pattern;
216   }
217 
218   /** Returns the value of the <b>DatePattern</b> option. */
219   public String getDatePattern() {
220     return datePattern;
221   }
222 
223   public void activateOptions() {
224     super.activateOptions();
225     if(datePattern != null && fileName != null) {
226       now.setTime(System.currentTimeMillis());
227       sdf = new SimpleDateFormat(datePattern);
228       int type = computeCheckPeriod();
229       printPeriodicity(type);
230       rc.setType(type);
231       File file = new File(fileName);
232       //System.out.println(fileName+"+++___===");
233      // if("".equals(fileName.substring(fileName.lastIndexOf("_")+1,fileName.length()))){
234           scheduledFilename = fileName+sdf.format(new Date(file.lastModified()));
235       //}else{
236          //scheduledFilename = fileName;
237       //}
238       //System.out.println(scheduledFilename+"+++___===");
239     } else {
240       LogLog.error("Either File or DatePattern options are not set for appender ["
241            +name+"].");
242     }
243   }
244 
245   void printPeriodicity(int type) {
246     switch(type) {
247     case TOP_OF_MINUTE:
248       LogLog.debug("Appender ["+name+"] to be rolled every minute.");
249       break;
250     case TOP_OF_HOUR:
251       LogLog.debug("Appender ["+name
252            +"] to be rolled on top of every hour.");
253       break;
254     case HALF_DAY:
255       LogLog.debug("Appender ["+name
256            +"] to be rolled at midday and midnight.");
257       break;
258     case TOP_OF_DAY:
259       LogLog.debug("Appender ["+name
260            +"] to be rolled at midnight.");
261       break;
262     case TOP_OF_WEEK:
263       LogLog.debug("Appender ["+name
264            +"] to be rolled at start of week.");
265       break;
266     case TOP_OF_MONTH:
267       LogLog.debug("Appender ["+name
268            +"] to be rolled at start of every month.");
269       break;
270     default:
271       LogLog.warn("Unknown periodicity for appender ["+name+"].");
272     }
273   }
274 
275 
276   // This method computes the roll over period by looping over the
277   // periods, starting with the shortest, and stopping when the r0 is
278   // different from from r1, where r0 is the epoch formatted according
279   // the datePattern (supplied by the user) and r1 is the
280   // epoch+nextMillis(i) formatted according to datePattern. All date
281   // formatting is done in GMT and not local format because the test
282   // logic is based on comparisons relative to 1970-01-01 00:00:00
283   // GMT (the epoch).
284 
285   int computeCheckPeriod() {
286     RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
287     // set sate to 1970-01-01 00:00:00 GMT
288     Date epoch = new Date(0);
289     if(datePattern != null) {
290       for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
291     SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
292     simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
293     String r0 = simpleDateFormat.format(epoch);
294     rollingCalendar.setType(i);
295     Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
296     String r1 =  simpleDateFormat.format(next);
297     //System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
298     if(r0 != null && r1 != null && !r0.equals(r1)) {
299       return i;
300     }
301       }
302     }
303     return TOP_OF_TROUBLE; // Deliberately head for trouble...
304   }
305 
306   /**
307      Rollover the current file to a new file.这个第二天生成前一天以日期命名的方法没用了
308   */
309 //  void rollOver() throws IOException {
310 //
311 //    /* Compute filename, but only if datePattern is specified */
312 //    if (datePattern == null) {
313 //      errorHandler.error("Missing DatePattern option in rollOver().");
314 //      return;
315 //    }
316 //
317 //    String datedFilename = fileName+sdf.format(now);
318 //    // It is too early to roll over because we are still within the
319 //    // bounds of the current interval. Rollover will occur once the
320 //    // next interval is reached.
321 //    if (scheduledFilename.equals(datedFilename)) {
322 //      return;
323 //    }
324 //
325 //    // close current file, and rename it to datedFilename
326 //    this.closeFile();
327 //
328 //    File target  = new File(scheduledFilename);
329 //    if (target.exists()) {
330 //      target.delete();
331 //    }
332 //
333 //    File file = new File(fileName);
334 //    boolean result = file.renameTo(target);
335 //    if(result) {
336 //      LogLog.debug(fileName +" -> "+ scheduledFilename);
337 //    } else {
338 //      LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
339 //    }
340 //
341 //    try {
342 //      // This will also close the file. This is OK since multiple
343 //      // close operations are safe.
344 //      this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
345 //    }
346 //    catch(IOException e) {
347 //      errorHandler.error("setFile("+fileName+", true) call failed.");
348 //    }
349 //    scheduledFilename = datedFilename;
350 //  }
351 
352   /**
353    * This method differentiates DailyRollingFileAppender from its
354    * super class.
355    *
356    * <p>Before actually logging, this method will check whether it is
357    * time to do a rollover. If it is, it will schedule the next
358    * rollover time and then rollover.
359    * */
360 //  protected void subAppend(LoggingEvent event) {
361 //    long n = System.currentTimeMillis();
362 //    if (n >= nextCheck) {
363 //      now.setTime(n);
364 //      nextCheck = rc.getNextCheckMillis(now);
365 //      try {
366 //    rollOver();
367 //      }
368 //      catch(IOException ioe) {
369 //          if (ioe instanceof InterruptedIOException) {
370 //              Thread.currentThread().interrupt();
371 //          }
372 //          LogLog.error("rollOver() failed.", ioe);
373 //      }
374 //    }
375 //    super.subAppend(event);
376 //   }
377 }
378 
379 /**
380  *  RollingCalendar is a helper class to DailyRollingFileAppender.
381  *  Given a periodicity type and the current time, it computes the
382  *  start of the next interval.  
383  * */
384 class RollingCalendar extends GregorianCalendar {
385   private static final long serialVersionUID = -3560331770601814177L;
386 
387   int type = DailyRollingFileAppender.TOP_OF_TROUBLE;
388 
389   RollingCalendar() {
390     super();
391   }  
392 
393   RollingCalendar(TimeZone tz, Locale locale) {
394     super(tz, locale);
395   }  
396 
397   void setType(int type) {
398     this.type = type;
399   }
400 
401   public long getNextCheckMillis(Date now) {
402     return getNextCheckDate(now).getTime();
403   }
404 
405   public Date getNextCheckDate(Date now) {
406     this.setTime(now);
407 
408     switch(type) {
409     case DailyRollingFileAppender.TOP_OF_MINUTE:
410     this.set(Calendar.SECOND, 0);
411     this.set(Calendar.MILLISECOND, 0);
412     this.add(Calendar.MINUTE, 1);
413     break;
414     case DailyRollingFileAppender.TOP_OF_HOUR:
415     this.set(Calendar.MINUTE, 0);
416     this.set(Calendar.SECOND, 0);
417     this.set(Calendar.MILLISECOND, 0);
418     this.add(Calendar.HOUR_OF_DAY, 1);
419     break;
420     case DailyRollingFileAppender.HALF_DAY:
421     this.set(Calendar.MINUTE, 0);
422     this.set(Calendar.SECOND, 0);
423     this.set(Calendar.MILLISECOND, 0);
424     int hour = get(Calendar.HOUR_OF_DAY);
425     if(hour < 12) {
426       this.set(Calendar.HOUR_OF_DAY, 12);
427     } else {
428       this.set(Calendar.HOUR_OF_DAY, 0);
429       this.add(Calendar.DAY_OF_MONTH, 1);
430     }
431     break;
432     case DailyRollingFileAppender.TOP_OF_DAY:
433     this.set(Calendar.HOUR_OF_DAY, 0);
434     this.set(Calendar.MINUTE, 0);
435     this.set(Calendar.SECOND, 0);
436     this.set(Calendar.MILLISECOND, 0);
437     this.add(Calendar.DATE, 1);
438     break;
439     case DailyRollingFileAppender.TOP_OF_WEEK:
440     this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
441     this.set(Calendar.HOUR_OF_DAY, 0);
442     this.set(Calendar.MINUTE, 0);
443     this.set(Calendar.SECOND, 0);
444     this.set(Calendar.MILLISECOND, 0);
445     this.add(Calendar.WEEK_OF_YEAR, 1);
446     break;
447     case DailyRollingFileAppender.TOP_OF_MONTH:
448     this.set(Calendar.DATE, 1);
449     this.set(Calendar.HOUR_OF_DAY, 0);
450     this.set(Calendar.MINUTE, 0);
451     this.set(Calendar.SECOND, 0);
452     this.set(Calendar.MILLISECOND, 0);
453     this.add(Calendar.MONTH, 1);
454     break;
455     default:
456     throw new IllegalStateException("Unknown periodicity type.");
457     }
458     return getTime();
459   }
460 }

 3、log4j.properties配置

1 #the destination is file
2 log4j.appender.dailyFile=com.gongli.log.DailyRollingFileAppender
3 log4j.appender.dailyFile.File=E:/logs/log_
4 #log4j.appender.dailyFile.DatePattern=yyyy-MM-dd'.log'这个千万别配置了,我在源码里面修改过,生成日志时时间戳会自动附加上的
5 log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
6 log4j.appender.dailyFile.layout.ConversionPattern=%d{HH:mm:ss} %5p%6.6r - %m%n