Сегодня в полдень я не буду отдыхать, я закончу оставшуюся часть черновика~
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>
Наконец, более продвинутый контент можно узнать из документов официального сайта.У меня такое ощущение, что если бы я провел четыре года свободного времени в колледже, изучая англоязычную техническую документацию, может быть, может быть, я сейчас буду другим. всем спасибо за прочтение!