AOP teknolojisini kullanarak SpringBoot'a dayalı işlem günlüğü yönetimini gerçekleştirin

1. Temel kavramlar

Bahar özelliklerine beş tür bildirim uygulanabilir:

Bildirimden önce (Önce): hedef yöntem çağrılmadan önce çağrı bildirimi

Bildirimden sonra (Sonra): hedef yöntem tamamlandıktan sonra çağrı bildirimi (normal veya anormal çıkıştan bağımsız olarak)

Döndükten sonra: Hedef yöntem başarıyla yürütüldükten sonra bildirimi çağırın

İstisna bildirimi (Atma sonrası): hedef yöntem bir istisna attıktan sonra çağrı bildirimi

Çevresinde bildirim (Çevresinde): Bildirim, bildirilen yöntemi sarar ve bildirilen yöntem çağrılmadan önce ve sonra özel davranışlar gerçekleştirir.

Yürütme emri:

Sonraki temel uygulamalar Surround bildirim , Önceden haber , Bildirim gönder , İade bildirimi , İstisna bildirimi Uygulamayı gerçekleştirin ve yürütme sırasını gösterin.

2. Temel uygulama

Beyanname bildirimi

Yukarıdaki yürütme sırasını doğrulamak için aşağıdaki kodu kopyalayabilirsiniz.

@Görünüş

public class Test {

private static int adım = 0;

@Pointcut ("@ annotation (com.chenyanwu.erp.erpframework.annotation.Log)") // nokta kesim ifadesi

özel void işlemi () {}

@Before ("işlem ()")

public void doBeforeTask () {

System.out.println (++ adım + "Ön bildirim");

}

@After ("işlem ()")

public void doAfterTask () {

System.out.println (++ adım + "bildirim sonrası");

}

@AfterReturning (pointcut = "işlem ()", dönen = "retVal")

public void doAfterReturnningTask (Object retVal) {

System.out.println (++ adım + "dönüş bildirimi, dönüş değeri:" + retVal.toString ());

}

@AfterThrowing (pointcut = "operation ()", throwing = "ex")

public void doAfterThrowingTask (Exception ex) {

System.out.println (++ step + "İstisna bildirimi, istisna bilgisi:" + ex.getMessage ());

}

/ **

* Surround bildirimlerinin ProceedingJoinPoint türü parametreleri taşıması gerekir

* Çevreleyen bildirim, dinamik aracının tüm sürecine benzer ProceedingJoinPoint türü parametreleri, hedef yöntemin çalıştırılıp çalıştırılmayacağını belirleyebilir

* Ve çevreleyen bildirim bir dönüş değerine sahip olmalıdır, dönüş değeri hedef yöntemin dönüş değeridir

* /

// @ Etrafında ("işlem ()")

public Object doAroundTask (ProceedingJoinPoint pjp) {

Dize yöntemadı = pjp.getSignature (). GetName ();

Nesne sonucu = boş;

Deneyin {

// Ön bildirim

System.out.println ("hedef yöntem" + yöntem adı + "start, parametre" + Arrays.asList (pjp.getArgs ()));

// hedef yöntemi çalıştır

sonuç = pjp.proceed ();

// bildirim döndür

System.out.println ("hedef yöntem" + yöntem adı + "başarıyla yürütülür," + sonuç döndürülür);

} catch (Throwable e) {

// İstisna bildirimi

System.out.println ("hedef yöntem" + yöntem adı + "istisna atar:" + e.getMessage ());

}

// Bildirim gönder

System.out.println ("Hedef Yöntem" + yöntem adı + "Son");

dönüş sonucu;

}

}

Dikkat edilmesi gereken bir nokta, giriş noktasıdır: @ Pointcutın ifadesi

biçim:

yürütme (değiştiriciler-model? ret-tip-model bildiren-tip-model? isim-model (param-model) atar-model?)

