API voor logboekregistratie van Java 9 Platform

1. Inleiding

In deze zelfstudie verkennen we de nieuw geïntroduceerde Logging API in Java 9 en implementeren we enkele voorbeelden om de meest voorkomende gevallen te behandelen.

Deze API is in Java geïntroduceerd voor een gemeenschappelijk mechanisme bieden om alle platformlogboeken te verwerken en een service-interface bloot te leggen die kan worden aangepast door bibliotheken en toepassingen. Op deze manier kunnen de JDK-platformlogboeken hetzelfde logging-framework gebruiken als de applicatie, en kunnen de projectafhankelijkheden worden verminderd.

2. Een aangepaste implementatie maken

In deze sectie gaan we de hoofdklassen van de Logging API laten zien die we moeten implementeren om een ​​nieuwe logger te maken. We doen dit door een eenvoudige logger te implementeren die alle logboeken naar de console afdrukt.

2.1. Het creëren van het Logger

De belangrijkste klasse die we moeten maken, is de Logger. Deze klasse moet het System.Logger interface en tenminste deze vier methoden:

  • getName (): geeft de naam van de logger terug. Het wordt door de JDK gebruikt om loggers op naam te maken
  • isLoggable (): geeft aan voor welke niveaus de logger is ingeschakeld
  • logboek (): het is de methode die het logboek afdrukt naar het onderliggende systeem dat de toepassing gebruikt - in ons geval de console. Er zijn er 2 logboek () methoden om te implementeren, die elk verschillende parameters ontvangen

Laten we eens kijken hoe onze implementatie eruit zal zien:

openbare klasse ConsoleLogger implementeert System.Logger {@Override public String getName () {retourneer "ConsoleLogger"; } @Override public boolean isLoggable (Level level) {return true; } @Override openbaar ongeldig logboek (Level-niveau, ResourceBundle-bundel, String-bericht, Throwable gegooid) {System.out.printf ("ConsoleLogger [% s]:% s -% s% n", level, msg, gegooid); } @Override public void log (Level level, ResourceBundle bundle, String format, Object ... params) {System.out.printf ("ConsoleLogger [% s]:% s% n", level, MessageFormat.format (format, params)); }}

Onze ConsoleLogger class overschrijft de vier genoemde methoden. De getName () methode retourneert een Draad, Terwijl de isLoggable () methode retourneert waar in alle gevallen. Eindelijk hebben we de 2 logboek () methode die naar de console wordt uitgevoerd.

2.2. Het creëren van het LoggerFinder

Zodra we onze logger hebben gemaakt, we moeten een LoggerFinder dat creëert voorbeelden van onze ConsoleLogger.

Om dit te doen, moeten we de abstracte klasse uitbreiden System.LoggerFinder en implementeer het getLogger () methode:

public class CustomLoggerFinder breidt System.LoggerFinder uit {@Override public System.Logger getLogger (String naam, Module module) {return new ConsoleLogger (); }}

In dit geval retourneren we altijd onze ConsoleLogger.

Ten slotte moeten we onze LoggerFinder as a Service, zodat het kan worden ontdekt door de JDK. Als we geen implementatie bieden, is het SimpleConsoleLogger wordt standaard gebruikt.

Het mechanisme dat door de JDK wordt gebruikt om de implementaties te laden, is het ServiceLoader. In deze tutorial vind je er meer informatie over.

Omdat we Java 9 gebruiken, verpakken we onze klas in een module en registreren we onze service in het module-info.java het dossier:

module com.baeldung.logging {voorziet java.lang.System.LoggerFinder met com.baeldung.logging.CustomLoggerFinder; exporteert com.baeldung.logging; }

Bekijk deze andere tutorial voor meer informatie over Java-modules.

2.3. Ons voorbeeld testen

Laten we, om ons voorbeeld te testen, een andere module maken die als een applicatie zal fungeren. Dit bevat alleen de Hoofd klasse die onze service-implementatie gebruikt.

Deze klasse krijgt een exemplaar van ons ConsoleLogger door het System.getLogger () methode:

openbare klasse MainApp {privé statisch System.Logger LOGGER = System.getLogger ("MainApp"); public static void main (String [] args) {LOGGER.log (Level.ERROR, "fouttest"); LOGGER.log (Level.INFO, "info test"); }}

Intern zal de JDK onze ophalen CustomLoggerFinder implementatie en maak een instantie van onze ConsoleLogger.

Laten we daarna het module-info bestand voor deze module:

module com.baeldung.logging.app {}

Op dit punt ziet onze projectstructuur er als volgt uit:

├── src │ ├── modules │ │ ├── com.baeldung.logging │ │ │ ├── com │ │ │ │ └── baeldung │ │ │ │ └── loggen │ │ │ │ ├── ConsoleLogger .java │ │ │ │ └── CustomLoggerFinder.java │ │ │ └── module-info.java │ │ ├── com.baeldung.logging.app │ │ │ ├── com │ │ │ │ └── baeldung │ │ │ │ └── logboekregistratie │ │ │ │ └── app │ │ │ │ └── MainApp.java │ │ │ └── module-info.java └──

Ten slotte gaan we onze twee modules compileren en plaatsen we ze in een mods directory:

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

Laten we tot slot het Hoofd klasse van de app module:

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

Als we de uitvoer van de console bekijken, kunnen we zien dat onze logboeken worden afgedrukt met onze ConsoleLogger:

ConsoleLogger [ERROR]: fouttest ConsoleLogger [INFO]: info-test

3. Een extern framework voor logboekregistratie toevoegen

In ons vorige voorbeeld waren we al onze berichten aan het loggen op de console, wat hetzelfde is als wat de standaard logger doet. Een van de handigste toepassingen van de Logging API in Java 9 is om applicaties de JDK-logboeken te laten doorsturen naar hetzelfde logging-framework dat de applicatie gebruikt, en dat is wat we gaan doen in deze sectie.

We zullen een nieuwe module maken die SLF4J gebruikt als logging-façade en Logback als logging-framework.

Omdat we de basis in de vorige sectie al hebben uitgelegd, kunnen we ons nu concentreren op het toevoegen van een extern logging-framework.

3.1. Aangepaste implementaties met SLF4J

Eerst implementeren we een andere Logger die voor elke instantie een nieuwe SLF4J-logger zal maken:

openbare klasse Slf4jLogger implementeert System.Logger {private final String naam; privé-eindlogger-logger; openbare Slf4jLogger (String naam) {this.name = naam; logger = LoggerFactory.getLogger (naam); } @Override public String getName () {return naam; } // ...}

Merk op dat dit Logger is een org.slf4j.Logger.

Voor de rest van de methoden, we vertrouwen op de implementatie op de SLF4J-loggerinstantie. Daarom onze Logger wordt ingeschakeld als de SLF4J-logger is ingeschakeld:

@Override public boolean isLoggable (Level level) {switch (level) {case OFF: return false; geval TRACE: retourneer logger.isTraceEnabled (); case DEBUG: return logger.isDebugEnabled (); case INFO: return logger.isInfoEnabled (); case WAARSCHUWING: retourneer logger.isWarnEnabled (); case ERROR: retourneer logger.isErrorEnabled (); case ALL: default: return true; }}

En de logboekmethoden roepen de juiste SLF4J-loggermethode aan, afhankelijk van het gebruikte logniveau:

@Override public void log (Level level, ResourceBundle bundle, String msg, Throwable throw) {if (! IsLoggable (level)) {return; } schakelaar (niveau) {geval TRACE: logger.trace (msg, gegooid); breken; case DEBUG: logger.debug (msg, gegooid); breken; case INFO: logger.info (msg, gegooid); breken; case WAARSCHUWING: logger.warn (msg, gegooid); breken; case ERROR: logger.error (msg, gegooid); breken; case ALL: default: logger.info (msg, gegooid); }} @Override public void log (Level level, ResourceBundle bundle, String format, Object ... params) {if (! IsLoggable (level)) {return; } String message = MessageFormat.format (formaat, params); switch (niveau) {case TRACE: logger.trace (bericht); breken; // ... // hetzelfde als de vorige schakelaar}}

Laten we tot slot een nieuw LoggerFinder die onze Slf4jLogger:

publieke klasse Slf4jLoggerFinder breidt System.LoggerFinder uit {@Override public System.Logger getLogger (String naam, Module module) {retourneer nieuwe Slf4jLogger (naam); }}

3.2. Module configuratie

Zodra we al onze klassen hebben geïmplementeerd, laten we onze service in onze module registreren en de afhankelijkheid van de SLF4J-module toevoegen:

module com.baeldung.logging.slf4j {vereist org.slf4j; biedt java.lang.System.LoggerFinder met com.baeldung.logging.slf4j.Slf4jLoggerFinder; exporteert com.baeldung.logging.slf4j; }

Deze module heeft de volgende structuur:

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

Nu kunnen we deze module compileren in het mods directory zoals we deden in de vorige sectie.

Merk op dat we de slf4j-api-jar in de mods-directory moeten plaatsen om deze module te compileren. Denk er ook aan om een ​​modulaire versie van de bibliotheek te gebruiken. De nieuwste versie is te vinden in Maven Central.

3.3. Logback toevoegen

We zijn bijna klaar, maar we moeten nog steeds de Logback-afhankelijkheden en configuratie toevoegen. Plaats hiervoor het logback-classic en logback-core potten in de mods directory.

Net als voorheen moeten we ervoor zorgen dat we een modulaire versie van de bibliotheek gebruiken. Nogmaals, de nieuwste versie is te vinden in Maven Central.

Laten we tot slot een Logback-configuratiebestand maken en dit in ons mods directory:

    % d {jjjj-MM-dd UU: mm: ss} [% thread]% -5level% logger {36} -% msg% n 

3.4. Onze applicatie uitvoeren

Op dit punt kunnen we onze app met behulp van onze SLF4J-module.

In dit geval, we moeten ook ons ​​Logback-configuratiebestand specificeren:

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

Als we ten slotte de uitvoer controleren, kunnen we zien dat onze logboeken worden afgedrukt met behulp van onze Logback-configuratie:

2018-08-25 14:02:40 [main] ERROR MainApp - fouttest 2018-08-25 14:02:40 [main] INFO MainApp - info test

4. Conclusie

We hebben in dit artikel laten zien hoe u een aangepaste logger in Java 9 kunt maken met behulp van de nieuwe Platform Logging API. We hebben ook een voorbeeld geïmplementeerd met behulp van een extern logboekregistratieframework, wat een van de handigste use-cases is van deze nieuwe API.

Zoals altijd is de volledige broncode van de voorbeelden beschikbaar op GitHub.