Útmutató a visszalépéshez

1. Áttekintés

A visszacsatolás az egyik legszélesebb körben használt naplózási keretrendszer a Java közösségben. Ez az előd, a Log4j helyettesítője. A Logback gyorsabb megvalósítást kínál, mint a Log4j, több beállítási lehetőséget és nagyobb rugalmasságot kínál a régi naplófájlok archiválásában.

Ez a bevezetés bemutatja a Logback architektúráját, és megmutatja, hogyan használhatja az alkalmazások jobbá tételét.

2. Logback architektúra

Három osztály tartalmazza a Logback architektúrát; Logger, Appender, és Elrendezés.

A naplózó a naplóüzenetek kontextusa. Ez az osztály, amellyel az alkalmazások kölcsönhatásba lépnek naplóüzenetek létrehozásakor.

A függelékek naplóüzeneteket helyeznek el a végső rendeltetési helyen. Egy naplózónak egynél több Appenderje lehet. Általában úgy gondoljuk, hogy az Appenders szöveges fájlokhoz van csatolva, de a Visszacsatolás ennél sokkal hatásosabb.

Az Elrendezés előkészíti az üzeneteket a kiadáshoz. A visszalépés támogatja az üzenetek formázására szolgáló egyedi osztályok létrehozását, valamint a meglévők robusztus konfigurációs beállításait.

3. Beállítás

3.1. Maven-függőség

A Logback az egyszerű naplózási homlokzatot a Java-hoz (SLF4J) használja natív interfészként. Mielőtt elkezdenénk naplózni az üzeneteket, hozzá kell adnunk a Logback és az Slf4j fájljainkat pom.xml:

 ch.qos.logback logback-core 1.2.3 org.slf4j slf4j-api 1.7.30 teszt 

A Maven Central rendelkezik a Logback Core legújabb verziójával és a legújabb verzióval slf4j-api.

3.2. Osztályút

A visszalépéshez szintén szükség van logback-classic.jar futásidejű osztályúton.

Ezt hozzáadjuk ehhez pom.xml mint tesztfüggőség:

 ch.qos.logback logback-classic 1.2.3 

4. Alapvető példa és konfiguráció

Kezdjük egy gyors példával a Logback alkalmazás alkalmazásához.

Először is szükségünk van egy konfigurációs fájlra. Létrehozunk egy nevű szövegfájlt logback.xml és tedd valahova az osztályunkba:

   % d {HH: mm: ss.SSS} [% thread]% -5level% logger {36} -% msg% n 

Ezután szükségünk van egy egyszerű osztályra a-val fő- módszer:

public class példa {private static final Logger logger = LoggerFactory.getLogger (példa.osztály); public static void main (String [] args) {logger.info ("Példa napló innen: {}", Example.class.getSimpleName ()); }}

Ez az osztály létrehozza a Logger és felhív információ () naplóüzenet létrehozásához.

Amikor futunk Példa látjuk a konzolba bejelentkezett üzenetünket:

20: 34: 22.136 [main] INFO példa - Példa napló a példából

Könnyű felismerni, miért olyan népszerű a Logback; percek alatt futunk.

Ez a konfiguráció és kód néhány tippet ad a működéséről.

  1. Van egy appender nevezett STDOUT amely egy osztály nevére utal ConsoleAppender.
  2. Van egy minta, amely leírja a naplóüzenet formátumát.
  3. Kódunk létrehoz egy Logger és egy üzeneten keresztül továbbítottuk neki üzenetünket információ () módszer.

Most, hogy megértettük az alapokat, nézzük meg közelebbről.

5. Logger Összefüggések

5.1. Kontextus létrehozása

Egy üzenet naplózásához a Logback szolgáltatásba inicializáltuk a Logger az SLF4J vagy a Logback szolgáltatásból:

private static final Logger logger = LoggerFactory.getLogger (példa.osztály); 

És akkor használta:

logger.info ("Példa napló innen: {}", példa.osztály.getSimpleName ()); 

Ez a mi naplózási környezetünk. Amikor létrehoztuk, elhaladtunk LoggerFactory az óránk. Ez adja a Logger egy név (van egy túlterhelés is, amely elfogadja a Húr).

