日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

        歡迎訪問 生活随笔!

        生活随笔

        當前位置: 首頁 > 运维知识 > 数据库 >内容正文

        数据库

        SpringBoot + AOP + MySQL监控系统数据变更实战

        發布時間:2025/6/15 数据库 32 豆豆
        生活随笔 收集整理的這篇文章主要介紹了 SpringBoot + AOP + MySQL监控系统数据变更实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

        2019獨角獸企業重金招聘Python工程師標準>>>

        記錄一下Spring AOP切入DAO層,進行數據監控。
        在寫這個需求時,從網上找了很多的資料,大部分都是沒有解決相關問題的。當然也有少數部分解決,但用的還是SSM架構的xml配置。一開始我的出發點是通過注解@annotation的方式來切入DAO需要監控的方法,但是并沒有用。接下來剖析下個人的實現和思路。

        相關依賴

        • spring-boot-starter-web
        • mysql-connector-java
        • lombok
        • spring-boot-starter-aop
        • mybatis-spring-boot-starter

        Spring AOP兩種代理

        • jdk代理
          使用Java動態代理來創建AOP代理,在程序運行期間由JVM根據反射等機制動態的生成(當然此接口要有實現類)。
        • cglib代理
          代理類不是接口時,Spring會切換為使用CGLIB代理,它的工作原理是:直接在class字節碼文件添加增強的代碼。

        思路

        在這里只針對ADD、UPDATE、DELETE做相關數據處理。

        直接使用注解@annotation的方式是不能實現,所以我先通過execution的方式切到DAO層,再通過一個自定義注解區分數據操作的類型以及區分所操作的是哪一張表,具體詳情如下:

        • 記錄ADD操作:使用@After注解,由于新增一條數據中如果有自增的值,也需要把自增對應字段的值也要記錄,所有在執行完之后記錄
        • 記錄DELETE操作:使用@Before注解,在執行刪除之前,記錄原數據。如果在刪除之后再記錄的話,那條數據已經沒有了
        • 記錄UPDATE操作:使用@Around注解,記錄更新前后的數據,舊數據與新數據有父子關系,這樣數據才能一一對應。

        主要核心代碼

        • 自定義注解類
        @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuditAction {/*** 操作類型*/Action action() default Action.GET;/*** 目標table*/String targetTable() default ""; }
        • 操作類型枚舉類
        public enum Action {ADD,DELETE,UPDATE,GET }
        • 相關DAO層接口中,在需要監控的方法上加上注解
        @Mapper public interface CompanyDao {Company getCompanyByNum(int companyNum);@AuditAction(action = Action.ADD, targetTable = "company")int addCompany(Company company);@AuditAction(action = Action.UPDATE, targetTable = "company")int updateCompany(Company company);@AuditAction(action = Action.DELETE, targetTable = "company")int deleteCompany(int companyNum); }
        • 定義切面類
        @Slf4j @Aspect @Component public class SystemAudioAspect {// 省略相關業務代碼,詳細代碼請看博客末尾 }
        • 切面類: 監控DELETE操作
          • 對應DELETE操作,這里我采用在執行之前攔截@Before,@Before(value = "execution(public * com.jtcoding.auditlog.dao...delete(..))")** 攔截所有的delete*方法,通過@AuditAction注解來判定是否需要監控,再通過注解中的targetTable來區分對應是對哪個表的操作,具體代碼如下:
        /*** 攔截DELETE操作,記錄被刪除的數據* @param joinPoint*/ @Before(value = "execution(public * com.jtcoding.auditlog.dao..*.delete*(..))") public void doBefore(JoinPoint joinPoint) {// 獲取方法中的參數Object[] args = joinPoint.getArgs();// 獲取該方法上的 @AuditAction注解AuditAction audioAction = this.getAudioActionByJoinPoint(joinPoint);if (audioAction != null && audioAction.action() == Action.DELETE) {Object obj = null;String targetTable = audioAction.targetTable();switch (targetTable) {case "company":int companyNum = (int) args[0];obj = companyService.getCompanyByNum(companyNum);break;case "plan":int planNum = (int) args[0];obj = planService.getPlanByNum(planNum);break;}if (obj != null) {this.addAudioLog(obj, AuditLogDao.DELETE, targetTable, null);}} }
        • 切面類: 監控ADD操作
          • 原理與DELETE類似
        /*** 攔截ADD操作,記錄新增的數據* @param joinPoint*/ @After(value = "execution(public * com.jtcoding.auditlog.dao..*.add*(..))") public void doAfter(JoinPoint joinPoint) {// 獲取該方法上的 @AuditAction注解AuditAction audioAction = this.getAudioActionByJoinPoint(joinPoint);if (audioAction != null && audioAction.action() == Action.ADD) {Object obj = joinPoint.getArgs()[0];this.addAudioLog(obj, AuditLogDao.ADD, audioAction.targetTable(), null);} }
        • 切面類: 監控UPDATE操作
        /*** 攔截UPDATE操作,記錄更新前后的數據* @param pjp* @return* @throws Throwable*/ @Around(value = "execution(public * com.jtcoding.auditlog.dao..*.update*(..))") public Object doAround(ProceedingJoinPoint pjp) throws Throwable {AuditAction audioAction = this.getAudioActionByJoinPoint(pjp);Object proceed = null;if (audioAction != null && audioAction.action() == Action.UPDATE) {String uuid = UUID.randomUUID().toString();Object originalObj = null;Object arg = pjp.getArgs()[0];String targetTable = audioAction.targetTable();switch (targetTable) {case "company":Company company = (Company) arg;originalObj = companyService.getCompanyByNum(company.getCompanyNum());break;case "plan":Plan plan = (Plan) arg;originalObj = planService.getPlanByNum(plan.getPlanNum());break;}AuditLog auditLog = null;if (originalObj != null) {// TODO 在執行原方法之前,記錄舊數據auditLog = this.addAudioLog(originalObj, AuditLogDao.UPDATE, targetTable, null);}// 執行原方法proceed = pjp.proceed();// TODO 在執行原方法之后,記錄新數據if (auditLog != null) {this.addAudioLog(arg, AuditLogDao.UPDATE, targetTable, auditLog.getLogNum());}}if (proceed == null) {return pjp.proceed();}return proceed; }

        至此,有關切面核心的邏輯已經代碼已經完成,相關Service和Controller代碼,請看這里(源碼)

        測試

        • 通過Postman進行相關API測試
          • Add Company : /companies POST Request
          • Delete Company : /companies/{companyNum} DELETE Request
          • Update Company : /companies PUT Request
          • ............
        • 具體請求如下圖

          ?

          新增Company

          ?

          刪除Company

          ?

          獲取某一個Company

          ?

          修改Company

        DB結果

        數據庫數據

        • 由上圖可以看出:
          • 新增操作:記錄新增的數據
          • 刪除操作:記錄原來的數據
          • 更新操作:記錄原數據與新數據,兩條數據有一個父子關系,方便數據的關聯
          • log_type與log_table_name:可以非常清晰的看出操作的是哪張表以及操作類型
          • src_num:可以找到UPDATE操作,前后數據的關聯

        遺留問題

        • 問題1:監控變更的數據,這里使用的是MySQL數據庫,存儲類型是VARCHAR(255),所以很容易超出上限。
        • 問題2:如果項目中使用會更改IoC容器加載順序的Jar,導致切入點無效,可以在使用到DAO接口的地方,加上@Lazy 懶加載注解即可。(該問題純屬本人猜測,還需深度研究)

        最后

        以上是個人的思路實現,有不對或者需要優化之處,請指出,謝謝。

        ?

        轉載于:https://my.oschina.net/u/4094976/blog/3034519

        總結

        以上是生活随笔為你收集整理的SpringBoot + AOP + MySQL监控系统数据变更实战的全部內容,希望文章能夠幫你解決所遇到的問題。

        如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

        主站蜘蛛池模板: www.亚洲黄色 | 日韩一区二区三区不卡 | 操操影视 | 亚洲乱码国产乱码精品精 | 国产91嫩草| 午夜刺激视频 | 国产一区一区 | 国产人妻人伦精品1国产 | 天天干天天干天天干天天 | 五十路av| 山村大伦淫第1部分阅读小说 | 国产一区在线免费观看 | 日韩亚洲第一页 | 欧美日韩在线免费播放 | 不卡av电影在线观看 | 国产在线97 | 国产男男gay网站 | 在线观视频免费观看 | 北条麻妃一区二区三区 | 午夜激情视频网站 | 91叉叉叉 | 五月天婷婷综合 | 一区二区啪啪啪 | 一级免费片| 成人在线视频一区二区三区 | 成人性生交大片免费卡看 | wwww欧美| 久久狠狠婷婷 | 超黄网站在线观看 | 久久av不卡 | 综合五月婷 | 看全色黄大色黄大片大学生 | 4438x亚洲最大| 青青草官网 | 中文字幕永久视频 | 91片看 | 天天夜夜啦啦啦 | 日韩有码在线视频 | 亚洲一一在线 | 欧美人妻少妇一区二区三区 | 亚洲国产日韩一区无码精品久久久 | 精品国产av鲁一鲁一区 | 国内精品偷拍 | 99re6这里有精品热视频 | 日本一区视频在线观看 | 日本aⅴ在线观看 | 欧美人体一区二区 | 人妻少妇被猛烈进入中文字幕 | 亚洲AV成人无码一二三区在线 | 色悠久久久 | 日本在线视频中文字幕 | 性一交一乱一色一视频麻豆 | 欧美偷拍视频 | 日韩中文字幕在线播放 | 日韩视频二区 | 2018天天弄 | 成人综合区 | 精品女同一区二区三区 | 久久人人插 | 欧美aaa级片| 天天看天天射 | 懂色av懂色av粉嫩av分享吧 | 一区二区在线精品 | 超碰一区二区 | 自拍视频啪 | 免费av网站在线看 | 91激情网| 国产精品主播视频 | av网址在线| 视色视频在线观看 | 无码人妻丰满熟妇精品 | 亚洲第一免费网站 | 毛片免费一区二区三区 | 中文字幕在线视频一区二区 | 欧美性www| 国产亚洲av在线 | 国产100页| 色撸撸在线视频 | 大屁股白浆一区二区 | 凹凸精品熟女在线观看 | 五月天一区二区三区 | 男女在线观看 | 91精品国产综合久久久蜜臀 | 人人射影院 | 五月天激情社区 | 日韩国产欧美一区二区三区 | 黄色aa毛片| 欧美黄色激情视频 | 一本一道久久综合狠狠老精东影业 | 日韩毛片一区 | 精品视频一区二区三区四区 | 成人h片在线观看 | 激情五月色婷婷 | 国产精品嫩草影院桃色 | 国产精品第十页 | 色一区二区三区四区 | 国产成人在线播放视频 | 成人乱人乱一区二区三区 | 日韩乱码一区二区 |