Während einiger Zeit in verschiedenen Jobs stellte sich heraus, dass ich mehrere Dienstprogramme benötigte, die zu diesem Zeitpunkt nicht verfügbar waren. Und ich sah, dass ich sie immer und immer wieder brauchte. Also schrieb ich meine eigene kleine Bibliothek, die ich sehr nützlich fand. Also habe ich es gerade als Open-Source-Java-Bibliothek veröffentlicht.
Hier ist der Github LinkJavadoc online ist hier verfügbarDiese Bibliothek ist auch in Maven Central verfügbar. Hier sind die Maven-Artefakte (die Version 1.5.0.8 ist die neueste zum Zeitpunkt des Schreibens dieses Artikels, kann sich aber in Zukunft ändern. Um nach der neuesten Version zu suchen, suchen Sie unter
http: //search.maven nach dem Artefakt "MgntUtils"
. org / ):
<dependency> <groupId>com.github.michaelgantman</groupId> <artifactId>MgntUtils</artifactId> <version>1.5.0.8</version> </dependency> <dependency> <groupId>com.github.michaelgantman</groupId> <artifactId>MgntUtils</artifactId> <version>1.5.0.8</version> <classifier>javadoc</classifier> </dependency> <dependency> <groupId>com.github.michaelgantman</groupId> <artifactId>MgntUtils</artifactId> <version>1.5.0.8</version> <classifier>sources</classifier> </dependency>
Nachfolgend finden Sie nur eine kurze Erklärung dessen, was sich dort befindet. Die Bibliothek enthält ein (wie ich hoffe) gut geschriebenes JavaDoc mit einer detaillierten Beschreibung. Hier ist die Liste der Funktionen:
Stacktrace-Rauschfilter
Nach meiner Erfahrung war diese Funktion die allgemeinste und nützlichste für mich. Stacktrace ist ein Lebensretter beim Debuggen oder Herausfinden von Fehlern in Ihrer Anwendung. Wenn Sie jedoch auf der Serverseite mit Protokollen arbeiten, können Sie auf einen riesigen Stacktrace stoßen, der das längste nutzlose Ende verschiedener Frameworks und Application Server-Pakete enthält. Und irgendwo in diesem Stapel befinden sich mehrere Zeilen einer relevanten Spur und sie können sich in verschiedenen Segmenten befinden, die durch nutzlose Informationen voneinander getrennt sind. Es wird zum Albtraum, nach relevanten Dingen zu suchen. Hier ist ein Link, der dasselbe Problem mit Beispielen aus der Praxis beschreibt (nicht für schwache Nerven):
https://dzone.com/articles/filtering-stack-trace-hell . In meiner Bibliothek gibt es eine Klasse mit dem Namen
TextUtils und der Methode
getStacktrace () mit mehreren überladenen Signaturen. Es nimmt eine Throwable-Instanz an und ermöglicht das Festlegen eines Paketpräfixes der relevanten Pakete.
Das gleiche Dienstprogramm (ab Version 1.5.0.3) verfügt auch über die Methode
getStacktrace () , die die Schnittstelle CharSequence anstelle von Throwable verwendet und somit das Filtern und Verkürzen von Stacktraces ermöglicht, die als Zeichenfolge gespeichert sind, genau wie Stacktraces, die aus Throwable extrahiert wurden. Im Wesentlichen können Stacktraces also zur Laufzeit oder später "on the fly" aus einer beliebigen Textquelle wie einem Protokoll herausgefiltert werden. (Nur zur Verdeutlichung: Das Dienstprogramm unterstützt nicht das Parsen und Ändern der gesamten Protokolldatei. Es unterstützt nur das Filtern einer Stapelverfolgung, die als Zeichenfolge übergeben wird. Wenn also Ausnahmen in der Protokolldatei gefiltert werden sollen, müssen Sie die Protokolldatei analysieren und Stacktrace (s) als separate Zeichenfolgen extrahieren und dann mit diesem Dienstprogramm die einzelnen Stacktraces filtern.
Hier ist ein Anwendungsbeispiel. Angenommen, Ihr Buchungskreis befindet sich immer in Paketen, die mit "com.plain" beginnen. * Sie legen also ein solches Präfix fest und tun dies
logger.info(TextUtils.getStacktrace(e,true,"com.plain."));
Dadurch werden alle nutzlosen Teile des Traces sehr intelligent herausgefiltert, sodass Sie eine sehr präzise Stapelverfolgung erhalten. Außerdem fand ich es sehr praktisch, das Präfix voreinzustellen und dann einfach die Komfortmethode zu verwenden
TextUtils.getStacktrace(e);
Es wird dasselbe tun. Um das Präfix voreinzustellen, verwenden Sie einfach die Methode
setRelevantPackage("com.plain.");
Wenn Sie diesen Wert bei der Konfiguration voreinstellen möchten, können Sie ab der Bibliotheksversion 1.1.0.1 die Umgebungsvariable "
MGNT_RELEVANT_PACKAGE " oder die Systemeigenschaft "
mgnt.relevant.package " auf den Wert "
com.plain " und die Eigenschaft setzen wird auf diesen Wert gesetzt, ohne dass Sie die Methode
TextUtils.setRelevantPackage ("com.plain.") aufrufen. explizit in Ihrem Code. Beachten Sie, dass der Wert der Systemeigenschaft Vorrang vor der Umgebungsvariablen hat, wenn beide festgelegt werden. Nur eine Erinnerung daran, dass Sie mit der Eigenschaft "System" Folgendes in Ihre Befehlszeile einfügen können:
"-Dmgnt.relevant.package = com.plain."
Wenn Sie eine frühere Version als 1.1.0.1 dieser Bibliothek verwenden oder die oben genannte Umgebungsvariable oder Systemeigenschaft nicht verwenden möchten und die Spring-Umgebung verwenden, können Sie das Präfix voreinstellen, indem Sie Ihrer Spring-Konfiguration das folgende Segment hinzufügen:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="com.mgnt.utils.TextUtils"/> <property name="targetMethod" value="setRelevantPackage"/> <property name="arguments" value="com.plain."/> </bean>
Javadoc erklärt alles im Detail. Aber hier ist ein kleiner Vorgeschmack: Sie erhalten folgenden Stacktrace:
at com.plain.BookService.listBooks() at com.plain.BookService$$FastClassByCGLIB$$e7645040.invoke() at net.sf.cglib.proxy.MethodProxy.invoke() ... at com.plain.LoggingAspect.logging() at sun.reflect.NativeMethodAccessorImpl.invoke0() ... at com.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks() at com.plain.web.BookController.listBooks()
statt
at com.plain.BookService.listBooks() at com.plain.BookService$$FastClassByCGLIB$$e7645040.invoke() at net.sf.cglib.proxy.MethodProxy.invoke() at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint() at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed() at com.plain.LoggingAspect.logging() at sun.reflect.NativeMethodAccessorImpl.invoke0() at sun.reflect.NativeMethodAccessorImpl.invoke() at sun.reflect.DelegatingMethodAccessorImpl.invoke() at java.lang.reflect.Method.invoke() at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs() at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod() at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke() at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke() at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() at org.springframework.transaction.interceptor.TransactionInterceptor.invoke() at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke() at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept() at com.plain.BookService$$EnhancerByCGLIB$$7cb147e4.listBooks() at com.plain.web.BookController.listBooks()
Silent String parst in Integer, Long usw
Dieselbe Klasse
TextUtils stellt Methoden bereit, mit denen String unbemerkt (ohne Ausnahme, wenn er jemals geworfen wird) in die Typen Double, Long, Integer, Short und Byte zerlegt werden kann. Die Methoden heißen
parseStringToLong (), parseStringToInteger () usw. Sie alle vertreten 4 Argumente:
- Ein String, der analysiert werden soll
- Eine Implementierung von Number (Double, Long, Integer, Short oder Byte) als Standardwert, wenn ein Analyseproblem aufgetreten ist
- Ein String, der als Fehlermeldung in das Protokoll geschrieben werden soll, wenn das erste Argument null ist (kann null sein, und dann wird kein Fehler gedruckt)
- Ein String, der als Fehlermeldung ausgegeben werden soll, wenn eine NumberFormatException aufgetreten ist (kann null sein und dann wird kein Fehler ausgegeben)
Zeichenfolge nach Zeitintervall analysieren
In derselben Klasse
TextUtils gibt es eine Methode
parseStringToTimeInterval (String value) . Diese Methode analysiert eine Zeichenfolge, von der erwartet wird, dass sie einen bestimmten Zeitintervallwert enthält - einen numerischen Wert mit optionalem Suffix für die Zeiteinheit. Beispielsweise wird die Zeichenfolge "38s" als 38 Sekunden, "24m" - 24 Minuten "4h" - 4 Stunden, "3d" - 3 Tage und "45" als 45 Millisekunden analysiert. Unterstützte Suffixe sind "
s " für Sekunden, "
m " für Minuten, "
h " für Stunden und "
d " für Tage. Zeichenfolge ohne Suffix enthält einen Wert in Millisekunden. Bei Suffixen wird die Groß- und Kleinschreibung nicht berücksichtigt. Wenn der bereitgestellte String ein nicht unterstütztes Suffix enthält oder einen negativen numerischen Wert oder eine Null enthält oder einen nicht numerischen Wert enthält, wird eine IllegalArgumentException ausgelöst. Diese Methode gibt die TimeInterval-Klasse zurück - eine Klasse, die ebenfalls in dieser Bibliothek definiert ist. Im Wesentlichen enthält es zwei Eigenschaften mit relevanten Getters und Setters: long "value" und java.util.concurrent.TimeUnit. Zusätzlich zu Gettern und
Setzern verfügt diese Klasse über Methoden
toMillis () ,
toSeconds () ,
toMinutes () ,
toHours () toDays () . Diese Methoden geben einen langen Wert in der angegebenen Zeitskala zurück (genauso wie die entsprechenden Methoden in der Klasse
java.util.concurrent.TimeUnit ).
Diese Methode kann sehr nützlich sein, um Zeitintervalleigenschaften wie Zeitüberschreitungen oder Wartezeiten aus Konfigurationsdateien zu analysieren. Es eliminiert unnötige Berechnungen von verschiedenen Zeitskalen bis hin zu Millisekunden. Bedenken Sie, dass Sie eine
methodInvokingInterval- Eigenschaft haben, die Sie für 5 Tage
festlegen müssen. Um den Millisekundenwert festzulegen, müssen Sie berechnen, dass 5 Tage 432000000 Millisekunden sind (offensichtlich keine unmögliche Aufgabe, aber ärgerlich und fehleranfällig), und dann muss jeder andere, der den Wert 432000000 sieht, ihn auf 5 zurückrechnen Tage, die frustrierend sind. Mit dieser Methode haben Sie jedoch einen Eigenschaftswert, der auf "5d" festgelegt ist und den Code aufruft
long milliseconds = TextUtils.parsingStringToTimeInterval("5d").toMillis();
löst Ihr Konvertierungsproblem. Dies ist natürlich keine übermäßig komplexe Funktion, kann jedoch die Konfigurationsdateien vereinfachen und klarer gestalten und Frustrationen und "blöde" Fehleinschätzungen in Millisekunden-Bugs vermeiden.
Versionen vergleichen
Dieses Dienstprogramm ermöglicht die Konvertierung von String in Version und umgekehrt sowie den korrekten Vergleich von Versionen und Versionsbereichen. Wenn Sie Versionen vergleichen müssen, vergleichen Sie häufig nur Strings. Nehmen wir also an, die Version "1.5.3" ist größer als die Version "1.3.1". Wenn Sie jedoch die Zeichenfolgen "1.4.2" und "1.12.3" vergleichen, ist die Zeichenfolge "1.4.2" fälschlicherweise größer. Dieses Dienstprogramm behebt also ein solches Problem und führt zusätzlich die VersionRange-Klasse ein und ermöglicht Vorgänge in Versionsbereichen. (Siehe Methoden
compareVersions in der Klasse
TextUtils und in der Klasse
VersionRange. )
String Unicode Konverter
Die Klasse
StringUnicodeEncoderDecoder enthält Methoden, die einen String (in einer beliebigen Sprache) in eine Folge von Unicode-Zeichen konvertieren können und umgekehrt. Beispielsweise wird eine Zeichenfolge "Hello World" in konvertiert
"\ u0048 \ u0065 \ u006c \ u006c \ u006f \ u0020 \ u0057 \ u006f \ u0072 \ u006c \ u0064"
und kann wieder hergestellt werden.
Lebenszyklus-Management (Fabriken, die sich selbst instanziieren)
Diese Funktion ist ein Paket mit einer kleinen Infrastruktur, die die Arbeit mit Fabriken vereinfacht und automatisiert, die konkrete Implementierungen einer Schnittstelle bereitstellen. Das Paket enthält nur 2 Klassen:
BaseEntityFactory und
BaseEntity . Kurz gesagt: Wenn Sie eine Factory erstellen, die
BaseEntityFactory und einige Interfaces mit all ihren konkreten Implementierungen erweitert, die
BaseEntity erweitern, wird jede Ihrer
Klasseninstanzen der konkreten Implementierungsklasse automatisch in Ihre Factory eingefügt. Sie müssen sich keine Gedanken darüber machen, wie und wann Sie Ihre Fabrik bevölkern müssen. Die Infrastruktur erledigt dies für Sie, wenn der Konstruktor Ihrer konkreten Implementierungsklasse aufgerufen wird. Sie müssen also nur eine beliebige Anzahl konkreter Implementierungsklassen erstellen und sicherstellen, dass für jeden Konstruktor ein Aufruf erfolgt. Danach können Sie Ihre Factory verwenden, um eine Ihrer konkreten Implementierungsklassen an einer beliebigen Stelle in Ihrem Code abzurufen. Dies ist eine kurze Erklärung. Es gibt ein paar Details, aber nicht so viele. Eine detaillierte Beschreibung dieses Pakets finden Sie in der Javadoc-API des Pakets
com.mgnt.lifecycle.management description. Der Quellcode enthält auch das Paket com.mgnt.lifecycle.management.example, das gut kommentierte und detaillierte Codebeispiele zur Verwendung dieser Funktion enthält.
Für den praktischen Gebrauch fand ich es sehr nützlich für das Spring-Framework. Denken Sie daran, dass Spring während der Initialisierung alle definierten Beans instanziiert. Wenn wir also im Spring-Kontext unsere konkreten Implementierungen einfach als Spring Beans deklarieren, instanziiert Spring sie für uns und initialisiert so ihre Factory automatisch. Dies könnte sehr praktisch sein. Stellen Sie sich vor, Sie haben ein Bean mit einer Eigenschaft des Typs der benutzerdefinierten Schnittstelle, die mehrere Implementierungen aufweist. Welche tatsächliche Implementierung jedoch erforderlich ist, wird zur Laufzeit ermittelt. Zu diesem Zeitpunkt können Sie also die Methode
getInstance (java.lang.String) Ihrer Factory verwenden, um auf die erforderliche Implementierung zuzugreifen. Auf diese Weise können Sie nicht ALLE Ihre konkreten Instantiierungen in Ihre Bean einfügen, und Sie müssen Spring
Bean Factory nicht verwenden, um auf eine von Spring definierte Bean zuzugreifen, da dies die Nicht-Intrusivität von Spring verletzen würde (dh Sie können Komponenten schreiben, von denen keine Abhängigkeit besteht Frühling). Wenn Sie zu einem späteren Zeitpunkt konkretere Implementierungen hinzufügen müssen, müssen Sie lediglich Ihre Implementierungsklassen zu Ihrem Code hinzufügen und sie als Spring Beans deklarieren. Den Rest erledigen der Frühling und diese Infrastruktur!
Datei-Utils
Mit diesem Dienstprogramm können Sie eine Datei als Zeichenfolge mit oder ohne Angabe eines Zeichensatzes oder als Byte-Array lesen. Dieses Dienstprogramm verwendet NIO-Paket und Puffer für eine schnellere Leistung. Die maximale Dateigröße für dieses Dienstprogramm beträgt 2 GB.
Zeit util
Dies ist nur eine einfache Methode, die die gleiche Funktionalität wie Thread.sleep () bietet, jedoch nicht verwendet wird. Dh es "schluckt" IterruptedException. Außerdem sind zwei Argumente erforderlich: Zeit bis zum Einschlafen und Maßeinheit. Also statt
try { Thread.sleep(2000); } catch (InterruptedException ie) { }
Sie können einfach schreiben:
TimeUtils.sleepFor(2, TimeUnit.SECONDS);
Ich fand es süß
Das ist es also. Fühlen Sie sich frei, diese Bibliothek herunterzuladen. Es wird mit einer MIT-Lizenz geliefert - einer der freizügigsten Lizenzen, die mir bekannt sind. Der Quellcode, Javadoc und die Binärversion sind über den obigen Link verfügbar. Der Code wurde von JDK 8 kompiliert, enthält jedoch keine Funktionen von Version 8. Es sollte auf jeden Fall mit Java 7 funktionieren, ich vermute, es wird mit Java 6 und sogar 5 funktionieren, habe es aber nicht mit diesen Versionen getestet. Verwenden Sie es nach Belieben, teilen Sie es anderen mit, wenn Sie es mögen, und senden Sie mir eine Nachricht an michael_gantman@yahoo.com, wenn Sie Feedback haben.