A naplózási összefüggések olyan hierarchiában léteznek, amely nagyon hasonlít a Java objektum-hierarchiára:

  1. A naplózó akkor ősi, ha a neve, amelyet egy pont követ, előtagja a leszármazott naplózó nevének
  2. A naplózó akkor szülő, ha nincs őse közte és egy gyermek között

Például a Példa osztály alatt van a com.baeldung.logback csomag. Van egy másik osztály neve PéldaAppender ban,-ben com.baeldung.logback.appenders csomag.

PéldaAppender naplója gyermeke A példa naplója.

Minden naplózó az előre definiált gyökér naplózó leszármazottja.

A Logger van egy Szint, amelyet konfigurációval vagy a gombbal lehet beállítani Logger.setLevel (). A kódban a szint beállítása felülbírálja a konfigurációs fájlokat.

A lehetséges szintek elsőbbségi sorrendben: NYOMON, HIBÁK, INFÓ, FIGYELEM és HIBA.Minden szinten van egy megfelelő módszer, amelyet egy üzenet naplózására használunk ezen a szinten.

Ha egy naplózóhoz nincs kifejezetten hozzárendelve egy szint, akkor a legközelebbi őse szintjét örökli. A gyökérnaplózó alapértelmezett értéke: HIBÁK. Az alábbiakban megtudjuk, hogyan lehet ezt felülbírálni.

5.2. Kontextus használata

Hozzunk létre egy példa programot, amely bemutatja a kontextus használatát a naplózási hierarchiákon belül:

ch.qos.logback.classic.Logger parentLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.logback"); parentLogger.setLevel (Level.INFO); Naplózó gyermeknapló = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.logback.tests"); parentLogger.warn ("Ez az üzenet naplózásra kerül, mert WARN> INFO."); parentLogger.debug ("Ez az üzenet nincs naplózva, mert DEBUG <INFO."); childlogger.info ("INFO == INFO"); childlogger.debug ("DEBUG <INFO"); 

Amikor ezt futtatjuk, a következő üzeneteket látjuk:

20: 31: 29.586 [main] WARN com.baeldung.logback - Ez az üzenet naplózásra kerül, mert WARN> INFO. 20: 31: 29.594 [main] INFO com.baeldung.logback.tests - INFO == INFO

Kezdjük a Logger nevezett com.baeldung.logback és leadta a ch.qos.logback.classic.Logger.

Logback kontextusra van szükség a szint beállításához a következő utasításban; vegye figyelembe, hogy az SLF4J absztrakt naplózója nem valósul meg setLevel ().

Kontextusunk szintjét arra állítottuk INFO;ezután létrehozunk egy másik naplózót, amelynek neve com.baeldung.logback.tests.

Minden üzenetkörnyezetben két üzenetet naplózunk, hogy bemutassuk a hierarchiát. A Logback naplózza a FIGYELMEZTET, és INFO üzeneteket, és kiszűri a HIBÁKüzenetek.

Most használjuk a gyökér naplózót:

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.logback"); logger.debug ("Sziasztok!"); Naplózó rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger (org.slf4j.Logger.ROOT_LOGGER_NAME); logger.debug ("Ez az üzenet naplózásra kerül, mert DEBUG == DEBUG."); rootLogger.setLevel (Level.ERROR); logger.warn ("Ez az üzenet nincs naplózva, mert WARN <ERROR."); logger.error ("Ez naplózva."); 

Ezeket az üzeneteket akkor látjuk, amikor végrehajtjuk ezt a részletet:

20: 44: 44.241 [main] DEBUG com.baeldung.logback - Sziasztok! 20: 44: 44.243 [main] DEBUG com.baeldung.logback - Ez az üzenet naplózásra kerül, mert DEBUG == DEBUG. 20: 44: 44.243 [main] ERROR com.baeldung.logback - Ezt naplózza. 

Befejezésül kezdtük a Logger kontextus és nyomtatott a HIBÁK üzenet.

Ezután lekérdeztük a gyökérnaplózót a statikusan meghatározott nevével, és a szintjét beállítottuk HIBA.

Végül bebizonyítottuk, hogy a Logback valójában minden állítást kiszűri, mint egy hiba.

5.3. Paraméterezett üzenetek

