Java 9 Platform Logging API

1. Introduksjon

I denne opplæringen vil vi utforske det nylig introduserte Logging API i Java 9 og implementere noen eksempler for å dekke de vanligste sakene.

Denne API-en er introdusert i Java til gi en felles mekanisme for å håndtere alle plattformloggene og å avsløre et tjenestegrensesnitt som kan tilpasses av biblioteker og applikasjoner. På denne måten kan JDK-plattformloggene bruke samme loggingsrammeverk som applikasjonen, og prosjektavhengighetene kan reduseres.

2. Lage en tilpasset implementering

I denne delen skal vi vise hovedklassene til Logging API som vi må implementere for å opprette en ny logger. Vi gjør det ved å implementere en enkel logger som skriver ut alle loggene til konsollen.

2.1. Opprette Logger

Hovedklassen som vi må lage er Logger. Denne klassen må implementere System.Logger grensesnitt og disse fire metodene i det minste:

  • getName (): returnerer navnet på loggeren. Den vil bli brukt av JDK til å lage loggere ved navn
  • isLoggable (): angir hvilke nivåer loggeren er aktivert for
  • Logg(): det er metoden som skriver ut loggen til det underliggende systemet applikasjonen bruker - konsollen i vårt tilfelle. Det er 2 Logg() metoder for å implementere, hver av dem mottar forskjellige parametere

La oss se hvordan implementeringen vår vil se ut:

offentlig klasse ConsoleLogger implementerer System.Logger {@Override public String getName () {return "ConsoleLogger"; } @Override public boolean isLoggable (Level level) {return true; } @Override public void log (Level level, ResourceBundle bundle, String msg, Throwable throw) {System.out.printf ("ConsoleLogger [% s]:% s -% s% n", level, msg, throw); } @ Overstyr offentlig tomromslogg (nivånivå, ResourceBundle-pakke, strengformat, objekt ... params) {System.out.printf ("ConsoleLogger [% s]:% s% n", nivå, MessageFormat.format (format params)); }}

Våre ConsoleLogger klasse overstyrer de fire nevnte metodene. De getName () metoden returnerer a Streng, mens isLoggable () metoden returnerer ekte i alle tilfeller. Endelig har vi 2 Logg() metode som sendes ut til konsollen.

2.2. Opprette LoggerFinder

Når vi har opprettet loggeren, vi trenger å implementere en LoggerFinder som skaper forekomster av vår ConsoleLogger.

For å gjøre det, må vi utvide den abstrakte klassen System.LoggerFinder og implementere getLogger () metode:

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

I dette tilfellet returnerer vi alltid våre ConsoleLogger.

Til slutt må vi registrere våre LoggerFinder som en tjeneste slik at den kan oppdages av JDK. Hvis vi ikke gir en implementering, vil SimpleConsoleLogger vil bli brukt som standard.

Mekanismen som brukes av JDK for å laste implementeringene er ServiceLoader. Du kan finne mer informasjon om det i denne veiledningen.

Siden vi bruker Java 9, pakker vi klassen vår i en modul og registrerer tjenesten vår i module-info.java fil:

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

For mer informasjon om Java-moduler, sjekk ut denne andre opplæringen.

2.3. Testing vårt eksempel

For å teste eksemplet vårt, la oss lage en annen modul som fungerer som en applikasjon. Dette vil bare inneholde Hoved klasse som bruker vår tjenesteimplementering.

Denne klassen vil få en forekomst av vår ConsoleLogger ved å ringe 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, "infotest"); }}

Internt vil JDK hente vår CustomLoggerFinder implementering og opprette en forekomst av vår ConsoleLogger.

Etter det, la oss lage modul-info fil for denne modulen:

modul com.baeldung.logging.app {}

På dette tidspunktet vil prosjektstrukturen vår se slik ut:

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

Til slutt skal vi kompilere de to modulene våre, og vi plasserer dem i en mods katalog:

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

Til slutt, la oss kjøre Hoved klasse av app modul:

java --module-path mods \ -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp

Hvis vi tar en titt på konsollutgangen, kan vi se at loggene våre skrives ut med ConsoleLogger:

ConsoleLogger [ERROR]: feiltest ConsoleLogger [INFO]: infotest

3. Legge til et eksternt loggingsrammeverk

I vårt forrige eksempel logget vi alle meldingene våre til konsollen, noe som er det samme som standardloggeren. En av de mest nyttige bruksområdene for Logging API i Java 9 er å la applikasjoner dirigere JDK-loggene til samme loggingsrammeverk som applikasjonen bruker., og det er det vi skal gjøre i denne delen.

