Сегодня в полдень я не буду отдыхать, я закончу оставшуюся часть черновика~
1. Система ведения журнала, поставляемая с Java API.
Java поставляется с регистрацией APIjava.util.loggingВ пакете есть только несколько классов, как показано ниже:
На самом деле структура очень проста, в основном состоит из следующих трех компонентов:
-
LoggerКомпонент: компонент регистратора определяет некоторые основные операции журнала, такие какlogвыходной журнал,getNameполучить имя объекта журнала,setLevel()Настройка уровня журнала и т. д. — это некоторые основные операции! -
HandlerКомпоненты:HandlerНекоторая обработка журнала должна определить это! Например, вы хотите записать вывод в файл, вы можете использоватьFileHandler, для вывода лога на консоль используйтеConsoleHandlerЖдать -
FormatterКомпонент: очевидно, чтобы определить формат вывода журнала! -
LevelКомпонент: уровень журнала, самый базовый уровеньINFO,WARNING -
filterКомпонент: фильтр, который позволяет фильтровать вывод лога
дляJava apiЖурнал системы, я написал небольшой каштан, чтобы подытожить:
package com.wokao66.logger;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.logging.FileHandler;
import java.util.logging.Filter;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class JavaLogger {
static Logger logger = Logger.getLogger(JavaLogger.class.getName());
public static void HandlerFilter() throws SecurityException, IOException {
//首先我声明一个文件处理器,因为我打算将日志输出到一个文件当中,即保存在E盘的a.txt文件
FileHandler handler = new FileHandler("E://a.txt");
//我自定义一个Formatter,用于对每条输出日志进行格式化,你也可以不指定,则默认使用SimpleFormatter
handler.setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
//这就是我自定义的格式
return "[" + new SimpleDateFormat().format(record.getMillis()) + "]-[" + record.getLevel()
+ "]-" + record.getSourceClassName() + "-" + "[" + record.getMessage() + "]\n";
}
});
//当然,我也可以设置一个过滤器
handler.setFilter(new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
//当日志内容与"this is a unloged message!"相同时,则不输出该日志,当然这里只是测试,实际项目这个规则是不存在的
return !record.getMessage().equals("this is a unloged message!");
}
});
//给Logger设置Handler
logger.addHandler(handler);
//默认是ConsoleHandler,禁用之后才不会输出到控制台,而是输出到文件中
logger.setUseParentHandlers(false);
}
public static void main(String[] args) throws SecurityException, IOException {
HandlerFilter();
logger.log(Level.INFO, "this is a info message!");
logger.log(Level.OFF, "this is a OFF message!");
logger.log(Level.SEVERE, "this is a SEVERE message!");
logger.log(Level.WARNING, "this is a WARNING message!");
logger.log(Level.INFO, "this is a unloged message!");//这一句将不会被记录到文件中
}
}
Во-вторых, поговорим о Logback!
logbackЭтот парень часто используется на предприятии. Сначала я расскажу о некоторых общих компонентах и конфигурациях логбэка, а затем приведу каштан в качестве демонстрации.
-
logbackОн состоит из трех основных модулей, а именноlogback-core,logback-access,logback-classic.вcoreЭто основной модуль и основа двух других модулей. -
logbackОн состоит из трех компонентов, а именноLogger,Appender,Layout.вloggerпринадлежатьclassicмодуль,appender,layoutпринадлежатьcoreмодуль,coreмодуль неloggerКонцепция чего-либо!AppenderФактически, это указывает на место назначения вывода журнала, который может быть консоль или файл. -
logbackОбычно имеет собственное соглашение об именахloggerОн назван в соответствии с иерархией и имеет отношение наследования, с.Приходит как разделение, имеющее концепцию предков и родительских узлов, таких какloggerНазван какcom.wokao666.www,Такcomто естьwokao666Родительский узел,comдаwwwпредковый узел. -
rootпринадлежат всемloggerкорневой узелorg.slf4j.Logger.ROOT_LOGGER_NAMEтак какrootимя. -
logbackПо умолчанию путь к классам будет искать файл с именемlogback-test.xml,logback.groovyилиlogback.xmlконфигурационный файл. -
Печать лога проходит вверх, что это значит? Например, если вы распечатываете журнал информационного уровня (вывод на консоль) и журнал ошибок, консоль одновременно выводит и журналы информации, и журналы ошибок, поскольку уровень ошибок выше, чем информационный.
Это просто! Итак, скажите, что вы хотите использоватьlogback, есть три основных шага:
- 1. Создайте соответствующий файл конфигурации в пути к классам, например
logback.xmlи выполните соответствующую настройку. - 2. Позвонив
LoggerFactory.getLogger()метод и передать ему имя или класс, чтобы получитьLoggerобъект - 3, полученный на втором шаге
Loggerобъект, вызовите соответствующий метод уровня журнала, напримерinfo(),error()
Ну не буду больше говорить, основы таковы, позвольте мне продемонстрировать волну через вопросы и каштаны:
先看看我的配置文件logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 表示启动配置文件扫描,每隔30秒扫描一次,什么意思?就是说它会去检查你的配置文件在运行过程中配置是否有变化 -->
<configuration scan="true" scanPeriod="30 seconds">
<!-- 配置一个存放日志文件的地方,注意这里是一个变量来着,以后可以通过${变量名}来获取变量的值 -->
<property name="log.base" value="/logs" />
<!-- 这里又定义一个变量 -->
<property name="log.controller" value="${log.base}/controller" />
<!-- 输出到控制台 -->
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 声明了一个存放info消息的appender -->
<!-- 启动日志回滚appender,就是说有一些规则,比如说规定一个文件大小达到10M之后输出到一个新的文件中去 -->
<appender name="controller-info"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.controller}/current-info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.controller}/controller_info_%d{yyyyMMdd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%msg%n</pattern>
</encoder>
</appender>
<!-- 声明了一个存放error消息的appender -->
<appender name="controller-error"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.controller}/current-error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.controller}/controller_error_%d{yyyyMMdd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%msg%n</pattern>
</encoder>
</appender>
<!-- 这里我定义一个logger,该logger会跟踪club.wokao666包下的日志打印语句,但是它不会对日志进行输出,因为你没有关联任何的appender,虽然没有关联,但是默认会继承自父logger的相应配置,即club包下的配置,由于我们也没有对club进行相应的配置,所以它默认会继承自下面的 root logger -->
<logger name="club.wokoa666" level="info"></logger>
<logger name="club.wokao666.controller" additivity="false" level="WARN">
<appender-ref ref="controller-error" /><!-- 关联我们的Appender,表示日志输出的地址 -->
</logger>
<!-- 这就是我们的根logger -->
<root level="info">
<appender-ref ref="controller-info" />
</root>
</configuration>
日志分类实例,添加相应的过滤器
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<property name="log.base" value="/logs" />
<property name="log.controller" value="${log.base}/controller" />
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<appender name="controller-info"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.controller}/current-info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.controller}/controller_info_%d{yyyyMMdd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%msg%n</pattern>
</encoder>
<!-- 过滤器配置 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="controller-debug"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.controller}/current-debug.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.controller}/controller_debug_%d{yyyyMMdd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%msg%n</pattern>
</encoder>
<!-- 过滤器配置 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="controller-error"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.controller}/current-error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.controller}/controller_error_%d{yyyyMMdd_HH}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%msg%n</pattern>
</encoder>
<!-- 过滤器配置 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="trace">
<appender-ref ref="controller-error" />
<appender-ref ref="controller-info" />
<appender-ref ref="controller-debug" />
</root>
</configuration>
Наконец, более продвинутый контент можно узнать из документов официального сайта.У меня такое ощущение, что если бы я провел четыре года свободного времени в колледже, изучая англоязычную техническую документацию, может быть, может быть, я сейчас буду другим. всем спасибо за прочтение!