A fenti mintadarabkivonatok üzeneteivel ellentétben a leghasznosabb naplóüzenetekhez csatolni kellett Húrok. Ez magában foglalja a memória lefoglalását, az objektumok sorosítását, az összefűzést Húrok, és később a szemetet takaríthatják meg.

Vegye figyelembe a következő üzenetet:

log.debug ("Az aktuális szám" + szám); 

Az üzenet felépítésének költsége felmerül, függetlenül attól, hogy a Napló naplózza-e az üzenetet, vagy sem.

A Logback egy alternatívát kínál a paraméterezett üzeneteivel:

log.debug ("A jelenlegi szám {}", count); 

A zárójelek {} bármelyiket elfogadják Tárgy és használja annak toString () módszer az üzenet összeállításához, csak miután ellenőrizte, hogy szükséges-e a naplóüzenet.

Próbálkozzunk néhány különböző paraméterrel:

String message = "Ez egy karakterlánc"; Egész nulla = 0; próbáld meg a {logger.debug ("Naplózási üzenet: {}", üzenet); logger.debug ("Osztás {} osztva {} - val", 42, nulla); int eredmény = 42 / nulla; } catch (e Kivétel) {logger.error ("Hiba történt a (z) {} osztásával {} -kal", 42, nulla, e); } 

Ez a kódrészlet:

21: 32: 10.311 [main] DEBUG com.baeldung.logback.LogbackTests - Naplózási üzenet: Ez egy String 21: 32: 10.316 [main] DEBUG com.baeldung.logback.LogbackTests - 42 megosztása 0-val 21:32 : 10.316 [main] ERROR com.baeldung.logback.LogbackTests - Hiba történt a 42-nek 0-val való elosztása esetén java.lang.ArithmeticException: / nullával a com.baeldung.logback.LogbackTests.givenParameters_ValuesLogged (LogbackTests.java:64) ... 

Látjuk, hogy a Húr, an int, és egy Egész szám paraméterként adhatók be.

Továbbá, amikor egy Kivétel kerül átadásra, mint utolsó argumentum egy naplózási módszerre, a Logback kinyomtatja nekünk a verem nyomát.

6. Részletes konfiguráció

Az előző példákban a 4. szakaszban létrehozott 11 soros konfigurációs fájlt használtuk naplóüzenetek nyomtatásához a konzolra. Ez a Logback alapértelmezett viselkedése; ha nem talál konfigurációs fájlt, létrehoz egy ConsoleAppender és társítja a gyökérnaplózóval.

6.1. Konfigurációs információk megkeresése

Egy konfigurációs fájl elhelyezhető az osztályúton és megnevezhető logback.xml vagy logback-test.xml.

A Logback megpróbálja megkeresni a konfigurációs adatokat:

  1. Megnevezett fájlok keresése logback-test.xml, logback.groovy,vagy logback.xml az osztályúton, ebben a sorrendben.
  2. Ha a könyvtár nem találja meg ezeket a fájlokat, akkor megpróbálja használni a Java fájlokat ServiceLoader hogy megtalálják a com.qos.logback.classic.spi.Configurator.
  3. Konfigurálja magát, hogy a kimenetet közvetlenül a konzolra naplózza

Megjegyzés: a Logback jelenlegi verziója nem támogatja a Groovy konfigurációt, mivel nincs a Groovy Java 9 kompatibilis verziója.

6.2. Alapkonfiguráció

Vizsgáljuk meg közelebbről a konfigurációs példánkat.

A teljes fájl benne van címkék.

Látunk egy címkét, amely egy Appender típusú ConsoleAppender, és megnevezi STDOUT. A címkén belül van egy kódoló. Mintája van annak, ami kinéz sprintf-stílusú menekülési kódok:

  % d {HH: mm: ss.SSS} [% thread]% -5level% logger {36} -% msg% n 

Utoljára látjuk a gyökér címke. Ez a címke a gyökér naplózót állítja be HIBÁK módot, és a kimenetét a Appender nevezett STDOUT:

6.3. A konfiguráció hibaelhárítása

A bejelentkezési konfigurációs fájlok bonyolulttá válhatnak, ezért számos beépített mechanizmus létezik a hibaelhárításhoz.

