自定義註解,利用AOP實現日誌保存(資料庫),代碼全貼,複製就能用

来源:https://www.cnblogs.com/blbl-blog/archive/2022/08/25/16625397.html
-Advertisement-
Play Games

前言 1,在一些特定的場景我們往往需要看一下介面的入參,特別是跨系統的介面調用(下發,推送),這個時候的介面入參就很重要,我們保存入參入庫,如果出問題就可以馬上定位是上游還是下游的問題(方便扯皮) 2,還有一般需要在系統中看普通日誌,還有特殊的異常(報錯)日誌,一般我們可以通過伺服器去查看相應的位置 ...


前言

1,在一些特定的場景我們往往需要看一下介面的入參,特別是跨系統的介面調用(下發,推送),這個時候的介面入參就很重要,我們保存入參入庫,如果出問題就可以馬上定位是上游還是下游的問題(方便扯皮)

2,還有一般需要在系統中看普通日誌,還有特殊的異常(報錯)日誌,一般我們可以通過伺服器去查看相應的位置,但是由於伺服器是一直運行的,日誌是一直在生成的,這個時候就不太方便。

3,保存入參,我們之間本地調試的時候就可以不用造數據,這個也是很方便的,只需改改就好。

這個時候就體現入參請求和相應結果的重要性

Aop基本概念

Aspect(切麵): Aspect 聲明類似於 Java 中的類聲明,在 Aspect 中會包含著一些 Pointcut 以及相應的 Advice。
Joint point(連接點):表示在程式中明確定義的點,典型的包括方法調用,對類成員的訪問以及異常處理程式塊的執行等等,它自身還可以嵌套其它 joint point。
Pointcut(切點):表示一組 joint point,這些 joint point 或是通過邏輯關係組合起來,或是通過通配、正則表達式等方式集中起來,它定義了相應的 Advice 將要發生的地方。
Advice(增強):Advice 定義了在 Pointcut 裡面定義的程式點具體要做的操作,它通過 before、after 和 around 來區別是在每個 joint point 之前、之後還是代替執行的代碼。
Target(目標對象):織入 Advice 的目標對象.。
Weaving(織入):將 Aspect 和其他對象連接起來, 並創建 Adviced object 的過程

自定義註解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserAccess {
    String desc() default "無信息";
}

對自定義註解進行aop切麵

一般使用更加詳細的日誌切麵

@Component
@Aspect
public class UserAccessAspect {

    // 這裡就是對上面進行切麵
    @Pointcut(value = "@annotation(com.xncoding.aop.aspect.UserAccess)")
    public void access() {

    }

    @Before("access()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
        System.out.println("second before");
    }

    @Around("@annotation(userAccess)")
    public Object around(ProceedingJoinPoint pjp, UserAccess userAccess) {
        //獲取註解里的值
        System.out.println("second around:" + userAccess.desc());
        try {
            return pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }
}

日誌切麵

如果想保存到資料庫或者進行更加詳細的日誌列印就可以使用下麵的日誌切麵,

這裡目前是列印,如果想保存到資料庫,可以創建相應的實體,set進去,然後進行insert到資料庫,如果使用mybatis-plus是很方便的,先創建表,然後用mybatis-plus 自動生成代碼,再用相應的mapper.inster() 保存到資料庫。

/**
 * 日誌切麵
 */
@Aspect
@Component
public class LogAspect {
    // 這個目前是對從 com.xncoding.aop.controller.* 下的都進行切入,如果想對上面的自定義註解進行切入,只需改成相對應的路徑
    // 例如:@Pointcut(value = "@annotation(com.xncoding.aop.aspect.UserAccess)")
    @Pointcut("execution(public * com.xncoding.aop.controller.*.*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內容
        System.out.println("方法的返回值 : " + ret);
    }

    //後置異常通知
    @AfterThrowing("webLog()")
    public void throwss(JoinPoint jp){
        System.out.println("方法異常時執行.....");
    }

    //後置最終通知,final增強,不管是拋出異常或者正常退出都會執行
    @After("webLog()")
    public void after(JoinPoint jp){
        System.out.println("方法最後執行.....");
    }

    //環繞通知,環繞增強,相當於MethodInterceptor
    @Around("webLog()")
    public Object arround(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("方法環繞start.....");
        try {
            Object o =  pjp.proceed();
            System.out.println("方法環繞proceed,結果是 :" + o);
            return o;
        } catch (Throwable e) {
            throw e;
        }
    }
}

測試controller

@RestController
@RequestMapping("aop")
public class UserController {
    @GetMapping("/first")
    public Object first() {
        return "first controller";
    }

