*   >> Læs Uddannelse artikler >> science >> programming

Java: Hvordan til at omdirigere stderr Og stdout til Commons Logging, med den opkaldende Class

Mange gange finder vi, at 3. parts biblioteker vil skrive til System.out eller System.err. Det skal nok være lettere at omdirigere disse til fælles skovhugst rammer, men det er ikke.

Nedenfor finder du en klasse, som du kan bruge til at opnå netop dette. Klassen er en instans af PrintWriter og kan instantieres og bruges som System.out og System.err PrintWriter. Det vil omdirigere alle stdout og stderr beskeder til Commons Logging. Det vil også se op den kaldende klasse og få en logger under navnet: com.domain.

Class (eventuelt med et brugerdefineret præfiks eller suffiks såsom: STDOUT.com.domain.Class eller com.domain.Class.STDOUT)

For at lette brugen kan du bruge de statiske fabrikken metoder, som automatisk registrerer klasse på STDOUT eller STDERR hhv. Nedenfor er et par typiske brug eksempler

Et par noter om, hvordan det fungerer:

  • PrintWriter er tilsidesættes, hver gang en metode kaldes den kaldende klasse så op og indspillede ( metoder er synkroniseret som de er i PrintWriter.


  • Når en flush () kaldes, eller PrintWriter auto flush træk skyller bufferen er hver enkelt String skrevet til Commons Logning. PrintWriter flush () 's efter en fuld linie udskrives, en ny linje er stødt på, eller en byte array er skrevet.

  • kaldende metode opnås ved at analysere StackTrace. For at dette skal fungere, skal denne handling sker umiddelbart efter et kald til enhver PrintWriter metode.


  • De medfølgende javadocs forklarer fleste funktioner

    Anvendelse eksempel: I starten af ​​din ansøgning:

    public static void vigtigste (String [] args) {CommonsLoggingPrintStream.registerOnStdout (null "STDOUT") CommonsLoggingPrintStream.registerOnStderr (null, "STDERR") //...}

    Anvendelse eksempel: I foråret (tilføje følgende til din opstart sammenhæng bruger fabrikken metoder, så ingen kode er nødvendig) :

    STDOUTSTDERR

    Klasse kode (Bemærk: du kan frit ændre pakken /classname, bliver de brugt i koden for at anaylize stakken spor, men de er så op dynamisk)

    pakke mycommons.

    logging, import java.io.ByteArrayOutputStream, import java.io.IOException, import java.io.PrintStream, import java.util.Locale, import java.util.concurrent.locks.ReentrantLock, import org.apache.commons.logging.LogFactory; /** * Denne klasse re-dirigerer alle anmodninger til PrintStream (bruges af STDOUT og STDERR) * og sender dem til Commons Logning. * * Den kaldende metode til PrintStream bestemmes ved at analysere staksporingen.

    * * Brug convenience metoder registerOnStdout og registerOnStderr til automatisk * oprette en instans af denne klasse og registrere den på strømmen til at omdirigere til * Commons skovhugst. * * Eksempel på typisk brug: * * * public static void vigtigste (String [] args) {* CommonsLoggingPrintStream.registerOnStdout (null, "STDOUT"); * CommonsLoggingPrintStream.registerOnStderr (null, "STDERR"); * //... *} * * * Note til de særling tilfælde: Hvis du foretager flere opkald til metoder, som ikke udløser * en flush, som forklaret i PrintWriter (f.

    eks append (char)) den kaldende metode * vil blive bestemt kun af den sidste indkaldelse, der udløser en flush eller kalder flush () direkte. også bemærke, at * i dette tilfælde skal du synkronisere adgang til disse metoder, da de ikke vil blive tråd sikker. * Det er generelt tilrådes at kun opkald metoder, der genererer en automatisk flush som beskrevet * i PrintWriter javadocs * /public class CommonsLoggingPrintStream strækker PrintStream {LoggingOutputStream OutputStream; privat ReentrantLock lås = ny ReentrantLock (); /** * Du kan bruge en ny instans til at logge alle PrintStream metoder til Commons Logging.

    * Meddelelser vil blive skrevet til CommonsLogging når flush () kaldes med * de samme regler som PrintStream bruger med autoFlush = true * * @ param prependName Et navn tilføjes i begyndelsen af ​​klassen (null for ingen) navn som i: registerOnStdout ("STDOUT" , null) resulterer i en log besked som: INFO STDOUT.org.mydomain.MyClass - Log besked * @ param postpendName Et navn postpended til klassen (null for ingen) navn som i: registerOnStdout (null, "stdout") resultater i en log besked såsom: INFO org.mydomain.MyClass.

    STDOUT -log besked * /public CommonsLoggingPrintStream (String prependName, String postpendName) {dette (ny LoggingOutputStream (prependName, postpendName, CommonsLoggingPrintStream.class.getCanonicalName ())); } Private CommonsLoggingPrintStream (LoggingOutputStream los) {super (los, true); this.outputStream = los; } /** * Convenience metode - Opretter en ny instans af * CommonsLoggingPrintStream og registrerer det på STDOUT * * @ param prependName Et navn tilføjes i begyndelsen af ​​klassen (null for ingen) navn som i: registerOnStdout ("stdout", null) resulterer i en log besked såsom: INFO STDOUT.

    org.mydomain.MyClass - Log besked * @ param postpendName Et navn postpended til klassen (null for ingen) navn som i: registerOnStdout (null, "STDOUT") resulterer i en log besked sådan som: INFO org.mydomain.MyClass.STDOUT -log besked *return en reference til CommonsLoggingPrintStream objekt oprettet, kan ignoreres i de fleste situationer * /public static CommonsLoggingPrintStream registerOnStdout (String prependName, String postpendName) {CommonsLoggingPrintStream ref = ny CommonsLoggingPrintStream ( prependName, postpendName); System.

    setOut (ref); returnere ref; } /** * Convenience metode - Opretter en ny instans af * CommonsLoggingPrintStream og registrerer det på STDERR * * @ param prependName Et navn tilføjes i begyndelsen af ​​klassen (null for ingen) navn som i: registerOnStdout ("STDERR", null) resulterer i en log besked såsom: INFO STDERR.org.mydomain.MyClass - Log besked * @ param postpendName Et navn postpended til klassen (null for ingen) navn som i: registerOnStdout (null, "STDERR") resulterer i en log besked sådan som: INFO org.mydomain.MyClass.

    STDERR -log besked *return en reference til CommonsLoggingPrintStream objekt oprettet, kan ignoreres i de fleste situationer * /public static CommonsLoggingPrintStream registerOnStderr (String prependName, String postpendName) {CommonsLoggingPrintStream ref = ny CommonsLoggingPrintStream ( prependName, postpendName); System.setErr (ref); returnere ref; } /** * Denne klasse er nødvendig for at gøre brug af PrintWriters garanterer * at flush vil blive kaldt på et passende tidspunkt. Vi sender data til * Commons Loggging først efter flush () kaldes den indpakkede output * stream af PrintWriter.

    * * /Privat statisk klasse LoggingOutputStream udvider ByteArrayOutputStream {private String currentCallerName; prependName = null private String; postpendName = null private String; privat String outerClassName = null; //Dette er dynamisk genereret, så ændringer i pakken eller klasse navn ikke påvirker funktionaliteten offentlige LoggingOutputStream (String prependName, String postpendName, String outerClassName) {this.prependName = (prependName! = Null &&! PrependName.isEmpty ()) ? prependName + "." : ""; = (= null postpendName! &&! postpendName.isEmpty ()) this.postpendName? ".

    " + PostpendName: ""; this.outerClassName = outerClassName; }Override Public void flush () kaster IOException {super.flush (); //Log resulterende bytes efter flush () kaldes. Vi kan stole på dette, fordi //vi skabt PrintStream med autoFlush indstillingen slået til. //Hvis en byte array skrevet det kan indeholde flere linjer String [] logMessages = this.toString () split ("\\ n").; for (String besked: logMessages) {LogFactory.getLog (currentCallerName) .info (message.trim ()); }} Void setNameOfCaller () {boolean reachedCallToOutterClass = false; StackTraceElement [] stabel = Thread.

    currentThread () getStackTrace (.); //Loop gennem stakken sporstoffer, indtil vi finder "java.io.PrintStream" //og returnere den første fuldt kvalificerede klasse-navn efter de opkald til PrintStream for (StackTraceElement e: stack) {if (e.getClassName () .equals (outerClassName)) {reachedCallToOutterClass = true; fortsætte; } else if (reachedCallToOutterClass) {this.currentCallerName = prependName + e.getClassName () + postpendName; tilbage; }} This.currentCallerName = "unknown.classname"; //Unreachable kode (eller så teorien holder)}} /** * Passes opkaldet videre til outputStream.

    setNameOfCaller () kun * hvis den synkroniserede lås på dette er ejet én gang. Hvis det * ejede mere end en gang, så er dette et tilbagekald indefra * PrintWriter, en situation, som vil gøre det vanskeligt /umuligt * at bestemme den kaldende metode, og er ikke nødvendigt, da * det første opkald til setNameOfCaller () er alle, der var * er nødvendig for at bestemme den kaldende metode. * /Private void setNameOfCaller (ReentrantLock lås) {if (lock.getHoldCount ()>

    Page   <<       [1] [2] [3] [4] [5] [6] >>
  • Copyright © 2008 - 2016 Læs Uddannelse artikler,https://uddannelse.nmjjxx.com All rights reserved.