A hibakeresési információk megtekintéséhez, amikor a Visszalépés feldolgozza a konfigurációt, bekapcsolhatja a hibakeresési naplózást:

 ... 

A Logback a konfiguráció feldolgozása közben kinyomtatja az állapotinformációkat a konzolra:

23: 54: 23,040 | -INFO a ch.qos.logback.classic.LoggerContext [alapértelmezett] - Talált erőforrás [logback-test.xml] itt: [file: / Users / egoebelbecker / ideaProjects / logback-guide / out / test / resources / logback-test.xml] 23: 54: 23,230 | -INFO a ch.qos.logback.core.joran.action.AppenderAction fájlban - A [ch.qos.logback.core.ConsoleAppender] 23 típusú appender példányosítása: 54: 23,236 | -INFO a ch.qos.logback.core.joran.action.AppenderAction fájlban - Az alkalmazás neve [STDOUT] néven 23: 54: 23,247 | -INFO a ch.qos.logback.core.joran.action.NestedComplexPropertyIA fájlban Feltételezve az alapértelmezett típust [ch.qos.logback.classic.encoder.PatternLayoutEncoder] a [kódoló] tulajdonsághoz 23: 54: 23,308 | -INFO a ch.qos.logback.classic.joran.action.RootLoggerAction - A ROOT logger szintjének beállítása DEBUG 23: 54: 23,309 | -INFO a ch.qos.logback.core.joran.action.AppenderRefAction fájlban - [STDOUT] nevű alkalmazás hozzáfűzése a Naplózóhoz [ROOT] 23: 54: 23,310 | -INFO a ch.qos.logback fájlban. classic.joran.action.ConfigurationAction - A konfiguráció vége. 23: 54: 23,313 | -INFO in [email protected] - Az aktuális konfiguráció regisztrálása biztonságos tartalékpontként

Ha figyelmeztetések vagy hibák lépnek fel a konfigurációs fájl elemzése során, a Logback állapotüzeneteket ír a konzolra.

Van egy második mechanizmus az állapotinformációk kinyomtatására:

  ... 

A StatusListener elfogja az állapotüzeneteket és kinyomtatja őket a konfigurálás során és a program futása közben.

Az összes konfigurációs fájl kimenete kinyomtatásra kerül, ami hasznos lehet a „gazember” konfigurációs fájlok felkutatásához az osztályúton.

6.4. A konfiguráció újratöltése automatikusan

A naplózási konfiguráció újratöltése egy alkalmazás futása közben hatékony hibaelhárító eszköz. A visszalépés lehetővé teszi ezt a letapogatás paraméter:

 ... 

Az alapértelmezett viselkedés a konfigurációs fájl 60 másodpercenként történő változásainak átvizsgálása. Módosítsa ezt az intervallumot hozzáadással scanPeriod:

 ... 

Megadhatjuk az értékeket ezredmásodpercekben, másodpercekben, percekben vagy órákban.

6.5. Módosítása Fakitermelők

A fenti mintafájlunkban beállítottuk a gyökérnaplózó szintjét, és társítottuk a konzolhoz Appender.

Bármely naplózónak beállíthatjuk a szintet:

   % d {HH: mm: ss.SSS} [% thread]% -5level% logger {36} -% msg% n 

Vegyük fel ezt az osztályútvonalunkba, és futtassuk ezt a kódot:

Logger foobar = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.foobar"); Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.logback"); Naplózó tesztlogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger ("com.baeldung.logback.tests"); foobar.debug ("Ezt a foobar naplózza"); logger.debug ("Ezt nem a naplózó naplózza"); logger.info ("Ezt a naplózó naplózza"); testslogger.info ("Ezt nem a tesztek naplózták"); testslogger.warn ("Ezt a tesztek naplózzák"); 

Látjuk ezt a kimenetet:

00: 29: 51.787 [main] DEBUG com.baeldung.foobar - Ezt naplózza a foobar 00: 29: 51.789 [main] INFO com.baeldung.logback - Ezt naplózza a 00: 29: 51.789 [main] WARN com .baeldung.logback.tests - Ezt a tesztek naplózzák 

Ha a naplózók szintjét nem állítja be programszerűen, akkor a konfiguráció beállítja őket; com.baeldung.foobar örököl HIBÁK a gyökérnaplóból.

