Java 9 Platform Logging API

1. Introduktion

I denne vejledning udforsker vi den nyligt introducerede Logging API i Java 9 og implementerer nogle eksempler for at dække de mest almindelige sager.

Denne API er blevet introduceret i Java til give en fælles mekanisme til at håndtere alle platformslogfiler og eksponere en servicegrænseflade, der kan tilpasses af biblioteker og applikationer. På denne måde kan JDK-platformloggene bruge den samme logningsramme som applikationen, og projektafhængigheden kan reduceres.

2. Oprettelse af en brugerdefineret implementering

I dette afsnit skal vi vise de vigtigste klasser i Logging API, som vi skal implementere for at oprette en ny logger. Det gør vi ved at implementere en simpel logger, der udskriver alle logfiler til konsollen.

2.1. Oprettelse af Logger

Hovedklassen, som vi er nødt til at skabe, er Logger. Denne klasse skal implementere System.Logger interface og disse fire metoder mindst:

  • getName (): returnerer navnet på loggeren. Det bruges af JDK til at oprette loggere ved navn
  • isLoggable (): angiver, hvilke niveauer loggeren er aktiveret til
  • log (): det er metoden, der udskriver loggen til det underliggende system, applikationen bruger - konsollen i vores tilfælde. Der er 2 log () metoder til implementering, der hver modtager forskellige parametre

Lad os se, hvordan vores implementering vil se ud:

offentlig klasse ConsoleLogger implementerer System.Logger {@Override public String getName () {return "ConsoleLogger"; } @Override public boolean isLoggable (Level level) {return true; } @ Overstyr offentlig tomrumslog (Niveauniveau, ResourceBundle-pakke, String-meddelelse, Kan kastes) {System.out.printf ("ConsoleLogger [% s]:% s -% s% n", niveau, msg, kastet); } @Override offentlig ugyldig log (Niveauniveau, ResourceBundle-pakke, Stringformat, Objekt ... params) {System.out.printf ("ConsoleLogger [% s]:% s% n", niveau, MessageFormat.format (format, params)); }}

Vores ConsoleLogger klasse tilsidesætter de fire nævnte metoder. Det getName () metode returnerer a Snor, mens isLoggable () metoden vender tilbage rigtigt i alle tilfælde. Endelig har vi 2 log () metode, der sendes til konsollen.

2.2. Oprettelse af LoggerFinder

Når vi først har oprettet vores logger, vi har brug for at implementere en LoggerFinder der skaber forekomster af vores ConsoleLogger.

For at gøre det er vi nødt til at udvide den abstrakte klasse System.LoggerFinder og implementere getLogger () metode:

offentlig klasse CustomLoggerFinder udvider System.LoggerFinder {@Override public System.Logger getLogger (String name, Module module) {return new ConsoleLogger (); }}

I dette tilfælde returnerer vi altid vores ConsoleLogger.

Endelig skal vi registrere vores LoggerFinder som en tjeneste, så den kan blive opdaget af JDK. Hvis vi ikke leverer en implementering, SimpleConsoleLogger bruges som standard.

Den mekanisme, som JDK bruger til at indlæse implementeringerne, er den ServiceLoader. Du kan finde mere information om det i denne vejledning.

Da vi bruger Java 9, pakker vi vores klasse i et modul og registrerer vores service i modul-info.java fil:

modul com.baeldung.logging {giver java.lang.System.LoggerFinder med com.baeldung.logging.CustomLoggerFinder; eksport com.baeldung.logging; }

For mere information om Java-moduler, se denne anden vejledning.

2.3. Test af vores eksempel

For at teste vores eksempel, lad os oprette et andet modul, der fungerer som en applikation. Dette vil kun indeholde Vigtigste klasse, der bruger vores serviceimplementering.

Denne klasse får en instans af vores ConsoleLogger ved at ringe til System.getLogger () metode:

offentlig klasse MainApp {privat statisk System.Logger LOGGER = System.getLogger ("MainApp"); public static void main (String [] args) {LOGGER.log (Level.ERROR, "error test"); LOGGER.log (Level.INFO, "info test"); }}

Internt vil JDK afhente vores CustomLoggerFinder implementering og oprette en instans af vores ConsoleLogger.

Lad os derefter oprette modul-info fil til dette modul:

modul com.baeldung.logging.app {}

På dette tidspunkt vil vores projektstruktur se sådan ud:

├── src │ ├── moduler │ │ ├── com.baeldung.logging │ │ │ ├── com │ │ │ │ ─── baeldung │ │ │ │ └── logging │ │ │ │ ├── ConsoleLogger .java │ │ │ │── CustomLoggerFinder.java │ │ │ └── module-info.java │ │ ├── com.baeldung.logging.app │ │ │ ├── com │ │ │ │ ─── baeldung │ │ │ │ ─── logning │ │ │ │ └── app │ │ │ │── MainApp.java │ │ │ └── module-info.java └──

Endelig skal vi sammensætte vores to moduler, og vi placerer dem i en mods vejviser:

javac - modul-sti mods -d mods / com.baeldung.logging \ src / modules / com.baeldung.logging / module-info.java \ src / modules / com.baeldung.logging / com / baeldung / logging / * .java javac - modul-sti mods -d mods / com.baeldung.logging.app \ src / moduler / com.baeldung.logging.app / module-info.java \ src / modules / com.baeldung.logging.app /com/baeldung/logging/app/*.java

Lad os endelig køre Vigtigste klasse af app modul:

java --modul-sti mods \ -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp

Hvis vi ser på konsoludgangen, kan vi se, at vores logfiler udskrives ved hjælp af vores ConsoleLogger:

ConsoleLogger [ERROR]: fejltest ConsoleLogger [INFO]: info test

3. Tilføjelse af en ekstern logningsramme

I vores tidligere eksempel loggede vi alle vores meddelelser til konsollen, hvilket er det samme som hvad standardloggeren gør. En af de mest nyttige anvendelser af Logging API i Java 9 er at lade applikationer dirigere JDK-logfilerne til den samme logningsramme, som applikationen bruger, og det er hvad vi skal gøre i dette afsnit.

Vi opretter et nyt modul, der bruger SLF4J som logningsfacade og Logback som logningsramme.

Da vi allerede har forklaret det grundlæggende i det foregående afsnit, kan vi nu fokusere på, hvordan du tilføjer en ekstern logningsramme.

3.1. Brugerdefinerede implementeringer ved hjælp af SLF4J

Først implementerer vi en anden Logger der opretter en ny SLF4J-logger til hver forekomst:

offentlig klasse Slf4jLogger implementerer System.Logger {privat endelig strengnavn; privat endelig Logger logger; offentlig Slf4jLogger (strengnavn) {this.name = navn; logger = LoggerFactory.getLogger (navn); } @ Override public String getName () {return name; } // ...}

Bemærk, at dette Logger er en org.slf4j.Logger.

For resten af ​​metoderne, Vi stoler på implementeringen på SLF4J logger-instansen. Derfor er vores Logger vil blive aktiveret, hvis SLF4J-loggeren er aktiveret:

@Override public boolean isLoggable (Level level) {switch (level) {case OFF: return false; sag TRACE: returner logger.isTraceEnabled (); sag DEBUG: returner logger.isDebugEnabled (); sag INFO: returner logger.isInfoEnabled (); sag ADVARSEL: returner logger.isWarnEnabled (); sag FEJL: returner logger.isErrorEnabled (); sag ALLE: standard: returner sand; }}

Og logmetoderne kalder den passende SLF4J-loggermetode afhængigt af det anvendte logniveau:

@ Overstyr offentlig tomrumslog (Niveauniveau, ResourceBundle-pakke, String-meddelelse, Kastbar) {hvis (! IsLoggable (niveau)) {return; } switch (niveau) {case TRACE: logger.trace (msg, kastet); pause; sag DEBUG: logger.debug (msg, kastet); pause; sag INFO: logger.info (msg, kastet); pause; sag ADVARSEL: logger.warn (msg, kastet); pause; sag FEJL: logger.error (msg, kastet); pause; sag ALLE: standard: logger.info (msg, kastet); }} @ Overstyr offentlig tomrumslog (Niveauniveau, ResourceBundle-pakke, Stringformat, Objekt ... parametre) {if (! IsLoggable (level)) {return; } Strengmeddelelse = MessageFormat.format (format, params); switch (niveau) {case TRACE: logger.trace (meddelelse); pause; // ... // samme som den forrige switch}}

Lad os endelig oprette en ny LoggerFinder der bruger vores Slf4jLogger:

offentlig klasse Slf4jLoggerFinder udvider System.LoggerFinder {@Override public System.Logger getLogger (String name, Module module) {returner ny Slf4jLogger (name); }}

3.2. Modulkonfiguration

Når vi har alle vores klasser implementeret, lad os registrere vores service i vores modul og tilføje afhængigheden af ​​SLF4J-modulet:

modul com.baeldung.logging.slf4j {kræver org.slf4j; giver java.lang.System.LoggerFinder com.baeldung.logging.slf4j.Slf4jLoggerFinder; eksport com.baeldung.logging.slf4j; }

Dette modul har følgende struktur:

├── src │ ├── moduler │ │ ├── com.baeldung.logging.slf4j │ │ │ ├── com │ │ │ │ ─── baeldung │ │ │ │ └── logning │ │ │ │ └─ ─ slf4j │ │ │ │── Slf4jLoggerFinder.java │ │ │ │── Slf4jLogger.java │ │ │ └── module-info.java └──

Nu kan vi kompilere dette modul i mods katalog som vi gjorde i det foregående afsnit.

Bemærk, at vi er nødt til at placere slf4j-api jar i mods-kataloget for at kompilere dette modul. Husk også at bruge en modulariseret version af biblioteket. Den nyeste version kan findes i Maven Central.

3.3. Tilføjer logback

Vi er næsten færdige, men vi skal stadig tilføje Logback-afhængigheder og konfiguration. For at gøre det skal du placere logback-klassiker og logback-kerne krukker i mods vejviser.

Som før skal vi sørge for, at vi bruger en modulær version af biblioteket. Igen kan den nyeste version findes i Maven Central.

Lad os endelig oprette en Logback-konfigurationsfil og placere den i vores mods vejviser:

    % d {åååå-MM-dd HH: mm: ss} [% tråd]% -5niveau% logger {36} -% msg% n 

3.4. Kører vores ansøgning

På dette tidspunkt kan vi køre vores app ved hjælp af vores SLF4J-modul.

I dette tilfælde, Vi skal også angive vores Logback-konfigurationsfil:

java --modul-sti mods \ -Dlogback.configurationFile = mods / logback.xml \ -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp

Endelig, hvis vi kontrollerer output, kan vi se, at vores logfiler udskrives ved hjælp af vores Logback-konfiguration:

2018-08-25 14:02:40 [main] FEJL MainApp - fejltest 2018-08-25 14:02:40 [main] INFO MainApp - info test

4. Konklusion

Vi har vist i denne artikel, hvordan man opretter en brugerdefineret logger i Java 9 ved hjælp af den nye Platform Logging API. Vi har også implementeret et eksempel ved hjælp af en ekstern logningsramme, som er en af ​​de mest nyttige brugssager i denne nye API.

Som altid er den fulde kildekode for eksemplerne tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found