As Tomcat internally uses JUL to log , you can use the system property java.util.logging.config.file to specify the file path of the properties file. For the format of this properties file , you can refer to your JRE_HOME/lib/logging.properties (which is the default configuration file used by JUL)

However, JUL does not support the daily rotation . If you don't mind , you can use its java.util.logging.FileHandler to rotate the log files based on the log 's file size instead:

# Define the FileHandler 
handlers= java.util.logging.FileHandler

# Configure the FileHandler
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 1024000
java.util.logging.FileHandler.count = 3
java.util.logging.FileHandler.formatter =  java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append=true

Then , each log file will has the limit size 1024000 bytes (1MB) , and maximum roll to 3 output log files . You can refer the Javadoc of java.util.logging.FileHandler for the details about the configuration.


You have to implemnt the File Handler if you want to support rotation on daily basis using JUL . I found a custom implemenation from this blog . I did not try it yet. You can refer it if you have any interest.

 

最近因为需要写了一个日志模块,主要功能是实现日志文件滚动(不限日志文件个数的滚动),还有就是记录日志信息。因为我功能有限,所以我没有选择log4j这样的日志扩展,而选择了jdk log扩展。

开发环境是netbean 6.8
下面是扩展JDK LOG的Handler的类 直接上代码了。

Java代码  收藏代码
  1. import java.io.BufferedOutputStream;  
  2. import java.io.File;  
  3. import java.io.FileOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.OutputStream;  
  6. import java.io.OutputStreamWriter;  
  7. import java.io.UnsupportedEncodingException;  
  8. import java.io.Writer;  
  9. import java.security.AccessController;  
  10. import java.security.PrivilegedAction;  
  11. import java.text.SimpleDateFormat;  
  12. import java.util.Date;  
  13. import java.util.logging.ErrorManager;  
  14. import java.util.logging.Handler;  
  15. import java.util.logging.Level;  
  16. import java.util.logging.LogManager;  
  17. import java.util.logging.LogRecord;  
  18. import java.util.logging.SimpleFormatter;  
  19. public class RollingFileHandler extends Handler {  
  20.   
  21.     private MeteredStream meter;  
  22.     private boolean append;  
  23.     private int limit;       // zero => no limit.  
  24.     private int count;  
  25.     private String pattern;  
  26.     private LogManager manager = LogManager.getLogManager();  
  27.     private boolean doneHeader;  
  28.     private Writer writerHandler;  
  29.     private OutputStream output;  
  30.     ErrorManager error;  
  31.     private static int index = 1;  
  32.   
  33.     @Override  
  34.     public synchronized void flush() {  
  35.         if (writerHandler != null) {  
  36.             try {  
  37.                 writerHandler.flush();  
  38.             } catch (Exception ex) {  
  39.                 // We don't want to throw an exception here, but we  
  40.                 // report the exception to any registered ErrorManager.  
  41.                 reportError(null, ex, ErrorManager.FLUSH_FAILURE);  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46.     private synchronized void flushAndClose() throws SecurityException {  
  47.         manager.checkAccess();  
  48.         if (writerHandler != null) {  
  49.             try {  
  50.                 if (!doneHeader) {  
  51.                     writerHandler.write(getFormatter().getHead(this));  
  52.                     doneHeader = true;  
  53.                 }  
  54.                 writerHandler.write(getFormatter().getTail(this));  
  55.                 writerHandler.flush();  
  56.                 writerHandler.close();  
  57.             } catch (Exception ex) {  
  58.                 // We don't want to throw an exception here, but we  
  59.                 // report the exception to any registered ErrorManager.  
  60.                 reportError(null, ex, ErrorManager.CLOSE_FAILURE);  
  61.             }  
  62.             writerHandler = null;  
  63.             output = null;  
  64.         }  
  65.     }  
  66.   
  67.     /** 
  68.      * Change the output stream. 
  69.      * <P> 
  70.      * If there is a current output stream then the <tt>Formatter</tt>'s 
  71.      * tail string is written and the stream is flushed and closed. 
  72.      * Then the output stream is replaced with the new output stream. 
  73.      * 
  74.      * @param out   New output stream.  May not be null. 
  75.      * @exception  SecurityException  if a security manager exists and if 
  76.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  77.      */  
  78.     protected synchronized void setOutputStream(OutputStream out) throws SecurityException {  
  79.         if (out == null) {  
  80.             throw new NullPointerException();  
  81.         }  
  82.         flushAndClose();  
  83.         output = out;  
  84.         doneHeader = false;  
  85.         String encoding = getEncoding();  
  86.         if (encoding == null) {  
  87.             writerHandler = new OutputStreamWriter(out);  
  88.   
  89.         } else {  
  90.             try {  
  91.                 writerHandler = new OutputStreamWriter(out, encoding);  
  92.             } catch (UnsupportedEncodingException ex) {  
  93.                 // This shouldn't happen.  The setEncoding method  
  94.                 // should have validated that the encoding is OK.  
  95.                 throw new Error("Unexpected exception " + ex);  
  96.             }  
  97.         }  
  98.     }  
  99.   
  100.     /** 
  101.      * Set (or change) the character encoding used by this <tt>Handler</tt>. 
  102.      * <p> 
  103.      * The encoding should be set before any <tt>LogRecords</tt> are written 
  104.      * to the <tt>Handler</tt>. 
  105.      * 
  106.      * @param encoding  The name of a supported character encoding. 
  107.      *        May be null, to indicate the default platform encoding. 
  108.      * @exception  SecurityException  if a security manager exists and if 
  109.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  110.      * @exception  UnsupportedEncodingException if the named encoding is 
  111.      *      not supported. 
  112.      */  
  113.     public void setEncoding(String encoding)  
  114.             throws SecurityException, java.io.UnsupportedEncodingException {  
  115.         super.setEncoding(encoding);  
  116.         if (output == null) {  
  117.             return;  
  118.         }  
  119.         // Replace the current writer with a writer for the new encoding.  
  120.         flush();  
  121.         if (encoding == null) {  
  122.             writerHandler = new OutputStreamWriter(output);  
  123.         } else {  
  124.             writerHandler = new OutputStreamWriter(output, encoding);  
  125.         }  
  126.     }  
  127.   
  128.     // A metered stream is a subclass of OutputStream that  
  129.     //   (a) forwards all its output to a target stream  
  130.     //   (b) keeps track of how many bytes have been written  
  131.     private class MeteredStream extends OutputStream {  
  132.   
  133.         OutputStream out;  
  134.         int written;  
  135.         boolean doneHeader;  
  136.         Writer writer;  
  137.   
  138.         MeteredStream(OutputStream out, int written) {  
  139.             this.out = out;  
  140.             this.written = written;  
  141.         }  
  142.   
  143.         public void write(int b) throws IOException {  
  144.             out.write(b);  
  145.             written++;  
  146.         }  
  147.   
  148.         public void write(byte buff[]) throws IOException {  
  149.             out.write(buff);  
  150.             written += buff.length;  
  151.         }  
  152.   
  153.         public void write(byte buff[], int off, int len) throws IOException {  
  154.             out.write(buff, off, len);  
  155.             written += len;  
  156.         }  
  157.   
  158.         public void flush() throws IOException {  
  159.             out.flush();  
  160.         }  
  161.   
  162.         public void close() throws IOException {  
  163.             out.close();  
  164.         }  
  165.     }  
  166.   
  167.     private void open(File fname, boolean append) throws IOException {  
  168.         int len = 0;  
  169.         if (append) {  
  170.             len = (int) fname.length();  
  171.         }  
  172.         FileOutputStream fout = new FileOutputStream(fname.toString(), append);  
  173.         BufferedOutputStream bout = new BufferedOutputStream(fout);  
  174.         meter = new MeteredStream(bout, len);  
  175.         setOutputStream(meter);  
  176.   
  177.     }  
  178.   
  179.     // Private method to configure a FileHandler from LogManager  
  180.     // properties and/or default values as specified in the class  
  181.     // javadoc.  
  182.     private void configure() {  
  183.         LogManager manager = LogManager.getLogManager();  
  184.   
  185.         String cname = getClass().getName();  
  186.   
  187.         pattern = "%h/java%u.log";  
  188.         limit = 0;  
  189.         if (limit < 0) {  
  190.             limit = 0;  
  191.         }  
  192.         append = false;  
  193.         setLevel(Level.ALL);  
  194.         setFilter(null);  
  195.         setFormatter(new SimpleFormatter());  
  196.         try {  
  197.             setEncoding(null);  
  198.         } catch (Exception ex) {  
  199.             try {  
  200.                 setEncoding(null);  
  201.             } catch (Exception ex2) {  
  202.                 // doing a setEncoding with null should always work.  
  203.                 // assert false;  
  204.             }  
  205.         }  
  206.     }  
  207.   
  208.     /** 
  209.      * Construct a default <tt>FileHandler</tt>.  This will be configured 
  210.      * entirely from <tt>LogManager</tt> properties (or their default values). 
  211.      * <p> 
  212.      * @exception  IOException if there are IO problems opening the files. 
  213.      * @exception  SecurityException  if a security manager exists and if 
  214.      *             the caller does not have <tt>LoggingPermission("control"))</tt>. 
  215.      * @exception  NullPointerException if pattern property is an empty String. 
  216.      */  
  217.     public RollingFileHandler() throws IOException, SecurityException {  
  218.         manager.checkAccess();  
  219.         configure();  
  220.         openFiles();  
  221.     }  
  222.   
  223.     /** 
  224.      * Initialize a <tt>FileHandler</tt> to write to the given filename. 
  225.      * <p> 
  226.      * The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt> 
  227.      * properties (or their default values) except that the given pattern 
  228.      * argument is used as the filename pattern, the file limit is 
  229.      * set to no limit, and the file count is set to one. 
  230.      * <p> 
  231.      * There is no limit on the amount of data that may be written, 
  232.      * so use this with care. 
  233.      * 
  234.      * @param pattern  the name of the output file 
  235.      * @exception  IOException if there are IO problems opening the files. 
  236.      * @exception  SecurityException  if a security manager exists and if 
  237.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  238.      * @exception  IllegalArgumentException if pattern is an empty string 
  239.      */  
  240.     public RollingFileHandler(String pattern) throws IOException, SecurityException {  
  241.         if (pattern.length() < 1) {  
  242.             throw new IllegalArgumentException();  
  243.         }  
  244.         manager.checkAccess();  
  245.         configure();  
  246.         this.pattern = pattern;  
  247.         this.limit = 0;  
  248.         this.count = 1;  
  249.         openFiles();  
  250.     }  
  251.   
  252.     /** 
  253.      * Initialize a <tt>FileHandler</tt> to write to the given filename, 
  254.      * with optional append. 
  255.      * <p> 
  256.      * The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt> 
  257.      * properties (or their default values) except that the given pattern 
  258.      * argument is used as the filename pattern, the file limit is 
  259.      * set to no limit, the file count is set to one, and the append 
  260.      * mode is set to the given <tt>append</tt> argument. 
  261.      * <p> 
  262.      * There is no limit on the amount of data that may be written, 
  263.      * so use this with care. 
  264.      * 
  265.      * @param pattern  the name of the output file 
  266.      * @param append  specifies append mode 
  267.      * @exception  IOException if there are IO problems opening the files. 
  268.      * @exception  SecurityException  if a security manager exists and if 
  269.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  270.      * @exception  IllegalArgumentException if pattern is an empty string 
  271.      */  
  272.     public RollingFileHandler(String pattern, boolean append) throws IOException, SecurityException {  
  273.         if (pattern.length() < 1) {  
  274.             throw new IllegalArgumentException();  
  275.         }  
  276.         manager.checkAccess();  
  277.         configure();  
  278.         this.pattern = pattern;  
  279.         this.limit = 0;  
  280.         this.count = 1;  
  281.         this.append = append;  
  282.         openFiles();  
  283.     }  
  284.   
  285.     /** 
  286.      * Initialize a <tt>FileHandler</tt> to write to a set of files.  When 
  287.      * (approximately) the given limit has been written to one file, 
  288.      * another file will be opened.  The output will cycle through a set 
  289.      * of count files. 
  290.      * <p> 
  291.      * The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt> 
  292.      * properties (or their default values) except that the given pattern 
  293.      * argument is used as the filename pattern, the file limit is 
  294.      * set to the limit argument, and the file count is set to the 
  295.      * given count argument. 
  296.      * <p> 
  297.      * The count must be at least 1. 
  298.      * 
  299.      * @param pattern  the pattern for naming the output file 
  300.      * @param limit  the maximum number of bytes to write to any one file 
  301.      * @param count  the number of files to use 
  302.      * @exception  IOException if there are IO problems opening the files. 
  303.      * @exception  SecurityException  if a security manager exists and if 
  304.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  305.      * @exception IllegalArgumentException if limit < 0, or count < 1. 
  306.      * @exception  IllegalArgumentException if pattern is an empty string 
  307.      */  
  308.     public RollingFileHandler(String pattern, int limit, int count)  
  309.             throws IOException, SecurityException {  
  310.         if (limit < 0 || count < 1 || pattern.length() < 1) {  
  311.             throw new IllegalArgumentException();  
  312.         }  
  313.         manager.checkAccess();  
  314.         configure();  
  315.         this.pattern = pattern;  
  316.         this.limit = limit;  
  317.         this.count = count;  
  318.         openFiles();  
  319.     }  
  320.   
  321.     /** 
  322.      * Initialize a <tt>FileHandler</tt> to write to a set of files 
  323.      * with optional append.  When (approximately) the given limit has 
  324.      * been written to one file, another file will be opened.  The 
  325.      * output will cycle through a set of count files. 
  326.      * <p> 
  327.      * The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt> 
  328.      * properties (or their default values) except that the given pattern 
  329.      * argument is used as the filename pattern, the file limit is 
  330.      * set to the limit argument, and the file count is set to the 
  331.      * given count argument, and the append mode is set to the given 
  332.      * <tt>append</tt> argument. 
  333.      * <p> 
  334.      * The count must be at least 1. 
  335.      * 
  336.      * @param pattern  the pattern for naming the output file 
  337.      * @param limit  the maximum number of bytes to write to any one file 
  338.      * @param count  the number of files to use 
  339.      * @param append  specifies append mode 
  340.      * @exception  IOException if there are IO problems opening the files. 
  341.      * @exception  SecurityException  if a security manager exists and if 
  342.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  343.      * @exception IllegalArgumentException if limit < 0, or count < 1. 
  344.      * @exception  IllegalArgumentException if pattern is an empty string 
  345.      * 
  346.      */  
  347.     public RollingFileHandler(String pattern, int limit, int count, boolean append)  
  348.             throws IOException, SecurityException {  
  349.         if (limit < 0 || pattern.length() < 1) {  
  350.             throw new IllegalArgumentException();  
  351.         }  
  352.         manager.checkAccess();  
  353.         configure();  
  354.         this.pattern = pattern;  
  355.         this.limit = limit;  
  356.         this.count = count;  
  357.         this.append = append;  
  358.         openFiles();  
  359.     }  
  360.   
  361.     // Private method to open the set of output files, based on the  
  362.     // configured instance variables.  
  363.     private void openFiles() throws IOException {  
  364.   
  365.         if (append) {  
  366.             File f = new File(pattern);  
  367.             try {  
  368.                 open(f, true);  
  369.             } catch (IOException ex) {  
  370.                 reportError(null, ex, ErrorManager.OPEN_FAILURE);  
  371.             }  
  372.         } else {  
  373.             rotate();  
  374.         }  
  375.   
  376.     }  
  377.   
  378.     // Rotate the set of output files  
  379.     private synchronized void rotate() {  
  380.         File target;  
  381.         File file;  
  382.         Level oldLevel = getLevel();  
  383.         setLevel(Level.OFF);  
  384.         close();  
  385.         Date date = new Date();  
  386.         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss");  
  387.         String dateFormat = format.format(date);  
  388.         boolean renameSucceeded = true;  
  389.         if (count > 0) {  
  390.             file = new File(pattern + '_' + dateFormat + '.' + count);  
  391.             if (file.exists()) {  
  392.                 index++;  
  393.                 target = new File(pattern + '_' + dateFormat + "." + index);  
  394.                 renameSucceeded = file.renameTo(target);  
  395.             }  
  396.             for (int i = count - 1; i >= 1 && renameSucceeded; i--) {  
  397.                 file = new File(pattern + "." + i);  
  398.                 if (file.exists()) {  
  399.                     target = new File(pattern + '.' + (i + 1));  
  400.                     renameSucceeded = file.renameTo(target);  
  401.                 }  
  402.             }  
  403.   
  404.             if (renameSucceeded) {  
  405.                 // Rename fileName to fileName.1  
  406.                 index = 1;  
  407.                 target = new File(pattern + '_' + dateFormat + "." + 1);  
  408.                 file = new File(pattern);  
  409.                 renameSucceeded = file.renameTo(target);  
  410.                 //  
  411.                 //   if file rename failed, reopen file with append = true  
  412.                 //  
  413.                 if (!renameSucceeded) {  
  414.                     File f = new File(pattern);  
  415.                     append = true;  
  416.                     try {  
  417.                         open(f, append);  
  418.                     } catch (IOException ex) {  
  419.                         reportError(null, ex, ErrorManager.OPEN_FAILURE);  
  420.                     }  
  421.                 }  
  422.             }  
  423.         }  
  424.         if (renameSucceeded) {  
  425.             File f = new File(pattern);  
  426.             try {  
  427.                 open(f, false);  
  428.             } catch (IOException ex) {  
  429.                 reportError(null, ex, ErrorManager.OPEN_FAILURE);  
  430.             }  
  431.         }  
  432.         setLevel(oldLevel);  
  433.     }  
  434.   
  435.     /** 
  436.      * Format and publish a <tt>LogRecord</tt>. 
  437.      * 
  438.      * @param  record  description of the log event. A null record is 
  439.      *                 silently ignored and is not published 
  440.      */  
  441.     public synchronized void publish(LogRecord record) {  
  442.   
  443.         if (!isLoggable(record)) {  
  444.             return;  
  445.         }  
  446.         String msg;  
  447.         try {  
  448.             msg = getFormatter().format(record);  
  449.         } catch (Exception ex) {  
  450.             // We don't want to throw an exception here, but we  
  451.             // report the exception to any registered ErrorManager.  
  452.             reportError(null, ex, ErrorManager.FORMAT_FAILURE);  
  453.             return;  
  454.         }  
  455.   
  456.         try {  
  457.             if (!doneHeader) {  
  458.                 writerHandler.write(getFormatter().getHead(this));  
  459.                 doneHeader = true;  
  460.             }  
  461.             if (writerHandler == null) {  
  462.                 File f = new File(pattern);  
  463.                 open(f, append);  
  464.             }  
  465.             writerHandler.write(msg);  
  466.   
  467.         } catch (Exception ex) {  
  468.             // We don't want to throw an exception here, but we  
  469.             // report the exception to any registered ErrorManager.  
  470.             reportError(null, ex, ErrorManager.WRITE_FAILURE);  
  471.         }  
  472.         flush();  
  473.         if (limit > 0 && meter.written >= limit) {  
  474.             // We performed access checks in the "init" method to make sure  
  475.             // we are only initialized from trusted code.  So we assume  
  476.             // it is OK to write the target files, even if we are  
  477.             // currently being called from untrusted code.  
  478.             // So it is safe to raise privilege here.  
  479.             AccessController.doPrivileged(new PrivilegedAction() {  
  480.   
  481.                 public Object run() {  
  482.                     rotate();  
  483.                     return null;  
  484.                 }  
  485.             });  
  486.         }  
  487.     }  
  488.   
  489.     /** 
  490.      * Close all the files. 
  491.      * 
  492.      * @exception  SecurityException  if a security manager exists and if 
  493.      *             the caller does not have <tt>LoggingPermission("control")</tt>. 
  494.      */  
  495.     public synchronized void close() throws SecurityException {  
  496.         flushAndClose();  
  497.     }  
  498.   
  499.     private static class InitializationErrorManager extends ErrorManager {  
  500.   
  501.         Exception lastException;  
  502.   
  503.         public void error(String msg, Exception ex, int code) {  
  504.             lastException = ex;  
  505.         }  
  506.     }  
  507.   
  508.     // Private native method to check if we are in a set UID program.  
  509.     private static native boolean isSetUID();  
  510. }  

 然后是Util类的代码

Java代码  收藏代码
  1. import java.io.IOException;  
  2. import java.util.logging.Handler;  
  3. import java.util.logging.Level;  
  4. import java.util.logging.Logger;  
  5. public class Utils {  
  6.   
  7.     private static Logger log;  
  8.   
  9.     /** 
  10.      * @serial Class that issued logging call 
  11.      */  
  12.     protected static String sourceClassName;  
  13.     /** 
  14.      * @serial Method that issued logging call 
  15.      */  
  16.     protected static String sourceMethodName;  
  17.     private transient boolean needToInferCaller;  
  18.   
  19.     static {  
  20.         inferCaller();  
  21.         Handler handler = configure("log.log",1000,1,true);  
  22.         try {  
  23.             log = Logger.getLogger(sourceClassName);  
  24.   
  25.             log.addHandler(handler);  
  26.   
  27.             log.setLevel(Level.ALL);  
  28.   
  29.         } catch (Exception ex) {  
  30.             System.out.println("can't init the Logger, caused by: " + ex);  
  31.         }  
  32.     }  
  33.   
  34.     public static void debug(String info) {  
  35.         inferCaller();  
  36.   
  37.         log.logp(Level.SEVERE, sourceClassName, sourceMethodName, info);  
  38.   
  39.     }  
  40.   
  41.     public static void debug(String info,Throwable thrown){  
  42.         inferCaller();  
  43.   
  44.         log.logp(Level.SEVERE, sourceClassName, sourceMethodName, info,thrown);  
  45.     }  
  46.   
  47.     public static void info(String info) {  
  48.         inferCaller();  
  49.         log.logp(Level.INFO, sourceClassName, sourceMethodName, info);  
  50.           
  51.     }  
  52.   
  53.      public static void info(String info,Throwable thrown){  
  54.         inferCaller();  
  55.   
  56.         log.logp(Level.INFO, sourceClassName, sourceMethodName, info,thrown);  
  57.     }  
  58.   
  59.     public static void warning(String info) {  
  60.         inferCaller();  
  61.         log.logp(Level.WARNING, sourceClassName, sourceMethodName, info);  
  62.     }  
  63.   
  64.      public static void warning(String info,Throwable thrown){  
  65.         inferCaller();  
  66.   
  67.         log.logp(Level.WARNING, sourceClassName, sourceMethodName, info,thrown);  
  68.     }  
  69.   
  70.     public static void error(String info) {  
  71.         inferCaller();  
  72.         log.logp(Level.SEVERE, sourceClassName, sourceMethodName, info);  
  73.     }  
  74.   
  75.      public static void error(String info,Throwable thrown){  
  76.         inferCaller();  
  77.   
  78.         log.logp(Level.SEVERE, sourceClassName, sourceMethodName, info,thrown);  
  79.     }  
  80. private static void init() {  
  81.         inferCaller();  
  82.   
  83.         log = Logger.getLogger(Utils.sourceClassName);  
  84.     }  
  85.   
  86.     // Private method to infer the caller's class and method names  
  87.     private static void inferCaller() {  
  88. //  needToInferCaller = false;  
  89.         // Get the stack trace.  
  90.         StackTraceElement stack[] = (new Throwable()).getStackTrace();  
  91.         // First, search back to a method in the Logger class.  
  92.         int ix = 0;  
  93.         while (ix < stack.length) {  
  94.             StackTraceElement frame = stack[ix];  
  95.             String cname = frame.getClassName();  
  96.             if (cname.equals("com.lhsm.logger.Utils")) {  
  97.                 stack[ix] = stack[2];  
  98.                 break;  
  99.             }  
  100.             ix++;  
  101.         }  
  102.         // Now search for the first frame before the "Logger" class.  
  103.         while (ix < stack.length) {  
  104.             StackTraceElement frame = stack[ix];  
  105.             String cname = frame.getClassName();  
  106.             if (!cname.equals("com.lhsm.logger.Utils")) {  
  107.                 // We've found the relevant frame.  
  108.                 sourceClassName = cname;  
  109.                 sourceMethodName = frame.getMethodName();  
  110.   
  111.                 return;  
  112.             }  
  113.             ix++;  
  114.         }  
  115.         // We haven't found a suitable frame, so just punt.  This is  
  116.         // OK as we are only committed to making a "best effort" here.  
  117.     }  
  118.   
  119.     /** 
  120.      * 
  121.      * @param pattern 为生成的输出文件名称指定一个模式。 
  122.      * @param limit   指定要写入到任意文件的近似最大量(以字节为单位)。如果该数为 0,则没有限制(默认为无限制)。.不能小于0 
  123.      * @param count   (1为不限滚动),这里指定个数滚动文件没有实现 
  124.      * @param append  指定是否应该将 FileHandler 追加到任何现有文件上。 
  125.      * @return 
  126.      */  
  127.     public static Handler configure(String pattern,int limit,int count,boolean append) {  
  128.         Handler handler = null;  
  129.         if (limit < 0 ||  pattern.length() < 1) {  
  130.         throw new IllegalArgumentException();  
  131.     }  
  132.           
  133.         try {  
  134.             handler = new RollingFileHandler(pattern, limit, count, append);  
  135.         } catch (IOException ex) {  
  136.             Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex);  
  137.         } catch (SecurityException ex) {  
  138.             Logger.getLogger(Utils.class.getName()).log(Level.SEVERE, null, ex);  
  139.         }  
  140.         return handler;  
  141.     }  
  142.   
  143.     /** 
  144.      * @return the sourceClassName 
  145.      */  
  146.     public String getSourceClassName() {  
  147.         if (needToInferCaller) {  
  148.             inferCaller();  
  149.         }  
  150.         return sourceClassName;  
  151.     }  
  152.   
  153.     /** 
  154.      * @return the sourceMethodName 
  155.      */  
  156.     public String getSourceMethodName() {  
  157.         if (needToInferCaller) {  
  158.             inferCaller();  
  159.         }  
  160.         return sourceMethodName;  
  161.     }  
  162. }  

 

下面是一个测试Foo类

Java代码  收藏代码
  1. public class Foo {  
  2.     private int i =0;  
  3.     public Foo(int i) {  
  4.         this.i = i;  
  5.     }  
  6.   
  7.     public void doIt() {  
  8.   
  9.         Utils.debug("Debug..."+i);  
  10.         Utils.info("Info..."+i);  
  11.         Utils.warning("Warn..."+i);  
  12.         Utils.error("Error..."+i);  
  13.     }  
  14.   
  15.       
  16.   
  17.     public void doFooIt() {  
  18.         Utils.debug("Debug..."+i);  
  19.         Utils.info("Info..."+i);  
  20.         Utils.warning("Warn..."+i);  
  21.         Utils.error("Error..."+i);  
  22.     }  
  23. }  

 

Java代码  收藏代码
    1. public class LogTest {  
    2.   
    3.     public static void main(String[] args) {  
    4.        for (int i = 0; i < 10000; i++) {  
    5.         Foo foo = new Foo(i);  
    6.   
    7.         foo.doIt();  
    8.         foo.doFooIt();  
    9.         }  
    10.   
    11.     }  
    12. }