Fakitermelőkörökölni is a appender-ref a gyökérnaplóból. Amint alább láthatjuk, felülírhatjuk ezt.

6.6. Változó helyettesítés

A bejelentkezési konfigurációs fájlok támogatják a változókat. A változókat a konfigurációs szkripten belül vagy kívül definiáljuk. Egy változó a konfigurációs szkript bármely pontján megadható egy érték helyett.

Például itt van az a konfigurációja FileAppender:

  $ {LOG_DIR} /tests.log true% -4relative [% thread]% -5level% logger {35} -% msg% n 

A konfiguráció tetején kijelentettük a ingatlannevezett LOG_DIR.Ezután a fájlon belüli fájl elérési útjának részeként használtuk appender meghatározás.

A tulajdonságokat a tag a konfigurációs szkriptekben. De elérhetők külső forrásokból is, például a rendszer tulajdonságaiból. Kihagyhatnánk a ingatlan deklarációt ebben a példában, és állítsa be a LOG_DIR a parancssorban:

$ java -DLOG_DIR = / var / log / alkalmazás com.baeldung.logback.LogbackTests

A tulajdonság értékét a $ {propertyname}. A Logback a változókat szövegpótlásként valósítja meg. Változó helyettesítés a konfigurációs fájl bármely pontján előfordulhat, ahol megadható egy érték.

7. Függelékek

Fakitermelők passz LoggingEvents nak nek Függelékek.Függelékek végezze el a fakitermelés tényleges munkáját. Általában a naplózásra úgy gondolunk, mint valami fájlra vagy konzolra, de a Logback sokkal többre képes. Logback-core számos hasznos függeléket nyújt.

7.1. ConsoleAppender

Láttuk ConsoleAppendermár cselekvésben. Neve ellenére ConsoleAppender üzeneteket fűz a System.outvagy System.err.

Használ egy OutputStreamWriter pufferelni az I / O-t, így irányítva System.err nem eredményez ki nem írt írást.

7.2. FileAppender

FileAppenderüzeneteket fűz egy fájlhoz. A konfigurációs paraméterek széles skáláját támogatja. Vegyünk fel egy fájl-kiegészítőt az alapvető konfigurációnkba:

    % d {HH: mm: ss.SSS} [% thread]% -5level% logger {36} -% msg% n tests.log true% -4relative [% thread]% -5level% logger {35} -% msg % n 

A FileAppender fájlnévvel van konfigurálva a következőn keresztül: . A tag utasítja a Appendercsonkolás helyett egy meglévő fájlhoz csatolni. Ha többször futtatjuk a tesztet, akkor azt látjuk, hogy a naplózási kimenet ugyanahhoz a fájlhoz van csatolva.

Ha felülről futtatjuk újra a tesztünket, akkor a com.baeldung.logback.tests keresse fel a konzolt és a tests.log nevű fájlt. A leszármazott naplózó örökli a gyökér napló társulását a ConsoleAppender -val való társulásával FileAppender. A függelékek kumulatívak.

Ezt a viselkedést felülírhatjuk:

Beállítás additivitás nak nek hamisletiltja az alapértelmezett viselkedést. Tesztek nem fog bejelentkezni a konzolra, és egyik utódja sem.

7.3. RollingFileAppender

Gyakran a naplóüzenetek hozzáfűzése ugyanahhoz a fájlhoz nem szükséges. Azt akarjuk, hogy a fájlok az idő, a naplófájl mérete vagy mindkettő kombinációja alapján gördüljenek.

Ehhez megvan RollingFileAppender:

  $ {LOG_FILE} .log $ {LOG_FILE}.% D {yyyy-MM-dd} .gz 30 3GB% -4relative [% thread]% -5level% logger {35} -% msg% n 

A RollingFileAppendervan egy RollingPolicy.Ebben a mintakonfigurációban a TimeBasedRollingPolicy.

Hasonló a FileAppender, fájlnévvel konfiguráltuk ezt az alkalmazót. Bejelentettünk egy tulajdonságot, és erre használtuk, mert az alábbi fájlnevet újra felhasználjuk.

