1. نظرة عامة
في الأنظمة العامة ، عندما نقوم ببعض العمليات المهمة ، مثل تسجيل الدخول إلى النظام ، وإضافة المستخدمين ، وحذف المستخدمين ، وما إلى ذلك ، نحتاج إلى استمرار هذه السلوكيات. في هذه المقالة ، نقوم بتنفيذ إدراج السجل من خلال التعليقات التوضيحية المخصصة لـ Spring AOP و Java. هذا الحل له اقتحام أقل للشركة الأصلية وأكثر مرونة في إدراك
2. تعريفات الفئة ذات الصلة للسجلات
نلخص تسجيل الدخول إلى فئتين: الوحدة الوظيفية ونوع التشغيل
استخدم فئات التعداد لتحديد moduletype نوع وحدة الوظائف ، مثل وحدة الطالب ووحدة المستخدم
التعداد العام ModuleType {default ("1") ، // student value student ("2") ، // student module teacher ("3") ؛ // وحدة المستخدم الخاصة moduletype (index string) {this.module = index ؛ } وحدة السلسلة الخاصة ؛ السلسلة العامة getModule () {return this.module ؛ }}استخدم فئة التعداد لتحديد نوع العملية: EventType. مثل تسجيل الدخول ، إضافة ، حذف ، تحديث ، حذف ، إلخ.
enum eventtype {default ("1" ، "افتراضي") ، إضافة ("2" ، "إضافة") ، تحديث ("3" ، "تحديث") ، delete_single ("4" ، "delete-single") ، login ("10" ، "login") ، login_out ("11" ، "login_out") ؛ Private EventType (فهرس السلسلة ، اسم السلسلة) {this.name = name ؛ this.event = index ؛ } الحدث الخاص بالسلسلة الخاصة ؛ اسم السلسلة الخاصة ؛ السلسلة العامة getEvent () {return this.event ؛ } السلسلة العامة getName () {return name ؛ }}3. تحديد التعليقات التوضيحية ذات الصلة بالسجل
3.1. logenable
هنا نحدد كمية التبديل من السجل. فقط عندما تكون هذه القيمة صحيحة في الفصل ، سيتم تمكين وظيفة السجل في هذه الفئة.
@موثقة @attreence (attreencepolicy.runtime) target ({elementType.type}) public interface logenable { / ** * إذا كان ذلك صحيحًا ، سيتم تمكين logevent أدناه ، وإلا * regurn * / boolean logenable ()3.2. logevent
تعريف السجل هنا. إذا تم شرح هذا التعليق التوضيحي على الفصل ، فسيتم استخدام هذه المعلمة كقيمة افتراضية لجميع طرق الفصل. إذا كان التعليق التوضيحي على الطريقة ، فسيعمل فقط على هذه الطريقة
@موثقة@attreence (enthypolicy.runtime) target ({java.lang.annotation.elementtype.method ، elementtype.type}) public interface logevent {moduletype module () moduletype.default ؛ // الوحدة النمطية التي ينتمي إليها السجل EventType () EventType.Default ؛ // سجل نوع الحدث سلسلة desc () الافتراضي "" ؛ // معلومات الوصف}3.3. @logkey
إذا كان هذا التعليق التوضيحي على طريقة ، يتم حفظ معلمات الطريقة بأكملها لتنسيق السجل في JSON. إذا تم شرح هذا التعليق التوضيحي على كل من الطريقة والفئة ، فإن التعليق التوضيحي على الطريقة يكتب القيمة في الفصل.
target ({elementType.field ، elementType.Parameter})@entry(retentionpolicy.runtime)@documentedpublic@interface logkey {String keyname () افتراضي "" ؛ // اسم المفتاح المنطقي isUserid () الافتراضي الخاطئة ؛ // ما إذا كان هذا الحقل هو معرف مستخدم هذه العملية ، فإليك حذفه Islog () الافتراضي ؛ // ما إذا تمت إضافته إلى السجل}4. تحديد فئة معالجة السجل
4.1. logadmmodel
حدد الفصل الذي يحمل معلومات السجل
الفئة العامة logadmmodel {private long id ؛ سلسلة userId الخاصة ؛ // تشغيل اسم المستخدم الخاص بالسلسلة الخاصة للمستخدم ؛ سلسلة خاصة admmodel ؛ // الوحدة النمطية السلسلة الخاصة. // عملية التاريخ الخاص التي تم إنشاؤها ؛ // Operation Content string private admoptcontent ؛ // Operation Content Private String DESC ؛ // SET SET/GEED}4.2. Ilogmanager
تحديد واجهة فئة Ilogmanager لمعالجة السجل
يمكننا تخزين السجلات في قاعدة البيانات ، أو إرسال سجلات لفتح الوسيطة ، إذا كان Redis ، MQ ، إلخ. كل فئة معالجة السجل هي فئة تنفيذ لهذه الواجهة
الواجهة العامة ilogmanager { / *** وحدة معالجة السجل* param paramlogadmbean* / void deallog (logadmmodel paramlogadmbean) ؛}4.3. Dblogmanager
فئة تنفيذ Ilogmanager لتخزين سجلات. تخزين محاكاة فقط هنا
servicepublic class dblogmanager تنفذ ilogmanager {Override public void deallog (logadmmodel paramlogadmbean) {system.out.println ("تخزين السجل إلى قاعدة البيانات ، محتوى السجل هو كما يلي:" + json.tojsonstring (paramlogadmbean))) ؛ }}5. تكوين AOP
5.1. يحدد Logaspects فئة AOP
توضيح هذا الفصل مع aspect
استخدم @pointcut لتحديد طرق الحزمة والفئة للاعتراض
نستخدم @AROUND لتحديد الطريقة
@component @sidepublic class logaspect {autowired private loginfogeneration loginfogeneration ؛ Autowired Private Ilogmanager logmanager ؛ @pointcut ("التنفيذ (*com.hry.spring.mvc.aop.log.service ..*.*. }} حول MountManagerLogPoint: العملية التجارية الرئيسية للطريقة الرئيسية
1. إذا كان الأمر كذلك ، فسيتم اتباع منطق السجل ، وإلا سيتم تنفيذ المنطق العادي.
2. تحقق مما إذا كانت طريقة التقاطع هي logevent. إذا كان الأمر كذلك ، فسيتم اتباع منطق السجل ، وإلا سيتم تنفيذ المنطق العادي.
3. احصل على القيمة المتوسطة لـ @logevent استنادًا إلى طريقة الحصول على وإنشاء بعض المعلمات من السجل. يتم تعريف قيمة @logevent على الفصل على أنها القيمة الافتراضية
4. استدعاء LogInfogeneration's ProcessManagerLogMessage لملء المعلمات الأخرى في السجل. سنتحدث عن هذه الطريقة لاحقًا.
5. إجراء مكالمات تجارية عادية
6. إذا نجح التنفيذ ، يقوم LogManager بتنفيذ السجل (نقوم فقط بتسجيل سجلات التنفيذ الناجح هنا ، ويمكنك أيضًا تحديد سجلات التسجيل الفاشل)
AROUND ("ManagerLogPoint ()") كائن عام حول MONKAGERLOGPOINT (POSTONINGJOINPOINT JP) يلقي رمي {class target = jp.getTarget (). getClass () ؛ // الحصول على logenable logenable logenable = (logenable) target.getAnnotation (logenable.class) ؛ if (logenable == null ||! logenable.logenable ()) {return jp.proceed () ؛ } // احصل على logevent على الفئة باعتبارها القيمة الافتراضية logeventClass = (logevent) target.getAnnotation (logevent.class) ؛ طريقة الطريقة = getInvokedMethod (JP) ؛ if (method == null) {return jp.proceed () ؛ } // الحصول على logevent على طريقة logevent logeventMethod = method.getAnnotation (logevent.class) ؛ if (logeventMethod == NULL) {return jp.proceed () ؛ } string optevent = logeventMethod.event (). getEvent () ؛ String optModel = logeventMethod.module (). getModule () ؛ سلسلة desc = logeventMethod.desc () ؛ if (logeventClass! = null) {// إذا كانت القيمة على الطريقة هي القيمة الافتراضية ، استبدلها بالقيمة العالمية. Optevent = Optevent.equals (EventType.Default)؟ logeventClass.event (). getEvent (): Optevent ؛ optmodel = optmodel.equals (moduletype.default)؟ logeventClass.Module (). getModule (): optmodel ؛ } logadmmodel logbean = new logadmmodel () ؛ logbean.setadmmodel (OptModel) ؛ logbean.setadmevent (Optevent) ؛ logbean.setdesc (desc) ؛ logbean.setCreatedAte (تاريخ جديد ()) ؛ loginfogeneration.processingManagerLogMessage (JP ، logbean ، method) ؛ الكائن returnObj = jp.proceed () ؛ إذا كان (Optevent.equals (EventType.login)) {// toDo إذا تم تسجيل الدخول ، فأنت بحاجة إلى الحكم على ما إذا كان ناجحًا بناءً على قيمة الإرجاع. إذا نجحت ، ثم أضف سجلات. الحكم هنا بسيط نسبيًا إذا (returnobj! = null) {this.logmanager.deallog (logbean) ؛ }} آخر {this.logmanager.deallog (logbean) ؛ } returnoBJ ؛ } / ** * احصل على طريقة الطلب * * param jp * regurn * / method public getInvokedMethod (JoinPoint jp) {// معلمات طريقة الاتصال قائمة class = new ArrayList () ؛ لـ (Object OBJ: jp.getargs ()) {classlist.add (obj.getClass ()) ؛ } class [] argscls = (class []) classlist.toarray (فئة جديدة [0]) ؛ // اسم الأسلوب المسمى methodName = jp.getSignature (). getName () ؛ طريقة الطريقة = فارغة ؛ حاول {method = jp.getTarget (). getClass (). getMethod (methodName ، argscls) ؛ } catch (nosuchmethodexception e) {e.printStackTrace () ؛ } طريقة الإرجاع ؛ }}6. الحل لتطبيق الحل أعلاه في الممارسة العملية
نحن هنا نحاكي أعمال الطلاب ، ونستخدم التعليقات التوضيحية أعلاه لتطبيقها عليها واعتراض السجلات.
6.1. iStudentService
فئة واجهة الأعمال ، تنفيذ الجنرال كرود
الواجهة العامة isTudentService {void deletebyid (string id ، string a) ؛ int save (عارضة الأزياء الطالب) ؛ تحديث باطل (عارضة الأزياء الطالب) ؛ void querybyid (معرف السلسلة) ؛}6.2. structerviceImpl:
logenable: @logevent يحدد جميع طرق الوحدة النمطية على فئة اعتراض سجل بدء التشغيل. معلومات أخرى على @logeven تحدد السجل. @service @logenable // بدء تشغيل log اعتراض @logevent (module = moduletype.student) فئة عامة studenterviceImpl تنفذ iStudentService { @ @ @logevent (event = eventtype.deLete_single ، desc = "delete record") System.out.printf (this.getClass () + "deleteById id =" + id) ؛ } OverrideLogevent (event = eventtype.add ، desc = "Save Record") // إضافة معرف السجل العام int Save (SustudentModel StudentModel) {system.out.printf (this.getClass () + "save =" + json.tojsontring (studentModel))) ؛ العودة 1 ؛ } OverRideLogevent (event = eventtype.update ، desc = "update record") // add update update public update public eduction (sustureModel studentModel) {system.out.printf (this.getClass () + "save update =" + json.tojsontring (studentModel)) ؛ } // لا يوجد معرف سجل Override public void querybyid (string id) {system.out.printf (this.getClass () + "querybyid id =" + id) ؛ }}قم بتنفيذ فئة الاختبار وطباعة المعلومات التالية للإشارة إلى أن تكوين التعليقات التوضيحية الخاصة بنا يتم تمكينه:
قم بتخزين السجلات في قاعدة البيانات ، ومحتوى السجل هو كما يلي:
{"admevent": "4" ، "admmodel": "1" ، "admoptContent": "{/7. الكود
انظر أدناه للحصول على الكود التفصيلي أعلاه
رمز github ، يرجى محاولة استخدام علامة V0.21 ، لا تستخدم Master ، لأنني لا أستطيع أن أضمن أن الرمز الرئيسي سيبقى دون تغيير