Vi oppretter en ny modul som bruker SLF4J som loggfasade og Logback som loggingsramme.

Siden vi allerede har forklart det grunnleggende i forrige avsnitt, kan vi nå fokusere på hvordan du legger til et eksternt loggingsrammeverk.

3.1. Egendefinerte implementeringer ved bruk av SLF4J

Først implementerer vi en annen Logger som vil opprette en ny SLF4J-logger for hver forekomst:

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

Legg merke til at dette Logger er en org.slf4j.Logger.

For resten av metodene, Vi vil stole på implementeringen på SLF4J logger-forekomsten. Derfor vår Logger vil bli aktivert hvis SLF4J-loggeren er aktivert:

@Override public boolean isLoggable (Level level) {switch (level) {case OFF: return false; case TRACE: return logger.isTraceEnabled (); sak DEBUG: return logger.isDebugEnabled (); case INFO: return logger.isInfoEnabled (); sak ADVARSEL: return logger.isWarnEnabled (); sak FEIL: return logger.isErrorEnabled (); case ALL: standard: return true; }}

Og loggmetodene vil kalle riktig SLF4J-loggermetode, avhengig av loggnivået som brukes:

@Override offentlig ugyldighetslogg (Nivånivå, ResourceBundle-pakke, String-melding, Kastbar kastet) {if (! IsLoggable (level)) {return; } bytte (nivå) {case TRACE: logger.trace (msg, kastet); gå i stykker; sak DEBUG: logger.debug (msg, kastet); gå i stykker; sak INFO: logger.info (msg, kastet); gå i stykker; sak ADVARSEL: logger.warn (msg, kastet); gå i stykker; sak FEIL: logger.error (msg, kastet); gå i stykker; sak ALLE: standard: logger.info (msg, kastet); }} @Override public void log (Nivånivå, ResourceBundle-pakke, Stringformat, Objekt ... params) {if (! IsLoggable (level)) {return; } Strengmelding = MessageFormat.format (format, params); switch (level) {case TRACE: logger.trace (melding); gå i stykker; // ... // samme som forrige bryter}}

Til slutt, la oss lage en ny LoggerFinder som bruker vår Slf4jLogger:

offentlig klasse Slf4jLoggerFinder utvider System.LoggerFinder {@Override public System.Logger getLogger (String name, Module module) {return new Slf4jLogger (name); }}

3.2. Modulkonfigurasjon

Når vi har implementert alle klassene våre, la oss registrere tjenesten vår i modulen vår og legge til avhengigheten av SLF4J-modulen:

modul com.baeldung.logging.slf4j {krever org.slf4j; gir java.lang.System.LoggerFinder com.baeldung.logging.slf4j.Slf4jLoggerFinder; eksport com.baeldung.logging.slf4j; }

Denne modulen vil ha følgende struktur:

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

Nå kan vi kompilere denne modulen i mods katalog som vi gjorde i forrige avsnitt.

Legg merke til at vi må plassere slf4j-api jar i mods-katalogen for å kompilere denne modulen. Husk også å bruke en modularisert versjon av biblioteket. Den siste versjonen finner du i Maven Central.

3.3. Legger til tilbakekobling

Vi er nesten ferdige, men vi trenger fortsatt å legge til avhengigheter og konfigurasjon for tilbakekobling. For å gjøre det, plasser logback-classic og logback-core krukker i mods katalog.

Som før må vi sørge for at vi bruker en modulær versjon av biblioteket. Igjen, den siste versjonen finner du i Maven Central.

Til slutt, la oss lage en Logback-konfigurasjonsfil og plassere den i vår mods katalog:

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

3.4. Kjører applikasjonen vår

På dette punktet kan vi kjøre vår app ved hjelp av SLF4J-modulen vår.

I dette tilfellet, Vi må også spesifisere vår Logback-konfigurasjonsfil:

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

Til slutt, hvis vi sjekker utdataene, kan vi se at loggene våre skrives ut ved hjelp av vår Logback-konfigurasjon:

2018-08-25 14:02:40 [main] FEIL MainApp - feiltest 2018-08-25 14:02:40 [main] INFO MainApp - infotest

4. Konklusjon

Vi har vist i denne artikkelen hvordan du oppretter en tilpasset logger i Java 9 ved å bruke den nye Platform Logging API. Vi har også implementert et eksempel ved hjelp av et eksternt loggingsrammeverk, som er en av de mest nyttige brukssakene til denne nye API-en.

Som alltid er hele kildekoden til eksemplene tilgjengelig på GitHub.


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