    @GetMapping("/doError")
    public Object error() {
        return 1 / 0;
    }

	@GetMapping("/second")
    @UserAccess(desc = "second")
    public Object second() {
        return "second controller 666";
    }

    @PostMapping("/user")
    public void userPost(@RequestBody UserVo userVo){
        System.out.println("我user進來了");
    }

}

user類

@Data
public class UserVo {

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性別")
    private Integer sex;
}

創建表SQL語句

CREATE TABLE `sys_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `log_type` varchar(50) NOT NULL COMMENT '日誌類型',
  `create_user_code` varchar(64) NOT NULL COMMENT '創建用戶編碼',
  `create_user_name` varchar(100) NOT NULL COMMENT '創建用戶名稱',
  `create_date` datetime NOT NULL COMMENT '創建時間',
  `request_uri` varchar(500) DEFAULT NULL COMMENT '請求URI',
  `request_method` varchar(10) DEFAULT NULL COMMENT '請求方式',
  `request_params` text COMMENT '請求參數',
  `response_params` text COMMENT '響應參數',
  `request_ip` varchar(20) NOT NULL COMMENT '請求IP',
  `server_address` varchar(50) NOT NULL COMMENT '請求伺服器地址',
  `is_exception` char(1) DEFAULT NULL COMMENT '是否異常',
  `exception_info` text COMMENT '異常信息',
  `start_time` datetime NOT NULL COMMENT '開始時間',
  `end_time` datetime NOT NULL COMMENT '結束時間',
  `execute_time` int(11) DEFAULT NULL COMMENT '執行時間',
  `user_agent` varchar(500) DEFAULT NULL COMMENT '用戶代理',
  `device_name` varchar(100) DEFAULT NULL COMMENT '操作系統',
  `browser_name` varchar(100) DEFAULT NULL COMMENT '瀏覽器名稱',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_sys_log_lt` (`log_type`) USING BTREE,
  KEY `idx_sys_log_cub` (`create_user_code`) USING BTREE,
  KEY `idx_sys_log_ie` (`is_exception`) USING BTREE,
  KEY `idx_sys_log_cd` (`create_date`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1560559854462500867 DEFAULT CHARSET=utf8 COMMENT='系統日誌表';

測試

請求參數:

debug圖片

這裡只是做列印,也可以在切麵裡面保存到資料庫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 很多小伙伴不知道Color Efex Pro 4是用來幹嘛的,小編給大家介紹一下,Color Efex Pro 4 for Mac全球最全面,最有創意的濾鏡組,用於色彩校正,潤飾和應用最令人驚嘆和最富想象力的攝影效果,釋放最大的創造力和想象力。 詳情:Color Efex Pro 4 for Mac ...
  • 1. 關聯關係 1.1 關聯關係概念說明 表與表之間的關係 : 1 對 1 1對多 多對多關係 ,通過主外鍵來實現。 外鍵在多的一方。比如員工和部門: 1個員工對應一個部門,一個部門可以有多個員工 要將表與表之間的關係:映射稱為 類與類之間的關係(準確的說應該是 對象和對象之間的關係 ) 一對一 夫 ...
  • 學習Stream的目的 函數式編程漸漸變成主流,為了看懂同事的代碼。 相對於傳統的編程方式,代碼更為簡潔清晰易懂。 使得併發編程變得如此簡單。 有效的避免了代碼嵌套地獄。(見樣例) if (條件1) { if (條件2) { if (條件3) { // 再嵌套下去都快見到Diablo了。 } } } ...
  • 目錄 一.OpenGL 波浪特效效果演示 1.原始圖片 2.效果演示 二.OpenGL 波浪特效源碼下載 三.猜你喜歡 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目 ...
  • ##redis是什麼? Redis(Remote Dictionary Server ),即遠程字典服務,是一個開源的使用ANSI C語言編寫、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。 redis是一個key-value存儲系統。和Memcached ...
  • Java集合09 18.TreeSet 元素無序:插入順序和輸出順序不一致 可以按照一定的規則進行排序,具體排序方式取決於構造方法: TreeSet () :根據其元素的自然排序進行排序 TreeSet (Comparator comparator) :根據指定的比較器進行排序 沒有帶索引的方法,所 ...
  • 1、獲取bean實例的三種方式 1.1 id 屬性 1.1.1 jar <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.18.RELEASE</sp ...
  • 最近寫項目發現pythoncom 導入 win32api、win32con、win32com、win32gui 等win32相關的包都會出現或多或少問題,Google一大堆不靠譜的方法試了個遍。 特此記錄一下解決辦法 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...