Parantez içindeki her desen şu anlama gelir:

  • Değiştirici eşleştirme (değiştirici-desen?)
  • Dönüş değeri eşleşmesi (ret-type-pattern) herhangi bir dönüş değerini, tam yolun sınıf adını vb. Belirtmek için * olabilir.
  • Sınıf yolu eşleştirme (bildiren-tip-desen?)
  • Yöntem adı eşleştirme (ad-desen) yöntem adını belirtebilir veya tümünü temsil edebilir, set, set ile başlayan tüm yöntemleri temsil eder
  • Parametre eşleştirme ((param-pattern)) belirli parametre türlerini belirtebilir, birden fazla parametre "," ile ayrılır, her parametre ayrıca "" ile temsil edilebilir - (String) gibi herhangi bir parametre türünü eşleştirme Dize parametresi yöntemi; (, String) iki parametreyle eşleşen bir yöntem anlamına gelir. İlk parametre herhangi bir türde olabilir ve ikinci parametre String türündedir; (...) sıfır veya daha fazla rastgele parametreyi temsil etmek için kullanılabilir
  • İstisna türü eşleştirme (atar-desen?)
  • Sonrasında "?" Olanlar isteğe bağlıdır

Misal:

1) yürütme (* ())

// Tüm yöntemlerle eşleşme anlamına gelir

2) yürütme (genel * com. Savage.service.UserService. ())

// com.savage.server.UserService içindeki tüm genel yöntemlerin eşleştiğini gösterir

3) yürütme (* com.savage.server. ())

// com.savage.server paketi ve alt paketleri altındaki tüm yöntemlerin eşleştiğini gösterir

Üç, günlük yönetimi gerçek savaş

Yukarıdaki temel uygulamanın anlaşılmasıyla, şimdi kodu doğrudan yapıştırıyoruz:

1. Bağımlı kavanoz paketi

org.springframework.boot

Spring-boot-starter-aop

2. Özel ek açıklamalar

@Target (ElementType.METHOD)

@Retention (RetentionPolicy.RUNTIME)

public @interface Günlüğü {

Dize değeri () varsayılan "";

}

3. Yönün farkına varın

@Görünüş

@Sipariş (5)

@Bileşen