Meghatározzuk a fileNamePattern benne RollingPolicy.Ez a minta nem csak a fájlok nevét határozza meg, hanem azt is, hogy milyen gyakran tekerje őket. TimeBasedRollingPolicymegvizsgálja a mintát és a legpontosabban meghatározott időszakban gördül.

Például:

   $ {LOG_DIR} / $ {LOG_FILE} .log $ {LOG_DIR} /% d {éééé / MM} / $ {LOG_FILE} .gz 3 GB 

Az aktív naplófájl / var / logs / application / LogFile.Ez a fájl minden hónap elején átkerül / Aktuális év / Aktuális hónap / LogFile.gzés RollingFileAppender teremtegy új aktív fájl.

Amikor az archivált fájlok teljes mérete eléri a 3 GB-ot, RollingFileAppenderaz archívumokat az első az elsőben ki alapján törli.

Vannak kódok egy hétre, órára, percre, másodpercre, sőt milliszekundumra. A visszalépésnek itt van egy hivatkozása.

RollingFileAppenderbeépített támogatással rendelkezik a fájlok tömörítésére is. A tömörített fájljainkat tömöríti, mert elnevezte őket LogFile.gz.

TimeBasedPolicynem az egyetlen lehetőség a fájlok gördítésére. A Logback is kínál SizeAndTimeBasedRollingPolicy,amely az aktuális naplófájl méret és az idő alapján gördülni fog. Azt is kínálja a FixedWindowRollingPolicyamely a naplófájlok nevét görgeti a naplózó minden indításakor.

A sajátunkat is megírhatjuk RollingPolicy.

7.4. Egyéni függelékek

Létrehozhatunk egyedi függelékeket a Logback egyik alap appender osztályának kibővítésével. Itt van egy oktatóanyag az egyedi függelékek létrehozásához.

8. Elrendezések

Elrendezések formázza a naplóüzeneteket. A Logback többi részéhez hasonlóan Elrendezésekkiterjeszthetők, és létrehozhatjuk a sajátunkat. Azonban az alapértelmezett PatternLayout felajánlja, amire a legtöbb alkalmazásnak szüksége van, majd néhányat.

Használtuk PatternLayout eddigi összes példánkban:

 % d {HH: mm: ss.SSS} [% thread]% -5level% logger {36} -% msg% n 

Ez a konfigurációs szkript tartalmazza a PatternLayoutEncoder.Elhaladunk egy Encoder a miénknek Appender,és ez a kódoló a PatternLayout az üzenetek formázásához.

A szöveg a tag meghatározza a naplóüzenetek formázását. PatternLayout sokféle konverziós szót és formátum-módosítót hajt végre minták létrehozásához.

Ezt bontsuk le. PatternLayout % -kal ismeri fel a konverziós szavakat, így a mintánkban szereplő konverziók a következőket generálják:

  • % d {HH: mm: ss.SSS} - időbélyeg órákkal, percekkel, másodpercekkel és ezredmásodpercekkel
  • [%cérna] - a naplóüzenetet létrehozó szál neve szögletes zárójelben
  • % -5szint - a naplózási esemény szintje, 5 karakterre kitöltve
  • % naplózó {36} - a naplózó neve, 35 karakterre csonkítva
  • % msg% n - a naplóüzenetek, amelyeket a platformfüggő sorelválasztó karakter követ

Tehát ehhez hasonló üzeneteket látunk:

21: 32: 10.311 [main] DEBUG com.baeldung.logback.LogbackTests - Naplózási üzenet: Ez egy karakterlánc

A konverziós szavak és a formátum-módosítók teljes listája itt található.

9. Következtetés

Ebben a kiterjedt útmutatóban a Logback alkalmazás alkalmazásának alapjait ismertettük.

Megvizsgáltuk a Logback architektúrájának három fő összetevőjét: naplózókat, függelékeket és elrendezést. A Logback's erőteljes konfigurációs szkriptekkel rendelkezik, amelyeket az összetevők manipulálására használtunk az üzenetek szűrésére és formázására. Megnéztük a naplófájlok létrehozásához, átgörgetéséhez, rendszerezéséhez és tömörítéséhez a két leggyakrabban használt fájlmellékletet is.

Szokás szerint a kódrészletek megtalálhatók a GitHubon.


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