Hoi! Bij het schrijven van de lessen benadruk ik vooral of er een specifiek onderwerp is dat absoluut essentieel zal zijn in het echte werk. Dus, LUISTER UP! Het onderwerp dat we vandaag behandelen, zal zeker van pas komen in al uw projecten vanaf de eerste dag van uw dienstverband. We gaan het hebben over Java Logging. Dit onderwerp is helemaal niet ingewikkeld (ik zou zelfs zeggen makkelijk). Maar je zult genoeg voor de hand liggende dingen hebben om je druk over te maken bij je eerste baan, dus het is beter om het nu goed te begrijpen :) Nou, laten we beginnen.

Wat is inloggen op Java?

Loggen is het vastleggen van gegevens over de werking van een programma. De plaats waar we deze gegevens vastleggen, wordt een "logboek" genoemd. Er rijzen meteen twee vragen: welke gegevens worden geschreven en waar? Laten we beginnen met het "waar". U kunt op veel verschillende plaatsen gegevens over het werk van een programma schrijven. Tijdens je studie heb je bijvoorbeeld vaak System.out.println()om gegevens naar de console uit te voeren. Dit is inderdaad logging, zij het in zijn eenvoudigste vorm. Dit is natuurlijk niet erg handig voor gebruikers of een productondersteuningsteam: ze willen natuurlijk geen IDE installeren en de console in de gaten houden :) Er is een meer gebruikelijk formaat voor het opnemen van informatie: tekstbestanden. Mensen zijn veel comfortabeler in het lezen van gegevens in dit formaat, en het is zeker veel handiger om gegevens op te slaan! Nu de tweede vraag: welke programmagegevens moeten worden gelogd? Dat is helemaal aan jou! Het logboeksysteem van Java is zeer flexibel. U kunt het configureren om alles te loggen wat uw programma doet. Aan de ene kant is dit goed. Maar stel je aan de andere kant voor hoe groot de logboeken van Facebook of Twitter zouden zijn als ze er alles in zouden schrijven. Deze grote bedrijven hebben waarschijnlijk wel de mogelijkheid om zoveel gegevens op te slaan. Maar stel je eens voor hoe moeilijk het zou zijn om informatie te vinden over één kritieke fout in 500 gigabyte aan tekstlogboeken? Dat zou erger zijn dan zoeken naar een speld in een hooiberg. Dienovereenkomstig kan Java worden geconfigureerd om alleen foutgegevens te loggen. Of zelfs alleen kritieke fouten! Dat gezegd hebbende, is het niet helemaal juist om te spreken van Java's native logging-systeem. Feit is dat programmeurs logging nodig hadden voordat deze functionaliteit aan de taal werd toegevoegd. Tegen de tijd dat Java zijn eigen logboekbibliotheek introduceerde, maakte iedereen al gebruik van de log4j-bibliotheek. De geschiedenis van inloggen op Java is eigenlijk heel lang en informatief. Kortom, Java heeft zijn eigen logboekbibliotheek, maar bijna niemand gebruikt het :) Later, toen er verschillende logbibliotheken verschenen en door programmeurs werden gebruikt, ontstonden er compatibiliteitsproblemen. Om te voorkomen dat mensen het wiel opnieuw uitvinden in een dozijn verschillende bibliotheken met verschillende interfaces, is het abstracte SLF4J-framework ("Service Logging Facade For Java") gemaakt. Het wordt abstract genoemd, want zelfs als je de methoden van SLF4J-klassen gebruikt en aanroept, gebruiken ze eigenlijk alle logframeworks die ervoor kwamen: log4j, de standaard java.util.logging en andere. Als je op een gegeven moment een specifieke functie van Log4j nodig hebt die in andere bibliotheken ontbreekt, maar je je project niet rechtstreeks aan deze bibliotheek wilt koppelen, gebruik dan gewoon SLF4J. En laat het dan de Log4j-methoden aanroepen. Als u van gedachten verandert en besluit dat u Log4j-functies niet langer nodig heeft, hoeft u alleen de "hier , en de Log4j-bibliotheek hier . Pak vervolgens het archief uit en gebruik IntelliJ IDEA om de JAR-bestanden aan het klassenpad toe te voegen. Menu-items: Bestand -> Projectstructuur -> Bibliotheken Selecteer de benodigde JAR-bestanden en voeg ze toe aan het project (de archieven die we hebben gedownload bevatten veel JAR-bestanden - kijk naar de afbeeldingen om te zien welke je nodig hebt) Merk op dat deze instructie voor die Waarom we logboekregistratie nodig hebben - 2Waarom we logboekregistratie nodig hebben - 3studenten die niet weten hoe ze Maven moeten gebruiken. Als je weet hoe je Maven moet gebruiken, is het meestal beter (veel gemakkelijker) om daar te beginnen. Als u Maven gebruikt , voegt u deze afhankelijkheid toe:

    	<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.14.0</version>
    	</dependency>
