SpringBoot之日誌註解和快取優化

xbhog發表於2021-10-16

SpringBoot之日誌註解和快取優化

日誌註解:

關於SpringBoot中的日誌處理,在之前的文章中頁寫過:

點選進入

image-20211016162803738

這次通過註解+Aop的方式來實現日誌的輸出;

首先需要定義一個註解類:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {
    String module() default "";  //模組名
    String operation() default ""; //操作名
}

然後定義切點:

//定義切點
@Pointcut("@annotation(com.xbhog.springbootvueblog.common.aop.LogAnnotation)")
public void logPointCut() {
}

白話文就是,註解所到之處都是切點;比較專業的解釋的話可以自行百度或者Google;

有了切點,那麼我們需要實現通知事件,這裡採用了環繞通知,也就是前後都會增強。

//環繞  處理流之前 和之後
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
    long beginTime = System.currentTimeMillis();
    //執行方法
    Object result = point.proceed();
    //執行時長(毫秒)
    long time = System.currentTimeMillis() - beginTime;
    //儲存日誌
    recordLog(point, time);
    return result;
}

point.proceed()就是註解下所需要執行的方法;類似於下面程式碼段:

@LogAnnotation(module = "listArticle", operation = "顯示主頁展示資料")
public Result listArticle(@RequestBody PageParams pageParams) {
    return articleService.listArticle(pageParams);
}

然後我們需要設定日誌輸出的資訊(recordLog),這裡我們通過反射來獲得相應的類名和方法名以及其他資訊等。

private void recordLog(ProceedingJoinPoint joinPoint, long time) {
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
    log.info("=====================log start================================");
    log.info("module:{}",logAnnotation.module());
    log.info("operation:{}",logAnnotation.operation());

    //請求的方法名
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = signature.getName();
    log.info("request method:{}",className + "." + methodName + "()");

    //請求的引數
    Object[] args = joinPoint.getArgs();
    String params = JSON.toJSONString(args[0]);
    log.info("params:{}",params);

    //獲取request 設定IP地址
    HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
    log.info("ip:{}", IpUtils.getIpAddr(request));


    log.info("excute time : {} ms",time);
    log.info("=====================log end================================");
}

這樣切點和切面已經完成了,使用的時候只需要在方法的上面直接加註解就可以獲得對應的方法的日誌資訊,這樣在上線的時候遇到報錯直接就可以定位到了。

快取的優化:

這個是在具體的專案中實現的,流程大體跟上面的實現類似,使用的也是註解實現的。

為什麼需要使用快取來提高網頁內容的訪問效率,因為記憶體的讀取比硬碟讀取的速度快的多的多,這樣對使用者的體驗比較好,但是不是所有的資料都得放到快取中,因為記憶體比磁碟貴的多,所以對哪些資料進行快取能使得使用者和伺服器均衡也需要一定的經驗。

Cache註解:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cache {
    long expire() default 1 * 60 * 1000;  //存活時間
    String name() default "";  //快取的名字
}

這裡設定了資料的存活時間和名字,使得資料在一定的時間裡可以在記憶體中讀取資料。

接下來看下快取的AOP實現:

直接來看下環繞通知的處理流程:

根據圖示,首先獲取類名和呼叫的方法名,然後設定兩個陣列,一個儲存引數型別一個儲存引數。

遍歷引數,將其轉換成字串,然後判斷字串引數(params)為不為空,不為空的話,加密當前字串引數,將當前的加密的密碼儲存到Redis中,每次進入該切面的時候,需要判斷RedisValue是否為空,如果為空的話,那麼需要執行註解下面的方法,如果不為空的話,直接從Redis中直接讀取資料顯示到前臺上。

通過日誌Aop與快取Aop的功能操作,實現效果如下:

image-20211016195110660

結束:

如果你看到這裡或者正好對你有所幫助,希望能點個?或者⭐感謝;

有錯誤的地方,歡迎在評論指出,作者看到會進行修改。

相關文章