Muchas veces nos encontramos con que las bibliotecas 3 ª parte escribirán a System.out o System.err. Probablemente debería ser más fácil para volver a dirigir a estos marcos de registro comunes, pero no lo es.
A continuación encontrará una clase que puede utilizar para llevar a cabo exactamente esto. La clase es una instancia de PrintWriter y se pueden crear instancias y se utiliza como System.out y System.err PrintWriter. Será volver a dirigir todos los mensajes STDOUT y STDERR a Commons Registro.
También buscará la clase llamada y obtener un registrador con el nombre: com.domain.Class (opcionalmente con un prefijo definido por el usuario o un sufijo, tales como: STDOUT.com.domain.Class o com.domain.Class.STDOUT)
Para facilitar el uso que usted puede utilizar los métodos de fábrica estáticos que registran automáticamente la clase en STDOUT o STDERR respectivamente.
A continuación se presentan un par de ejemplos típicos de uso
Algunas notas acerca de cómo funciona:
Ejemplo de uso: Al comienzo de su aplicación:
principales (String [] args) {static void públicas CommonsLoggingPrintStream.registerOnStdout (null "STDOUT"); CommonsLoggingPrintStream.registerOnStderr (null, "STDERR"); //...
}
Ejemplo de uso: En primavera (añada lo siguiente a su contexto inicio, utiliza los métodos de fábrica por lo que no se requiere ningún código) :
STDOUTSTDERR
Código de Clase (nota: usted puede cambiar libremente el paquete /classname, que se utilizan en el código para anaylize el seguimiento de pila, pero se levantó de forma dinámica) paquete
mycommons.logging; importación java.io.ByteArrayOutputStream; java.io.IOException importación; java.io.PrintStream importación, importación java.util.Locale, importación java.util.concurrent.locks.ReentrantLock; org.apache.commons.
logging.LogFactory importación; /** * Esta clase re-dirige todas las peticiones a PrintStream (usado por stdout y stderr) * y los envía a los Comunes Registro. * * El método de llamada a PrintStream se determina mediante el análisis de la traza de la pila. * * Utilizar los métodos de conveniencia registerOnStdout y registerOnStderr automáticamente * crear una instancia de esta clase y registrarlo en la corriente para redirigir a * Commons Logging. * * Ejemplo de uso típico: * * * main (String [] args) void estáticos públicos {* CommonsLoggingPrintStream.
registerOnStdout (null, "STDOUT"); * CommonsLoggingPrintStream.registerOnStderr (null, "STDERR"); * //...} * * * * Nota para los casos excéntricos: Si realiza varias llamadas a métodos que no activan * un color, como se explica en PrintWriter (por ejemplo, append (char)) el método de llamada * será determinado solamente por la última llamada que desencadena un color o llama a flush () directamente. También tenga en cuenta que * en este caso se debe sincronizar el acceso a estos métodos, ya que no serán seguros para subprocesos.
* Se aconseja generalmente a sólo llamar a métodos que generan una descarga automática como se describe en los * javadocs PrintWriter * /public class CommonsLoggingPrintStream extiende PrintStream {LoggingOutputStream flujoSalida; cerradura ReentrantLock privada = new ReentrantLock (); /** * Se puede utilizar una nueva instancia para registrar todos los métodos PrintStream a Commons Registro.
* Los mensajes se escriben en CommonsLogging cuando flush () se llama usando * las mismas reglas que utiliza PrintStream con autoFlush = true * *param prependName Un nombre antepuesto a la clase (nulo para ninguno) nombre como en: registerOnStdout ("STDOUT" , nulos) da como resultado un mensaje de registro, tales como: INFO STDOUT.org.mydomain.MyClass - Entrar mensaje *param postpendName Un nombre postpended a la clase (nulo para ninguno) nombre como en: registerOnStdout (null), resultados "STDOUT" en un mensaje de registro, tales como: el mensaje INFO org.mydomain.MyClass.
STDOUT -Log * /CommonsLoggingPrintStream pública (String prependName, Cadena postpendName) {esta (nueva LoggingOutputStream (prependName, postpendName, CommonsLoggingPrintStream.class.getCanonicalName ())); } CommonsLoggingPrintStream privada (LoggingOutputStream los) {super (los, true); this.outputStream = los; } /** * Método Práctico - Crea una nueva instancia de * CommonsLoggingPrintStream y la registra en STDOUT * *param prependName Un nombre antepuesto a la clase (nulo para ninguno) nombre como en: registerOnStdout ("STDOUT", null) resulta en un mensaje de registro, tales como: INFO STDOUT.
org.mydomain.MyClass - Ingresar mensaje *param postpendName Un nombre postpended a la clase (nulo para ninguno) nombre como en: registerOnStdout (null, "STDOUT") da como resultado un mensaje de registro como como: mensaje INFO org.mydomain.MyClass.STDOUT -Log *return una referencia al objeto CommonsLoggingPrintStream creado, puede ser ignorada en la mayoría de situaciones * /public static CommonsLoggingPrintStream registerOnStdout (String prependName, Cadena postpendName) {CommonsLoggingPrintStream ref = new CommonsLoggingPrintStream ( prependName, postpendName); System.
setOut (ref); volver ref; } /** * Método Práctico - Crea una nueva instancia de * CommonsLoggingPrintStream y la registra en STDERR * *param prependName Un nombre antepuesto a la clase (nulo para ninguno) nombre como en: registerOnStdout ("STDERR", null) resultados en un mensaje de registro, tales como: INFO STDERR.org.mydomain.MyClass - Ingresar mensaje *param postpendName Un nombre postpended a la clase (nulo para ninguno) nombre como en: registerOnStdout (null, "STDERR") da como resultado un mensaje de registro como como: mensaje INFO org.mydomain.MyClass.
STDERR -Log *return una referencia al objeto CommonsLoggingPrintStream creado, puede ser ignorada en la mayoría de situaciones * /public static CommonsLoggingPrintStream registerOnStderr (String prependName, Cadena postpendName) {CommonsLoggingPrintStream ref = new CommonsLoggingPrintStream ( prependName, postpendName); System.setErr (ref); volver ref; } /** * Esta clase es necesaria con el fin de hacer uso de PrintWriters garantiza * que ras será llamado en el momento apropiado.
Publicamos datos a * Commons Loggging sólo después de flush () se llama en la salida * corriente envuelta por PrintWriter. * * /Private LoggingOutputStream clase estática extiende ByteArrayOutputStream {currentCallerName private String; private String prependName = null; private String postpendName = null; private String outerClassName = null; //Esta es generado dinámicamente por lo que los cambios en el paquete o el nombre de la clase no afectan a la funcionalidad LoggingOutputStream pública (String prependName, Cadena postpendName, Cadena outerClassName) {this.
prependName = (prependName! = Null &&! PrependName.isEmpty ()) ? prependName + "." : ""; this.postpendName = (postpendName! = null &&! postpendName.isEmpty ())? "." + PostpendName: ""; this.outerClassName = outerClassName; }Override Public void flush () throws IOException {super.flush (); //Iniciar bytes resultantes después ras () se llama. Podemos confiar en esto porque //creamos el PrintStream con la opción autoFlush encendido. //Si una matriz de bytes se escribe puede contener varias líneas String [] AnotarMensajes = this.toString split () ("\\ n.
"); for (String mensaje: AnotarMensajes) {LogFactory.getLog (currentCallerName) .info (message.trim ()); }} Void setNameOfCaller () {reachedCallToOutterClass Boolean = false; StackTraceElement [] = pila Thread.currentThread () getStackTrace (.); //Recorrer elementos traza de la pila hasta que encontremos "java.io.PrintStream" //y devolver la primera clase-nombre completo después de las llamadas a PrintStream para (e StackTraceElement: pila) {if (e.getClassName () .equals (outerClassName)) {reachedCallToOutterClass = true; continuar; } else if (reachedCallToOutterClass) {this.
currentCallerName = prependName + e.getClassName () + postpendName; regreso; }} This.currentCallerName = "unknown.classname"; //Código inalcanzable (o eso teoría sostiene)}} /** * Pasa la llamada a outputStream.setNameOfCaller () sólo * si el bloqueo sincronizado en este es de propiedad de una vez. Si se trata de * poseía más de una vez, entonces es una devolución de llamada desde el interior * PrintWriter, situación que hará que sea difícil * /imposible determinar el método de llamada, y no es necesario, ya que * la primera llamada a setNameOfCaller () es todo lo que era * es necesario para determinar el método de llamada.
* /Private void setNameOfCaller (bloqueo ReentrantLock) {if (lock.getHoldCount ()>