最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中實現(xiàn)日志記錄的方案總結(jié)

 更新時間:2024年12月09日 08:21:27   作者:小碼A夢  
在平時使用到一些軟件中,比如某寶或者某書,通過記錄用戶的行為來構(gòu)建和分析用戶的行為數(shù)據(jù),這就需要使用到日志系統(tǒng)來存儲或者記錄數(shù)據(jù),小編為大家整理了幾種Java日志方案,希望對大家有所幫助

在平時使用到一些軟件中,比如某寶或者某書,通過記錄用戶的行為來構(gòu)建和分析用戶的行為數(shù)據(jù),同時也能更好優(yōu)化產(chǎn)品設(shè)計和提升用戶體驗。比如在一個訂單系統(tǒng)中,需要確定追蹤用戶的行為,比如:

  • 登錄/登出
  • 瀏覽商品
  • 加購商品
  • 搜索商品關(guān)鍵字
  • 下單

上述行為就需要使用到日志系統(tǒng)來存儲或者記錄數(shù)據(jù),Java 有幾種日志方案,簡單介紹幾種實現(xiàn)方案,以及需要注意的點。

日志添加需要注意問題

根據(jù)業(yè)務(wù)的不同,需要使用匹配到合適的日志方案。也需要注意幾個問題:

  • 不能影響原來的業(yè)務(wù)邏輯。
  • 不能報錯,即使報錯,不能影響原有的業(yè)務(wù)代碼。
  • 對于耗時的日志代碼,使用異步方法
  • 侵入性低,盡量少改動原始代碼

Spring AOP

Spring AOP 通過切面編程實現(xiàn)不修改原有代碼,而動態(tài)添加功能的能力。這種方式有以下幾個好處:

  • 侵入性低
  • 可重用性強

本文使用基于注解的 AOP,首先定義一個切面注解 AopTest:

/**
 * 切面注解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AopTest {
}

再創(chuàng)建通知 @Around :

@Around("@annotation(com.test.annotation.AopTest)")
public Object annotationTest(ProceedingJoinPoint joinPoint) throws Throwable {
    log.info("執(zhí)行前");
    Object result = joinPoint.proceed(); // 執(zhí)行目標(biāo)方法
    Object[] args = joinPoint.getArgs();
    log.info("執(zhí)行后");
    return result;
}

一般都會在執(zhí)行后添加日志即可,想要在那個方法或者接口加日志,只需要在方法上添加注解即可,比如在接口添加注解:

@GetMapping
@AopTest
public String first(String param) {
    log.info("執(zhí)行first方法");
    return "result " + param;
}

請求接口后,就有如下的輸出:

執(zhí)行前
執(zhí)行first方法
執(zhí)行后

但是切面有一個問題,執(zhí)行切面報錯,方法也無法執(zhí)行,就需要捕獲異常,保證業(yè)務(wù)代碼正常執(zhí)行,改造一下上面的通知:

@Around("@annotation(com.test.annotation.AopTest)")
public Object annotationTest(ProceedingJoinPoint joinPoint) throws Throwable {log.info("執(zhí)行前");
    log.info("執(zhí)行前");
    Object result = joinPoint.proceed(); // 執(zhí)行目標(biāo)方法
    try {
        Object[] args = joinPoint.getArgs();
        // 添加日志
        log.info("執(zhí)行后");
        int a = 1/0;
    } catch (Exception e) {
        log.error(e.getMessage());
    }
    return result;
}

改造后,即使切面報錯,也不會影響業(yè)務(wù)代碼的執(zhí)行了。

AOP 是同步執(zhí)行的,如果日志添加是一個比較耗時的操作,也會影響接口的響應(yīng)速度,此時可以使用異步的方式,比如消息隊列。

總結(jié)一下,Spring AOP 有以下幾個優(yōu)點和缺點。

優(yōu)點:

  • 侵入性低
  • 可重用性強

缺點及解決方案:

1、切面報錯可能會影響業(yè)務(wù)代碼

問題:在切面的異常如果沒有正確處理,可能會影響業(yè)務(wù)代碼的正常執(zhí)行。

解決方案:

  • 捕獲異常,確保業(yè)務(wù)代碼正常執(zhí)行
  • 一般使用try catch 捕獲異常,防止向上傳播

2、同步執(zhí)行會影響接口響應(yīng)速度

問題:如果切面中存在耗時的操作,同步操作會導(dǎo)致接口的響應(yīng)速度變慢。

解決方案:

  • 通過消息隊列將耗時操作異步執(zhí)行
  • 使用 @Async 將方法異步執(zhí)行,將任務(wù)從主線程脫離出來,交給其他線程池執(zhí)行

事件監(jiān)聽 + 異步

Spring 事件監(jiān)聽機制是一種發(fā)布-訂閱模式,將事件的發(fā)布和監(jiān)聽解耦開來。通過這種機制,事件的發(fā)布者無需關(guān)注監(jiān)聽的邏輯,監(jiān)聽者也無需直接依賴發(fā)布者。

Spring 事件監(jiān)聽有三個部分組成:

1.事件

自定義一個事件,繼承 ApplicationEvent:

@Getter
@Setter
public class DemoEvent extends ApplicationEvent {

    private String name;

    public DemoEvent(Object source) {
        super(source);
    }
}

2.事件監(jiān)聽

基于 @EventListener 注解監(jiān)聽事件:

@Component
@Slf4j
public class DemoEventListener {

  @EventListener
  public void handleEvent(DemoEvent event){
      log.info(event.getName());
      log.info("事件監(jiān)聽");

  }
}

3.事件發(fā)布

使用 applicationEventPublisher.publishEvent 方法發(fā)布事件,

@Autowired
private ApplicationEventPublisher applicationEventPublisher;

@Override
public void publish() {
    // 執(zhí)行業(yè)務(wù)代碼
    log.info("執(zhí)行登錄,當(dāng)前時間 {}",LocalTime.now());
    DemoEvent event = new DemoEvent(this);
    event.setName("hello");
    applicationEventPublisher.publishEvent(event);
    log.info("完成登錄,當(dāng)前時間 {}",LocalTime.now());
    log.info("執(zhí)行 service");
}

配置好事件的發(fā)布和監(jiān)聽之后,在業(yè)務(wù)代碼添加事件的發(fā)布,監(jiān)聽方法內(nèi)添加日志的記錄。

Spring 事件監(jiān)聽雖然解耦了發(fā)布和監(jiān)聽,只是解耦邏輯代碼,兩者還是同步執(zhí)行,并且都是在同一個線程執(zhí)行的,所以事件監(jiān)聽也無法解決添加日志報錯,以及耗時的問題。

4.驗證監(jiān)聽方法是否同步

在事件監(jiān)聽添加延遲:

  @EventListener
  public void handleEvent(DemoEvent event){
      try {
          Thread.sleep(2000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      log.info(event.getName());
      log.info("事件監(jiān)聽");

  }

控制臺輸出:

執(zhí)行登錄,當(dāng)前時間 16:52:30.799
hello
事件監(jiān)聽
完成登錄,當(dāng)前時間 16:52:33.799
執(zhí)行 service

接口執(zhí)行了 3 秒多,并且 publish 方法要等待監(jiān)聽方法執(zhí)行完畢之后才能執(zhí)行,說明事件監(jiān)聽是同步的

5.驗證監(jiān)聽方法報錯是否會影響主流程

在監(jiān)聽方法添加錯誤代碼:

@EventListener
public void handleEvent(DemoEvent event){
    int a = 1/0;
    log.info(event.getName());
    log.info("事件監(jiān)聽");

}

控制臺輸出:

執(zhí)行登錄,當(dāng)前時間 17:10:08.396
java.lang.ArithmeticException: / by zero

監(jiān)聽方法報錯,接口也報錯,業(yè)務(wù)代碼無法執(zhí)行,說明監(jiān)聽方法報錯會影響事件發(fā)布方法。

解決報錯的問題,使用異常捕獲即可。而延遲的問題,就需要使用到異步的操作,異步就是另啟一個線程執(zhí)行監(jiān)聽方法,異步除了能解決延遲的問題,也順便解決了報錯的問題。

實現(xiàn)異步在監(jiān)聽方法上添加 @Async 異步注解,監(jiān)聽方法添加延遲和錯誤代碼:

執(zhí)行登錄,當(dāng)前時間 17:21:50.971
完成登錄,當(dāng)前時間 17:21:50.974
執(zhí)行 service

publish 方法既不會延遲,也不會因為監(jiān)聽報錯影響執(zhí)行,異步完美解決耗時和報錯的問題

消息隊列

海量日志場景,消息隊列是一個很好的選擇,它也是解耦了發(fā)布者和訂閱者,如果訂閱者開啟了手動確認(rèn),消費者也需要使用 try catch 捕獲異常信息,確保消息能正常消費。

總結(jié)

本文介紹幾種日志記錄的實現(xiàn)方案:

  • Spring AOP:
    • 優(yōu)點: 侵入性低,代碼可重復(fù)性強
    • 問題以及解決方案:
      • 切面中可能會報錯,報錯會影響業(yè)務(wù)代碼的正常執(zhí)行,解決方法是使用 try catch 捕獲異常。
      • 日志記錄會影響業(yè)務(wù)代碼執(zhí)行效率,可以使用消息隊列異步執(zhí)行日志操作
  • 事件監(jiān)聽 + 異步
    • 優(yōu)點: 解耦業(yè)務(wù)邏輯和日志記錄,提升代碼的內(nèi)聚性。
    • 缺點以及解決方案:
      • AOP 存在的問題,事件監(jiān)聽同樣存在,報錯和耗時都會影響業(yè)務(wù)代碼。報錯可以使用異常捕獲,延遲問題可以使用異步方式解決,而異步另起線程也順便解決了報錯影響業(yè)務(wù)代碼的問題。
  • 消息隊列
    • 優(yōu)點: 使用于高并發(fā)日記記錄場景
    • 問題: 增加系統(tǒng)的復(fù)雜性和穩(wěn)定性,還需要考慮消息的丟失和重復(fù)消費問題。

到此這篇關(guān)于Java中實現(xiàn)日志記錄的方案總結(jié)的文章就介紹到這了,更多相關(guān)Java日志記錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot項目接入MQTT的詳細指南

    SpringBoot項目接入MQTT的詳細指南

    MQTT是一種輕量級的消息傳輸協(xié)議,特別適用于物聯(lián)網(wǎng)(IoT)場景,具有低帶寬、高延遲網(wǎng)絡(luò)環(huán)境下的優(yōu)勢,SpringBoot作為流行的 Java開發(fā)框架,能夠方便地與MQTT集成,實現(xiàn)高效的消息通信,本文將詳細介紹如何在SpringBoot項目中接入MQTT,需要的朋友可以參考下
    2025-03-03
  • Mybatis如何通過接口實現(xiàn)sql執(zhí)行原理解析

    Mybatis如何通過接口實現(xiàn)sql執(zhí)行原理解析

    為了簡化MyBatis的使用,MyBatis提供了接口方式自動化生成調(diào)用過程,可以大大簡化MyBatis的開發(fā),下面這篇文章主要給大家介紹了關(guān)于Mybatis如何通過接口實現(xiàn)sql執(zhí)行原理解析的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • Mybatis Plus插件三種方式的逆向工程的使用

    Mybatis Plus插件三種方式的逆向工程的使用

    這篇文章主要介紹了Mybatis Plus插件三種方式的逆向工程的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java實現(xiàn)根據(jù)模板高效生成Word文檔

    Java實現(xiàn)根據(jù)模板高效生成Word文檔

    在日常辦公中,我們經(jīng)常需要生成標(biāo)準(zhǔn)化的Word文檔,手工填充內(nèi)容不僅繁瑣,而且容易出錯,下面小編就和大家詳細講講如何使用Java根據(jù)模板生成Word文檔吧
    2026-03-03
  • JavaEE開發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    JavaEE開發(fā)基于Eclipse的環(huán)境搭建以及Maven Web App的創(chuàng)建

    本文主要介紹了如何在Eclipse中創(chuàng)建的Maven Project,本文是JavaEE開發(fā)的開篇,也是基礎(chǔ)。下面內(nèi)容主要包括了JDK1.8的安裝、JavaEE版本的Eclipse的安裝、Maven的安裝、Tomcat 9.0的配置、Eclipse上的M2Eclipse插件以及STS插件的安裝。
    2017-03-03
  • maven配置阿里云倉庫的實現(xiàn)方法(2022年)

    maven配置阿里云倉庫的實現(xiàn)方法(2022年)

    本文主要介紹了maven配置阿里云倉庫的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 實例詳解SpringMVC入門使用

    實例詳解SpringMVC入門使用

    大家好,本篇文章主要講的是實例詳解SpringMVC入門使用,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • jvm中指定時區(qū)信息user.timezone問題及解決方式

    jvm中指定時區(qū)信息user.timezone問題及解決方式

    同一份程序使用時間LocalDateTime類型,在國內(nèi)和國外部署后,返回的時間信息前端使用出問題,這篇文章主要介紹了jvm中指定時區(qū)信息user.timezone問題及解決方法,需要的朋友可以參考下
    2023-02-02
  • Spring事件監(jiān)聽機制觀察者模式詳解

    Spring事件監(jiān)聽機制觀察者模式詳解

    這篇文章主要為大家介紹了Spring事件監(jiān)聽機制觀察者模式實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • java圖片添加水印實例代碼分享

    java圖片添加水印實例代碼分享

    這篇文章主要為大家詳細介紹了java圖片添加水印實例代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-12-12

最新評論

怀仁县| 和林格尔县| 河间市| 绥宁县| 申扎县| 许昌市| 闽清县| 醴陵市| 江城| 洛扎县| 博白县| 巢湖市| 玛曲县| 张家界市| 西昌市| 娱乐| 彰武县| 绥芬河市| 姚安县| 阿巴嘎旗| 福建省| 西昌市| 凉山| 都昌县| 江达县| 毕节市| 苗栗市| 罗城| 道孚县| 全南县| 北宁市| 冀州市| 孟村| 华池县| 祁东县| 鹤壁市| 阳曲县| 高要市| 青浦区| 饶平县| 安义县|