Сегодня я расскажу о логировании в Java --- логирование, logback

Java задняя часть
Сегодня я расскажу о логировании в Java --- логирование, logback

Сегодня в полдень я не буду отдыхать, я закончу оставшуюся часть черновика~

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-classiccoreЭто основной модуль и основа двух других модулей.

  • logbackОн состоит из трех компонентов, а именноLogger,Appender,Layoutloggerпринадлежать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>

Наконец, более продвинутый контент можно узнать из документов официального сайта.У меня такое ощущение, что если бы я провел четыре года свободного времени в колледже, изучая англоязычную техническую документацию, может быть, может быть, я сейчас буду другим. всем спасибо за прочтение!