public class LogAspect {

private Logger logger = LoggerFactory.getLogger (LogAspect.class);

@Autowired

özel ErpLogService logService;

@Autowired

ObjectMapper objectMapper;

özel ThreadLocal startTime = new ThreadLocal ();

@Pointcut ("@ annotation (com.chenyanwu.erp.erpframework.annotation.Log)")

public void pointcut () {

}

/ **

* Ön bildirim, Kontrolör katmanı işleminden önce müdahale edin

*

* @param joinPoint giriş noktası

* /

@Before ("pointcut ()")

public void doBefore (JoinPoint joinPoint) {

// Geçerli çağrı zamanını alın

startTime.set (yeni Tarih ());

}

/ **

* Normal getiri

*

* @param joinPoint giriş noktası

* @param rvt normal sonucu

* /

@AfterReturning (pointcut = "pointcut ()", dönen = "rvt")

public void doAfter (JoinPoint joinPoint, Object rvt) Exception {atar {

handleLog (joinPoint, null, rvt);

}

/ **

* Anormal bilgi yakalama

*

* @param joinPoint

* @param e

* /

@AfterThrowing (pointcut = "pointcut ()", throwing = "e")

public void doAfter (JoinPoint joinPoint, Exception e) Exception {atar {

handleLog (joinPoint, e, null);

}

@Async

private void handleLog (son JoinPoint birleştirme Noktası, nihai İstisna e, Nesne rvt) İstisna {

// yorum al

Yöntem yöntem = getMethod (joinPoint);

Günlük günlüğü = getAnnotationLog (yöntem);

eğer (log == null) {

dönüş;

}

Şimdiki tarih = yeni Tarih ();

// İşlem veritabanı günlük tablosu

ErpLog erpLog = yeni ErpLog ();

erpLog.setErrorCode (0);

erpLog.setIsDeleted (0);

// Bilgi isteme

HttpServletRequest isteği = ToolUtil.getRequest ();

erpLog.setType (ToolUtil.isAjaxRequest (istek)? "Ajax isteği": "Normal istek");

erpLog.setTitle (log.value ());

erpLog.setHost (request.getRemoteHost ());

erpLog.setUri (request.getRequestURI (). toString ());

// erpLog.setHeader (request.getHeader (HttpHeaders.USER_AGENT));

erpLog.setHttpMethod (request.getMethod ());

erpLog.setClassMethod (joinPoint.getSignature (). getDeclaringTypeName () + "." + joinPoint.getSignature (). getName ());

// İstenen yöntem parametresi değeri

Nesne bağımsız değişkenleri = joinPoint.getArgs ();

// İstenen yöntem parametresi adı

LocalVariableTableParameterNameDiscoverer u

= new LocalVariableTableParameterNameDiscoverer ();

String paramNames = u.getParameterNames (yöntem);

eğer (değiştirgeler! = null paramNames! = null) {

StringBuilder parametreleri = new StringBuilder ();

params = handleParams (params, args, Arrays.asList (paramNames));

erpLog.setParams (params.toString ());

}

String retString = JsonUtil.bean2Json (rvt);

erpLog.setResponseValue (retString.length ()> 5000? JsonUtil.bean2Json ("İstek parametresi verileri görüntülenemeyecek kadar uzun"): retString);

eğer (e! = null) {

erpLog.setErrorCode (1);

erpLog.setErrorMessage (e.getMessage ());

}

Tarih stime = startTime.get ();

erpLog.setStartTime (stime);

erpLog.setEndTime (şimdi);

erpLog.setExecuteTime (şimdi.getTime () - stime.getTime ());

erpLog.setUsername (MySysUser.loginName ());

HashMap browserMap = ToolUtil.getOsAndBrowserInfo (istek);

erpLog.setOperatingSystem (browserMap.get ("os"));

erpLog.setBrower (browserMap.get ("tarayıcı"));

erpLog.setId (IdUtil.simpleUUID ());

logService.insertSelective (erpLog);

}

/ **

* Yorum var mı, varsa anla

* /

private Log getAnnotationLog (Yöntem yöntemi) {

eğer (yöntem! = null) {

dönüş method.getAnnotation (Log.class);

}

boş döndür;

}

özel Yöntem getMethod (JoinPoint joinPoint) {

İmza imzası = joinPoint.getSignature ();

MethodSignature methodSignature = (MethodSignature) imza;

Yöntem yöntem = methodSignature.getMethod ();

eğer (yöntem! = null) {

iade yöntemi;

}

boş döndür;

}

private StringBuilder handleParams (StringBuilder parametreleri, Object args, List paramNames) JsonProcessingException {

for (int i = 0; i

Best Express, 13 tonluk "Double 11" bir ekspres kamyonun alev aldığını söyledi: yeniden düzenleme ve tazminat gerçekleştirildi
önceki
İnternet ünlü sebze pazarını ciddi bir şekilde ziyaret ettikten sonra, bunun sadece fotoğraf çekmek ve iyi görünmekle ilgili olmadığını gördük.
Sonraki
İtfaiyeci günü ve "yarım"
Zhejiang'ın açılışı ve Hangzhou'da "One Belt One Road" Think Tank Forumu düzenlendi
Çin'deki bu yüksek teknoloji projesi Batılı bilim adamlarının özel ilgisini çekti.Yabancı medya: Çin'in bir vizyonu var
Yeni otel | Hoshino Resorts, Japonya'da kendi çiftliği olan bir tatil oteli açtı
Süper yanma! Alipay teknolojisi çift 11 belgeseli "One Heart One Battle" özel dünya prömiyeri
Şangay'ın en batı gece pazarı geri döndü! Hafta sonları alışveriş ve yemek için eksiksiz bir rehber
Double Eleven Express'iniz yine otoyolda mı yandı? Cainiao İstasyonu bu mesajı hiç göndermedi
En iyi matematikçiler ne kadar korkunç olabilir? Gerçek ortaya çıkar, insanları bu gerçeğe inanamaz hale getirir
Uluslararası Hoşgörü Günü | Başkalarına karşı hoşgörülü olmak, kendinize yumuşak davranmaktır
Kunqu Operası "Şakayık Köşkü" Avrupa'da bir arkadaş bulur, "Du Liniang Çin'in Uyuyan Güzelidir"
Duygusal rezonans elde etmek için kullanıcıların seslerini dinlemek: "Kullanıcı merkezli", FAW-Volkswagen Audi'nin kazanan sırrıdır
Öngörülemeyen! Doğu'nun dibi Batı'da altıncı oldu, Jazz 372 sayı gerideydi
To Top