Geweldig! We hebben de instellingen gevonden :) Laten we eens kijken hoe SLF4J werkt. Hoe zorgen we ervoor dat het werk van het programma ergens wordt vastgelegd? Hiervoor hebben we twee dingen nodig: logger en appender. Laten we beginnen met de eerste. Een logger is een object dat volledige controle biedt over logging. Een logger maken is heel eenvoudig: we doen dit met behulp van de statische LoggerFactory.getLogger() methoden. De methodeparameter is de klasse waarvan de bewerking wordt vastgelegd. Laten we onze code uitvoeren:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("Test log entry!!!");
       LOGGER.error("An error occurred!");
   }
}
Console-uitvoer:

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
Wat zien we hier? Eerst zien we een foutmelding. Dit is een gevolg van het feit dat we nu de nodige instellingen missen. Dienovereenkomstig kan onze logger momenteel alleen foutmeldingen (ERROR) uitvoeren en alleen naar de console. De methode logger.info() werkte niet. Maar logger.error() deed het! Op de console zien we de huidige datum, de methode waarop de fout is opgetreden ( main), het woord "ERROR", en onze boodschap! ERROR is het logboekniveau. In het algemeen geldt dat als een logboekvermelding is gemarkeerd met het woord "ERROR", er op dit punt in het programma een fout is opgetreden. Als het item is gemarkeerd met het woord "INFO", geeft het bericht alleen actuele informatie weer over de normale werking van het programma. De SLF4J-bibliotheek heeft veel verschillende logboekniveaus waarmee u logboekregistratie flexibel kunt configureren. Het is allemaal heel eenvoudig te beheren: alle benodigde logica zit al in de Java Logger- klasse. U hoeft alleen de relevante methoden aan te roepen. Als u een routinebericht wilt loggen, roept u de methode logger.info() aan. Gebruik logger.error() voor een foutmelding . Gebruik voor een waarschuwing logger.warn()

Laten we het nu hebben over appender

Een appender is de plaats waar uw gegevens naartoe gaan. In zekere zin het tegenovergestelde van een gegevensbron, namelijk "punt B". Standaard worden gegevens uitgevoerd naar de console. Merk op dat we in het vorige voorbeeld niets hoefden te configureren: de tekst verscheen in de console en de logger van de Log4j-bibliotheek kan alleen berichten op ERROR-niveau naar de console sturen. Het is duidelijk dat het voor mensen handiger is om logboeken in een tekstbestand te lezen en te schrijven. Om het standaardgedrag van de logger te wijzigen, moeten we onze bestandsappender configureren. Om aan de slag te gaan, moet u een log4j.xml-bestand rechtstreeks in de map src maken. Je bent al bekend met het XML-formaat: we hebben er onlangs een les over gehad :) Dit is de inhoud van het bestand:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
   <Appenders>
       <File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
           <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
       </File>
   </Appenders>
   <Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
   </Loggers>
