*   >> Lecture Éducation Articles >> science >> la programmation

Java: Comment rediriger stderr et stdout Commons Logging à, de la convocation Class

Plusieurs fois, nous constatons que les bibliothèques 3rd Party devront écrire au System.out ou System.err. Il devrait probablement être plus facile de re-diriger ces cadres à forestières communes, mais il est pas.

Ci-dessous vous trouverez une classe que vous pouvez utiliser pour accomplir exactement cela. La classe est une instance de PrintWriter et peut être instancié et utilisé comme System.out et System.err PrintWriter. Il va rediriger tous les messages stdout et stderr communes de log.

Il se penchera également sur la classe d'appel et obtenir un enregistreur sous le nom: com.domain.Class (éventuellement avec un préfixe ou un suffixe défini par l'utilisateur tels que: STDOUT.com.domain.Class ou com.domain.Class.STDOUT)

Pour la facilité d'utilisation, vous pouvez utiliser les méthodes de fabrique statiques qui enregistrent automatiquement la classe sur STDOUT ou STDERR respectivement.

Voici quelques exemples typiques d'utilisation

Quelques notes sur la façon dont cela fonctionne:

  • PrintWriter est remplacée, chaque fois qu'une méthode est appelée la classe d'appel est recherché et enregistré ( méthodes sont synchronisés car ils sont dans PrintWriter.

  • Quand un flush () est appelée, ou auto fonction ras de PrintWriter vide le tampon, chaque corde est écrit communes de log. PrintWriter flush () d 'après une pleine ligne est imprimée, une nouvelle ligne est rencontrée, ou un tableau d'octets est écrit.


  • La méthode d'appel est obtenue par l'analyse de la StackTrace. Pour que cela fonctionne, cette action doit se produire immédiatement après un appel à toute méthode PrintWriter.

  • Les javadocs inclus expliquent la plupart des fonctionnalités

    Exemple d'utilisation: Au début de votre application:

    static void main (String [] args) {CommonsLoggingPrintStream.registerOnStdout publics (null , "STDOUT"); CommonsLoggingPrintStream.registerOnStderr (null, "STDERR"); //...

    }

    Exemple d'utilisation: Au printemps (ajouter ce qui suit à votre contexte de démarrage, utilise les méthodes de fabrique donc pas de code est requis) :

    STDOUTSTDERR

    Code de classe (note: vous pouvez changer librement le paquet /classname, ils sont utilisés dans le code pour anaylize la trace de la pile, mais ils sont pris de façon dynamique)

    package mycommons.logging; importation java.io.ByteArrayOutputStream; java.io.IOException d'importation; java.io.PrintStream d'importation, l'importation java.util.Locale; java.util.concurrent.locks.

    ReentrantLock importation, l'importation org.apache.commons.logging.LogFactory; /** * Cette classe redirige toutes les demandes à PrintStream (utilisé par STDOUT et STDERR) * et les envoie aux communes Logging. * * La méthode d'appel à PrintStream est déterminée par l'analyse de la trace de la pile. * * Utilisez les méthodes pratiques registerOnStdout et registerOnStderr à * créer automatiquement une instance de cette classe et de l'enregistrer sur le flux de rediriger vers * communes forestières.

    * * Exemple d'utilisation typique: * * * static void main (String [] args) {* CommonsLoggingPrintStream.registerOnStdout publics (null, "STDOUT"); * CommonsLoggingPrintStream.registerOnStderr (null, "STDERR"); * //...} * * * * Note pour les cas excentriques: Si vous faites plusieurs appels à des méthodes qui ne déclenchent pas * une chasse d'eau, comme expliqué dans PrintWriter (par exemple, append (char)) la méthode d'appel * sera déterminé uniquement par le dernier appel qui déclenche une chasse d'eau ou appelle flush () directement.

    noter également que * dans ce cas vous devez synchroniser l'accès à ces méthodes car ils ne seront pas thread-safe. * Il est généralement conseillé de seulement appeler les méthodes qui génèrent un rinçage automatique comme décrit * dans les javadocs de PrintWriter CommonsLoggingPrintStream * /public class étend PrintStream {LoggingOutputStream outputStream; serrure de ReentrantLock privée = new ReentrantLock (); /** * Vous pouvez utiliser une nouvelle instance de se connecter toutes les méthodes de PrintStream communes de log.

    * Les messages seront écrits CommonsLogging quand flush () est appelé en utilisant * les mêmes règles que PrintStream utilise avec autoFlush = true * *param prependName Un nom préfixé à la classe (null pour aucun) nom comme dans: registerOnStdout ("STDOUT" , résultats nuls) dans un message de journal telles que: INFO STDOUT.org.mydomain.MyClass - Connexion un message *param postpendName Un nom postpended à la classe (null pour aucun) nom comme dans: registerOnStdout (null), les résultats "STDOUT" dans un message de journal telles que: INFO org.mydomain.MyClass.

    STDOUT -Log un message * /de CommonsLoggingPrintStream publique (String prependName, String postpendName) {cette (nouvelle LoggingOutputStream (prependName, postpendName, CommonsLoggingPrintStream.class.getCanonicalName ())); } CommonsLoggingPrintStream privé (LoggingOutputStream los) {super (los, true); this.

    outputStream = los; } /** * Méthode de convenance - Crée une nouvelle instance de * CommonsLoggingPrintStream et l'enregistre sur la sortie standard * *param prependName Un nom préfixé à la classe (null pour aucun) nom comme dans: registerOnStdout (STDOUT, "" NULL) dans les résultats un message de journal telles que: INFO STDOUT.org.mydomain.MyClass - Connectez un message *param postpendName Un nom postpended à la classe (null pour aucun) nom comme dans: registerOnStdout (null, "STDOUT") les résultats dans un message de journal telles comme: le message INFO org.mydomain.MyClass.

    STDOUT -Log *return une référence à l'objet de CommonsLoggingPrintStream créé, peut être ignoré dans la plupart des situations * /public static CommonsLoggingPrintStream registerOnStdout (String prependName, String postpendName) {CommonsLoggingPrintStream ref = new CommonsLoggingPrintStream ( prependName, postpendName); System.

    setOut (ref); retourner ref; } /** * Méthode de convenance - Crée une nouvelle instance de * CommonsLoggingPrintStream et l'enregistre sur STDERR * *param prependName Un nom préfixé à la classe (null pour aucun) nom comme dans: registerOnStdout ("STDERR", null) dans les résultats un message de journal telles que: INFO STDERR.org.mydomain.MyClass - Connectez un message *param postpendName Un nom postpended à la classe (null pour aucun) nom comme dans: registerOnStdout (null, "STDERR") les résultats dans un message de journal telles comme: le message INFO org.mydomain.MyClass.

    STDERR -Log *return une référence à l'objet de CommonsLoggingPrintStream créé, peut être ignoré dans la plupart des situations * /public static CommonsLoggingPrintStream registerOnStderr (String prependName, String postpendName) {CommonsLoggingPrintStream ref = new CommonsLoggingPrintStream ( prependName, postpendName); System.setErr (ref); retourner ref; } /** * Cette classe est nécessaire afin de rendre l'utilisation de PrintWriters garantit * que le flush sera appelée au moment opportun.

    Nous affichons des données à * communes Loggging seulement après flush () est appelée sur la sortie * flux enveloppé par PrintWriter. * * /LoggingOutputStream de classe statique privée étend ByteArrayOutputStream {currentCallerName String privé; Chaîne privée prependName = null; Chaîne privée postpendName = null; Chaîne privée outerClassName = null; //Il est généré dynamiquement afin que les changements à l'emballage ou le nom de la classe ne affectent la fonctionnalité LoggingOutputStream publique (String prependName, String postpendName, String outerClassName) {this.

    prependName = (prependName! = Null &&! PrependName.isEmpty ()) ? prependName + "." : ""; this.postpendName = (postpendName! = null &&! postpendName.isEmpty ())? "." + PostpendName: ""; this.outerClassName = outerClassName; Flush vide}Override publique () throws IOException {super.flush (); //Connexion octets résultant après flush () est appelée. Nous pouvons compter sur cela parce que //nous avons créé le PrintStream avec l'option autoFlush allumé. //Si un tableau d'octets est écrit, il peut contenir de multiples lignes String [] = LogMessages this.toString () split ("\\ n").

    ; pour (String message: LogMessages) {LogFactory.getLog (currentCallerName) .info (message.trim ()); }} SetNameOfCaller void () {reachedCallToOutterClass Boolean = false; StackTraceElement [] = pile Thread.currentThread () getStackTrace ().; //Boucle sur les oligo-éléments de la pile jusqu'à ce que nous trouvons "java.io.PrintStream" //et retourner la première classe-nom complet après les appels à PrintStream pour (StackTraceElement e: pile) {if (e.getClassName () .equals (outerClassName)) {reachedCallToOutterClass = true; Continuez; } else if (reachedCallToOutterClass) {this.

    currentCallerName = prependName + e.getClassName () + postpendName; revenir; }} This.currentCallerName = "unknown.classname"; //Code inaccessible (ou alors théorie tient)}} /** * transmet l'appel à outputStream.setNameOfCaller () * seulement si le verrou synchronisé sur ce appartient fois. Si elle est * possédait plus d'une fois alors ceci est un rappel de l'intérieur * PrintWriter, une situation qui rendra * difficile /impossible de déterminer la méthode d'appel, et ne sont pas nécessaires puisque * le premier appel à setNameOfCaller () est tout ce qui était * nécessaires pour déterminer la méthode d'appel.

    * /Private void setNameOfCaller (serrure de ReentrantLock) {if (lock.getHoldCount ()>

    Page   <<       [1] [2] [3] [4] [5] [6] >>
  • Copyright © 2008 - 2016 Lecture Éducation Articles,https://lecture.nmjjxx.com All rights reserved.