Регулярно настраивайте время интервала и печати журнала
После получения запроса журнал регулярно печатается через log4j. Описание требования заключается в следующем: журнал должен быть в состоянии регулярно напечатать, а интервал времени может быть сопоставлен. Говоря о времени, прежде всего, я думаю о классе DailyrollingFileAppender. Различные времена. Согласно DatePattern, вы можете обратиться к классу SimpleDateFormat. Некоторые общие настройки времени заключаются в следующем:
Благодаря наблюдению, я обнаружил, что нет формата даты, аналогичного N минут, поэтому я написал пользовательский класс на основе класса DailyrollingFileAppender. Процесс заключается в следующем:
1) Скопируйте исходный код класса DailyrollingFileAppender и переименовать его MinuterollingAppender. Чтобы настроить его в log4j.xml, добавьте время интервала элемента конфигурации и добавьте методы набора и получения;
Private Int Intertertame = 10;
2) Поскольку класс DailyrollingFileAppender использует класс RollingCalendar для расчета следующего интервального времени и необходимо пройти время интервала параметра, класс RollingCalendar модифицируется как внутренний класс; Поскольку его метод состоит в том, чтобы вычислить время следующего пролонного действия на основе DatePattern, в настоящее время другой режим времени не требуется, метод модификации выглядит следующим образом:
публичная дата getNextCheckDate (дата сейчас) {this.SetTime (сейчас); this.set (calendar.second, 0); this.set (calendar.millisecond, 0); this.add (календарь.minute, время интервала); вернуть getTime (); }3) Когда режим времени сопоставлен в соответствии с протоколом, режим времени должен быть отключен. Измените его на статический финал и удалите параметры DatePattern в методе GET, SET и конструкторе MinuterOllingAppender в ответе.
частная статическая строка datepattern = "'.'yyyy-mm-dd-hh-mm'.log'";
Аналогичным образом, ComputeCheckPeriod (), который обслуживает несколько DatePatterns, также может быть удален; Преобразование было завершено, а категория готового продукта заключается в следующем:
пакет net.csdn.blog; Импорт java.io.file; импортировать java.io.ioexception; Импорт java.io.ErentertedioException; импортировать java.text.simpledateformat; импортировать java.util.calendar; импортировать java.util.date; импортировать java.util.gregoriancalendar; Импорт org.apache.log4j.fileAppender; Импорт org.apache.log4j.layout; Импорт org.apache.log4j.helpers.loglog; Импорт org.apache.log4j.spi.loggingevent; /** * Timerable By Minate appender * * @author coder_xia * * /public Class minuterollingAppender Extends fileAppender { /** * С шаблона даты. По умолчанию шаблон установлен на «'.'yyyy-mm-dd» *, что означает ежедневный роллет. */ private static String datepattern = "'.'yyyy-mm-dd-hh-mm'.log'"; / *** Время интервала, единица: минуты*/ private int интервал времени = 10; /** * Файл журнала будет переименован в значение переменной запланированного флиленам * при введении следующего интервала. Например, если период роллера * составляет один час, файл журнала будет переименован в значение * "" Перепланированное место "в начале следующего часа. * * Точное время, когда возникает опрокидывание в зависимости от регистрации. */ private String presenLEDFILENAME; /*** В следующий раз, когда мы оценим, что должен произойти опрокидывание. */ private long nextCeck = System.currentTimeMillis () - 1; Дата сейчас = новая дата (); SimpleDateFormat SDF; RollingCalendar RC = new RollingCalendar (); /*** Конструктор по умолчанию ничего не делает. */public minuterollingAppender () {}/** * создание создания <code> minuterollingAppender </code> и откройте файл *, разработанный <code> filename </code>. Открытое имя файла станет пунктом назначения * для этого приложения. */ public minuterollingAppender (макета макета, имя строкового файла) бросает ioException {super (макет, имя файла, true); ActivateOptions (); } / ** * @return The IntervalTime * / public int getIntervaltime () {return QuardalTime; } / ** * @param интервал времени * Время интервала для установки * / public void setIntervaltime (int интервал) {this.Intervaltime = expredTime; } @Override public void ActivateOptions () {super.ActivateOptions (); if (filename! = null) {own.settime (system.currenttimemillis ()); sdf = new SimpleDateFormat (datePattern); File file = new File (имя файла); preduledFilename = имя файла + sdf.format (новая дата (file.lastmodified ())); } else {loglog .Error ("либо файл, либо параметры datePattern не установлены для Appender [" + name + "]."); }} /*** РОВЛЕНИЕ Текущий файл в новый файл. */ void rollover () бросает ioException {string datedfilename = имя файла + sdf.format (сейчас); // Пока рано перевернуться, потому что мы все еще находимся в пределах // текущего интервала. Пролочный пробел произойдет после достижения следующего интервала. if (wared offilename.equals (datedfilename)) {return; } // закрыть текущий файл и переименовать его в DatedFilEname this.closefile (); File Target = новый файл (PreseedFilename); if (target.exists ()) {target.delete (); } File file = new File (имя файла); Boolean result = file.renameto (Target); if (result) {loglog.debug (fileName + " ->" + warededFilename); } else {loglog.error ("не удалось переименовать [" + filename + "] до [" + preseedFilename + "]."); } try {// Это также закроет файл. Это нормально, так как несколько операций по закрытию безопасны. this.setfile (имя файла, true, this.bufferedio, this.buffersize); } catch (ioException e) {errorHandler.error ("setFile (" + filename + ", true) вызов вызов."); } presenuledFilename = DatedFilEname; } /*** Этот метод отличает MinuterollingAppender от его супер класса. * * <p> * До фактического регистрации этот метод проверит, пришло ли время сделать * пролонку. Если это так, это запланирует следующее время пролонга, а затем * Rollover. * */ @Override Protected void subAppend (событие loggingEvent) {long n = System.currentTimeMillis (); if (n> = nextCeck) {now.setTime (n); NextCeck = rc.getNextCheckMillis (сейчас); try {rollover (); } catch (ioException ioe) {if (ioe ancessionof urruptEdioException) {thread.currentThread (). Enterrupt (); } Loglog.Error ("rovlover () не удалось.", Ioe); }} super.subappend (event); } /*** RollingCalendar - это помощник класса для MinuterollingAppender. Учитывая тип * периодичности и текущее время, он вычисляет начало следующего * интервала. * */ Class RollingCalendar Extends gregorianCalendar {Private Static Final Long SerialVersionUID = -3560331770601814177L; RollingCalendar () {super (); } public long getNextCheckmillis (дата сейчас) {return getNextCheckDate (сейчас) .getTime (); } Общественная дата getNextCheckdate (дата сейчас) {this.setTime (сейчас); this.set (calendar.second, 0); this.set (calendar.millisecond, 0); this.add (календарь.minute, время интервала); вернуть getTime (); }}}Файл конфигурации теста выглядит следующим образом:
<? xml version = "1.0" Encoding = "utf-8"?> <! Doctype log4j: Система конфигурации "log4j.dtd"> <log4j: configuration xmlns: log4j = "http://jakarta.apache.org/log4j/"> <appender name = "myfile"> <> <param amame = "param amame =" "param ama alm =" "param ama alm =" "param ama ama ama alm = value="log4jTest.log" /> <param name="Append" value="true" /> <param name="intervalTime" value="2"/> <layout> <param name="ConversionPattern" value="%p %d (%c:%L)- %m%n" /> </layout> </appender> <root> <priority value="debug"/> <appender-ref ref = "myfile"/> </root> </log4j: конфигурация>
Что касается реализации времени, вы также можете использовать реализацию таймера, предоставленную Java, которая устраняет расчет и сравнение времени каждый раз, когда вы записываете журнал. Разница на самом деле заключается в настройке потока и вызове метода опрокидывания. Реализация следующая:
пакет net.csdn.blog; Импорт java.io.file; импортировать java.io.ioexception; импортировать java.text.simpledateformat; импортировать java.util.date; импортировать java.util.timer; импортировать java.util.timertask; Импорт org.apache.log4j.fileAppender; Импорт org.apache.log4j.layout; Импорт org.apache.log4j.helpers.loglog; Общедоступный класс TimertaskrollingAppender Extens FileAppender { /*** С шаблона даты. По умолчанию шаблон установлен на «'.'yyyy-mm-dd» *, что означает ежедневный роллет. */ private static final String datePattern = ". / *** Время интервала, единица: минуты*/ private int интервал времени = 10; SimpleDateFormat SDF = new SimpleDateFormat (datePattern); /*** Конструктор по умолчанию ничего не делает. */public timertaskrollingAppender () {}/** * создание создания <code> timertaskrollingAppender </code> и откройте файл *, разработанный <code> filename </code>. Открытое имя файла станет пунктом назначения * для этого приложения. */ public timertaskrollingAppender (макет макета, имя строкового файла) бросает ioException {super (макет, имя файла, true); ActivateOptions (); } / ** * @return The IntervalTime * / public int getIntervaltime () {return QuardalTime; } / ** * @param интервал времени * Время интервала для установки * / public void setIntervaltime (int интервал) {this.Intervaltime = expredTime; } @Override public void ActivateOptions () {super.ActivateOptions (); Таймер timer = new Timer (); timer.schedule (new logtimetask (), 1000, интервал * 60000); } class logtimertask extends timertask {@override public void run () {string datedfilename = filename + sdf.format (new date ()); закрытый файл (); File Target = новый файл (DatedFilename); if (target.exists ()) target.delete (); File file = new File (имя файла); Boolean result = file.renameto (Target); if (result) loglog.debug (filename + " ->" + datedfilename); else loglog.error («не удалось переименовать [« + файл » +»] до [" + datedfilename +"]. "); try {setFile (имя файла, true, bufferedio, buffersize); } catch (ioException e) {errorHandler.error ("setFile (" + filename + ", true) вызов вызов."); }}}}}Тем не менее, есть две проблемы с приведенной выше реализацией:
1) параллелизм
Место, где проблемы с параллелизмом могут возникнуть после вызова closeFile () в run (), метод subAppend () просто пишет журнал. В настоящее время файл закрыт, и будет сообщена следующая ошибка:
java.io.ioexception: Поток закрыт на sun.nio.cs.streamencoder.ensureopen (неизвестный источник) на sun.nio.cs.streamencoder.write (неизвестный источник) на sun.nio.cs.streamencoder.write (неизвестный источник) на Java.io.OutputStreamWriter.Write (неизвестный источник). ..................Решение относительно простое. Просто сделайте весь метод run () синхронизироваться и добавьте синхронизированное ключевое слово; Тем не менее, автор не решил ситуацию, когда журнал может быть потерян, если он действительно хочет написать ее, и скорость написания достаточно быстрая;
Использование таймера для реализации является проще, но если задачи в таймере выполняются слишком долго, они будут занимать исключительно объект таймера, делая последующие задачи невозможными в любое время. Решение также проще. Класс версии Timer Pool Pool PradeDexeCutorService используется для реализации следующего:
/ ** * */ пакет net.csdn.blog; Импорт java.io.file; импортировать java.io.ioexception; импортировать java.text.simpledateformat; импортировать java.util.date; импортировать java.util.concurrent.executors; импортировать java.util.concurrent.timeUnit; Импорт org.apache.log4j.fileAppender; Импорт org.apache.log4j.layout; Импорт org.apache.log4j.helpers.loglog; /** * @Author CODER_XIA * <p> * Используйте PreduledExeCutorService для реализации журналов печатной печати временной конфигурации * <p> * * * /public class preseeDexeCutorServiceAppender Extends fileAppender { /** * Паттерн даты. По умолчанию шаблон установлен на «'.'yyyy-mm-dd» *, что означает ежедневный роллет. */ private static final String datePattern = ". / *** Время интервала, единица: минуты*/ private int интервал времени = 10; SimpleDateFormat SDF = new SimpleDateFormat (datePattern); /*** Конструктор по умолчанию ничего не делает. */public cheduledExecutorserviceAppender () {}/** * создание <code> preduledExecutorServiceAppender </code> и откройте файл *, разработанный <code> filename </code>. Открытое имя файла станет * направлением для этого приложения. */ public glededExecutorserviceAppender (макет макета, имя строкового файла) бросает ioException {super (макет, имя файла, true); ActivateOptions (); } / ** * @return The IntervalTime * / public int getIntervaltime () {return QuardalTime; } / ** * @param интервал времени * Время интервала для установки * / public void setIntervaltime (int интервал) {this.Intervaltime = expredTime; } @Override public void ActivateOptions () {super.ActivateOptions (); Исполнители. NewsingleThreadSchededExeCutor (). PradeuLeAtFixEdRate (new LogTimetAsk (), 1, интервал * 60000, TimeUnit.milliseconds); } класс logTimeRtask реализует runnable {@Override public void run () {string datedfilename = filename + sdf.format (new date ()); закрытый файл (); File Target = новый файл (DatedFilename); if (target.exists ()) target.delete (); File file = new File (имя файла); Boolean result = file.renameto (Target); if (result) loglog.debug (filename + " ->" + datedfilename); else loglog.error («не удалось переименовать [« + файл » +»] до [" + datedfilename +"]. "); try {setFile (имя файла, true, bufferedio, buffersize); } catch (ioException e) {errorHandler.error ("setFile (" + filename + ", true) вызов вызов."); }}}}}Что касается реализации времени, это почти конец. По умолчанию - генерировать новый файл журнала за 10 минут. Вы можете установить его самостоятельно при его настройке. Тем не менее, есть скрытая опасность. Если человек на конфигурации не знает, что интервал времени - это минуты, если вы думаете, что это секунды, у вас есть 600, а затем откройте отладон для создания файла журнала с G, это определенно будет катастрофой. Следующее преобразование заключается в том, чтобы объединить максимальный размер RollingFileAppender и максимальное количество файлов резервного копирования, чтобы соответствовать, а затем улучшить его снова. В следующий раз мы продолжим описывать процесс трансформации.
Добавить конфигурацию имени модуля
Я упомянул пользовательскую реализацию класса Log4J Printing, поэтому я не буду говорить о указанном размере и количестве файлов резервного копирования. Я могу добавить его из кода копии класса RollingFileAppender в предыдущий пользовательский класс. Единственное, что необходимо решить, - это проблема параллелизма, то есть, когда файл переименования закрыт, будет сообщена ошибка выходного потока, когда произойдет событие журнала.
Сейчас есть такой сценарий приложения, и часто есть:
1. Проект содержит несколько разных проектов;
2. Один и тот же проект содержит разные модули.
Для первого случая вы можете настроить log4j <catogery = "test">, а затем использовать следующий метод при генерации Logger:
Logger logger = logger.getLogger ("test");Во втором случае мы надеемся распечатать различные модули в один и тот же файл журнала, но мы надеемся распечатать имя модуля в журнале, чтобы найти проблему, когда возникает проблема. Следовательно, эта статья должна добавить модуль на конфигурации в класс Приложения. Давайте начнем преобразование ниже. В отличие от печати, мы используем класс RollingFileAppender в качестве базового класса для преобразования.
Во -первых, добавьте модуль на конфигурации и добавьте методы получения и установки;
Поскольку он унаследован от RollingFileAppender, вам нужно только форматировать данные в LoggingEvent в subAppend (), добавить метод FormatinFo для форматирования данных, и код опущен;
Конечная категория продукта заключается в следующем:
пакет net.csdn.blog; Импорт org.apache.log4j.category; Импорт org.apache.log4j.rollingfileappender; Импорт org.apache.log4j.spi.loggingevent; / ** * @Author CODER_XIA * */ Public Class ModuleAppender Extends RollingFileAppender {Private String Modulename; / ** * @return the Modulename */ public String getModulename () {return Modulename; } / ** * @param modulename * Модульское имя для установки * / public void setmodulename (string modulename) {this.modulename = modulename; } / ** * Format Print Content * * @param Event * event * @return msg * / private String formatinfo (oventevent event) {StringBuilder sb = new StringBuilder (); if (modulename! = null) {sb.append (modulename) .append ("|"); sb.append (event.getMessage ()); } вернуть sb.toString (); } @Override public void subAppend (ovent void event) {string msg = formatinfo (event); super.subappend (new LoggingEvent (Category.class.getName (), Event .getLogger (), event.getLevel (), msg, null)); }}