1. Übersicht
In allgemeinen Systemen müssen wir diese Verhaltensweisen bestehen bleiben, wenn wir einige wichtige Vorgänge wie das Anmelden beim System, das Hinzufügen von Benutzern, das Löschen von Benutzern usw. durchführen. In diesem Artikel implementieren wir die Protokollinsertion durch benutzerdefinierte Annotationen von Frühlings -AOP und Java. Diese Lösung hat weniger Eingriff in das ursprüngliche Geschäft und ist flexibler bei der Verwirklichung
2. Verwandte Klassendefinitionen von Protokollen
Wir haben das Protokoll in zwei Klassen abstrakten: Funktionsmodul und Betriebstyp
Verwenden Sie Aufzählungsklassen, um das Modul -Modulmoduletyp des Funktionsmoduls zu definieren, z. B. das Schüler- und das Benutzermodul
public enum moduletype {default ("1"), // Standardwert Student ("2"), // Schülermodullehrer ("3"); // Benutzermodul Private Moduletype (String -Index) {this.module = index; } private String -Modul; public String getModule () {return this.module; }}Verwenden Sie eine Aufzählungsklasse, um den Typ des Vorgangs zu definieren: EventType. Wie Anmeldung, Hinzufügen, Löschen, Update, Löschen usw.
public enum eventType {default ("1", "default"), add ("2", "add"), update ("3", "update"), delete_single ("4", "delete-single"), login ("10", "login"), login_out ("11", "login_out"); private EventType (String -Index, String -Name) {this.name = name; this.event = index; } private String -Ereignis; privater Zeichenfolge Name; public String getEvent () {return this.event; } public String getName () {return name; }}3. Definieren Sie logarithmische Annotationen
3.1. @Logenable
Hier definieren wir die Schaltermenge des Protokolls. Nur wenn dieser Wert in der Klasse zutrifft, wird die Protokollfunktion in dieser Klasse aktiviert.
@Documented @retention (retentionPolicy.runtime) @target ({Elementtype.type}) public @Interface logEnable { / ** * Wenn true, wird das logevent unterhalb der Klasse aktiviert, ansonsten * @return * / boolean logenable () Default true;}3.2. @Logevent
Definition des Protokolls hier. Wenn diese Annotation in der Klasse kommentiert ist, wird dieser Parameter als Standardwert für alle Methoden der Klasse verwendet. Wenn sich die Annotation auf der Methode befindet, funktioniert sie nur für diese Methode
@Documented@retention (retentionPolicy.runtime) @target ({java.lang.annotation.elementtype.method, elementtype.type}) public @Interface LOGEVENT {moduletype module () Default moduletype.Default; // das Modul, zu dem das Protokoll EventType Event () eventType.Default gehört; // Ereignistyp String String () Standard ""; // Beschreibungsinformationen}3.3. @Logkey
Wenn sich diese Annotation auf einer Methode befindet, werden die Parameter der gesamten Methode im JSON -Format für Anmeldungen gespeichert. Wenn diese Annotation sowohl für die Methode als auch für die Klasse kommentiert ist, überschreibt die Annotation der Methode den Wert der Klasse.
@Target ({Elementtype.field, elementtype.parameter})@retention(runtentionPolicy.Runtime)@documentedPublic @Interface Logkey {String Keyname () Standard ""; // Der Name des key booleschen isuserID () Standard False; // Ob dieses Feld die BenutzerID dieser Operation ist, hier wird boolean islog () Standard true weggelassen. // ob es zum Protokoll hinzugefügt wird}4. Definieren Sie die Protokollverarbeitungsklasse
4.1. Logadmmodel
Definieren Sie die Klasse, die Protokollinformationen enthält
öffentliche Klasse logAdmmodel {private long id; private String userID; // Benutzer private Zeichenfolge Benutzername betreiben; private String admmodel; // Modul Private String aduldent; // Operation Private Datum erstelltes Datum; // Betriebsinhalt private String admptent; // Betriebsinhalt privat String Desc; // Bemerkung eingestellt/werden weggelassen}4.2. Iloogmanager
Definieren Sie die Schnittstellenklasse Iloogmanager für die Protokollverarbeitung
Wir können Protokolle in der Datenbank speichern oder Protokolle zum Öffnen von Middleware senden, wenn Redis, MQ usw. jede Protokollverarbeitungsklasse ist eine Implementierungsklasse dieser Schnittstelle
öffentliche Schnittstelle IloGManager { / *** Protokollverarbeitungsmodul* @param paramlogadmbean* / void Deallog (logAdmmodel paramlogAdmbean);}4.3. Dblogmanager
ILogmanager -Implementierungsklasse zum Speichern von Protokollen. Nur hier simulierter Speicher hier
@ServicePublic Class DblogManager implementiert ILogmanager {@Override public void Deallog (logAdmmodel paramlogadmbean) {System.out.println ("Store die Protokoll in die Datenbank, der Protokollinhalt ist wie folgt:" + json.tojonstring (paramlogadmbean); }}5. AOP -Konfiguration
5.1. Logaspect definiert die AOP -Klasse
Annotieren Sie diese Klasse mit @aspect
Verwenden Sie @PointCut, um die Paket- und Klassenmethoden zum Abfangen zu definieren
Wir verwenden @around, um die Methode zu definieren
@Component @Aspektpublic Class Logaspect {@autowired Private Loginfogeneration Loginfogeneration; @Autowired Private Iloogmanager Logmanager; @Pointcut ("Execution (*com.hry.spring.mvc.aop.log.service ..*.*(..)") ") public void ManagerLogpoint () {} @around (" ManagerLogpoint () ") public Object umManagerLogpoint (ConceingJoInpoint JP) Throwable ashable {. }} rund ummanagerLogpoint: Der Hauptgeschäftsprozess der Hauptmethode
1. Überprüfen Sie, ob die Klasse der Abschlussmethode von @logenable kommentiert wird. In diesem Fall wird die Protokolllogik befolgt, sonst wird eine normale Logik ausgeführt.
2. Überprüfen Sie, ob die Intercept -Methode @Logevent ist. In diesem Fall wird die Protokolllogik befolgt, andernfalls wird die normale Logik ausgeführt.
3. Erhalten Sie den Medianwert von @logevent basierend auf der erhaltenen Methode und generieren Sie einige Parameter des Protokolls. Der Wert von @logevent wird in der Klasse als Standardwert definiert
4. Rufen Sie die ProcessManagerLogMessage von Loginfogeneration auf, um andere Parameter im Protokoll zu füllen. Wir werden später über diese Methode sprechen.
5. Normale Geschäftsanrufe durchführen
6. Wenn die Ausführung erfolgreich ist, führt der Logmanager das Protokoll aus (wir zeichnen nur die Protokolle der erfolgreichen Ausführung hier auf und Sie können auch die Protokolle der fehlgeschlagenen Aufzeichnung definieren).
@Around ("ManagerLogpoint ()") öffentliches Objekt umManagerLogpoint (ProceedingJoInpoint JP) löst Throwable {class target = jp.gettarget (). GetClass () aus; // logEnable logenable logenable = (logEnable) target.getAnnotation (logenable.class) abrufen; if (logenable == null ||! logenable.logenable ()) {return jp.procece (); } // das logevent in der Klasse als Standardwert logevent loGEventClass = (loGeVvent) target.getannotation (logevent.class) erhalten; Methodenmethode = GetInvokedMethod (JP); if (method == null) {return jp.procece (); } // das logevent auf der Methode logevent logeventMethod = methode.getannotation (logevent.class) erhalten; if (loGEventMethod == null) {return jp.procece (); } String opEvent = loGEventMethod.event (). GetEvent (); String optModel = loGeVventMethod.module (). GetModule (); String desc = logeVventMethod.desc (); if (logeventClass! = null) {// Wenn der Wert auf der Methode der Standardwert ist, ersetzen Sie ihn durch den globalen Wert. opEvent = opEvent.equals (EventType.Default)? logeventClass.event (). getEvent (): opeVent; optModel = optModel.equals (moduletype.default)? logeventClass.module (). getModule (): optmodel; } LogAdmmodel logbean = new LogAdmmodel (); logbean.setAdmmodel (Optmodel); logbean.setAdMevent (opeVent); logbean.setDesc (Desc); logbean.setCreatedate (neues Datum ()); loginfogeneration.processingManagerLogMessage (JP, Logbean, Methode); Objekt returnObj = jp.procece (); if (opevent.equals (eventType.login)) {// todo Wenn es angemeldet ist, müssen Sie beurteilen, ob es auf der Grundlage des Rückgabewerts erfolgreich ist. Wenn es erfolgreich ist, fügen Sie Protokolle hinzu. Das Urteil hier ist relativ einfach, wenn (returnObj! = Null) {this.logManager.deallog (logbean); }} else {this.logmanager.deAllog (logbean); } return returnObj; } / ** * die Anforderungsmethode abrufen * * @param jp * @return * / public methode getInvokedMethod (joinpoint jp) {// Parameter des Aufrufens von Methodenlistenklassenlist = new ArrayList (); für (Objekt obj: jp.getargs ()) {classlist.add (obj.getClass ()); } Class [] argscls = (class []) classlist.toArray (neue Klasse [0]); // der aufgerufene Methodenname String methodname = jp.getSignature (). GetName (); Methode Methode = NULL; try {method = jp.gettarget (). getClass (). getMethod (methodName, argscls); } catch (NoSuchMethodException e) {e.printstacktrace (); } Rückgabemethode; }}6. Die Lösung zur Anwendung der obigen Lösung in der Praxis
Hier simulieren wir das Geschäft von Studenten und verwenden die obigen Anmerkungen, um sie auf sie anzuwenden und die Protokolle abzufangen.
6.1. ISTUDENTENTEVICE
Business Interface -Klasse, General Crud ausführen
public interface iStudentService {void deleteById (String -ID, String a); int Save (StudentModel StudentModel); void Update (StudentModel StudentModel); void queryById (String -ID);}6.2. StudenterviceImpl:
@Logenable: @Logevent definiert alle Modulmethoden in der Startprotokoll -Interception -Klasse. Weitere Informationen zu @Logeven definieren das Protokoll. @Service@LogEnable // Start log interception @LogEvent(module = ModuleType.STUDENT)public class StudentServiceImpl implements IStudentService { @Override @LogEvent(event = EventType.DELETE_SINGLE, desc = "Delete Record") // Add log identifier public void deleteById(@LogKey(keyName = "id") String id, String a) { System.out.printf (this.getClass () + "DeleteById id =" + id); } @Override @logevent (event = eventType.add, desc = "record") // Protokollidentifier public int Save (StudentModel StudentModel) {System.out.printf (this.getClass () + "Save =" + Json.tojstring (StudentModel)); Rückkehr 1; } @Override @logevent (event = eventType.update, Desc = "Aktualisieren Sie den Datensatz") // Protokollidentifier public void Update (studentModel studentModel) {System.out.printf (this.getClass () + "Save Update =" + JSON.tojserstring (StudentModel)); } // keine Protokollidentifier @Override public void queryById (String -ID) {System.out.printf (this.getClass () + "queryById id =" + id); }}Führen Sie die Testklasse aus und drucken Sie die folgenden Informationen aus, um anzuzeigen, dass unsere Konfiguration unserer Protokollanmerkungen aktiviert ist:
Speichern Sie die Protokolle in der Datenbank, und der Protokollinhalt lautet wie folgt:
{"adminent": "4", "admmodel": "1", "admoptContent": "{/" id/":/" 1/"}", "Createdate": 152577973811, "Desc": "Record"} löschen}7. Code
Im Folgenden finden Sie den detaillierten Code oben
Github -Code, bitte versuchen Sie, Tag v0.21 zu verwenden, verwenden Sie keinen Master, da ich nicht garantieren kann, dass der Mastercode unverändert bleibt