</Configuration>
Niets bijzonders of moeilijks hier :) Maar toch, laten we de inhoud doornemen.
<Configuration status="INFO">
Dit is de zogenaamde StatusLogger. Het staat los van onze logger en wordt gebruikt in de interne processen van Log4j. Als u status="TRACE" instelt in plaats van status="INFO", wordt alle informatie over het interne werk van Log4j weergegeven op de console (StatusLogger geeft gegevens weer op de console, zelfs als onze appender een bestand is). We hebben het nu niet nodig, dus laten we het zoals het is.

<Appenders>
   <File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
       <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
   </File>
</Appenders>
Hier maken we onze appender. De tag <File> geeft aan dat het een bestandsappender zal zijn. name="MyFileAppender" stelt de naam van de appender in. fileName="C:\Users\Gebruikersnaam\Desktop\testlog.txt" geeft het pad aan naar het logbestand waar alle gegevens naartoe worden geschreven. append="true" geeft aan of de gegevens aan het einde van het bestand moeten worden geschreven. In ons geval is dit precies wat we gaan doen. Als u de waarde instelt op false, wordt de oude inhoud van het logbestand elke keer dat het programma wordt gestart, verwijderd. <PatternLayout patroon="%d{jjj-MM-dd HH:mm:ss.SSS} [%t] %-5niveau %logger{36} - %msg%n"/>geeft de opmaakinstellingen aan. Hier kunnen we reguliere expressies gebruiken om aan te passen hoe tekst wordt opgemaakt in ons logboek.

<Loggers>
       <Root level="INFO">
           <AppenderRef ref="MyFileAppender"/>
       </Root>
</Loggers>
Hier geven we het rootniveau aan. We hebben het niveau "INFO" ingesteld, wat betekent dat alle berichten waarvan het niveau hoger is dan INFO (volgens de tabel die we hierboven hebben bekeken) niet worden gelogd. Ons programma heeft 3 berichten: één INFO, één WARN en één ERROR. Met de huidige configuratie worden alle 3 de berichten gelogd. Als u het rootniveau wijzigt in ERROR, komt alleen het laatste bericht van de LOGGER.error()-methodeaanroep in het logboek terecht. Bovendien hoort hier ook een verwijzing naar de appender. Om zo'n verwijzing te maken, moet u een <ApprenderRef> -tag binnen de <Root> -tag maken en het kenmerk ref='naam van uw appender' eraan toevoegen. Voor het geval je het vergeten bent, hier hebben we de naam van de apper ingesteld: <. En hier is onze code!

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyTestClass {

   public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);

   public static void main(String[] args) {

       LOGGER.info("The program is starting!!!");

       try {
           LOGGER.warn("Attention! The program is trying to divide a number by another.
           System.out.println(12/0);
       } catch (ArithmeticException x) {

           LOGGER.error("Error! Division by zero!");
       }
   }
}
Het is natuurlijk een beetje gek (het vangen van een RuntimeException is een twijfelachtig idee), maar het is perfect voor onze doeleinden :) Laten we onze methode main() 4 keer achter elkaar uitvoeren en naar ons testlog.txt-bestand kijken. Je hoeft het niet van tevoren aan te maken: de bibliotheek doet dit automatisch. Alles werkte! :) Nu heb je een geconfigureerde logger. Je kunt spelen met een aantal van je oude programma's, door logger-oproepen aan elke methode toe te voegen. Kijk dan naar het resulterende logboek :) Het gaat dieper in op het onderwerp inloggen. Het zou een uitdaging zijn om alles in één keer uit te lezen. Dat gezegd hebbende, bevat het wel veel aanvullende nuttige informatie. U leert bijvoorbeeld hoe u de logger zo configureert dat deze een nieuw tekstbestand aanmaakt als ons testlog.txt-bestand een bepaalde grootte bereikt :) En daarmee sluiten we onze les af! Vandaag heb je kennis gemaakt met een heel belangrijk onderwerp en deze kennis zal je zeker van pas komen bij je toekomstige werk. Tot de volgende keer! :)