当前位置: 首页 > news >正文

使用mybatis的statementHander拦截器监控表和字段并发送钉钉消息

新建mybatis的statementHander拦截器拦截器 类

面试题:

2.实现

解析Sql时引入JSqlParser

JSqlParser 是一个 SQL 语句解析器。 它将 SQL转换为可遍历的 Java 类层次结构。 

<dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>4.6</version></dependency>

 添加拦截器代码:

package com.yy.config;import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.smart.model.LocalUser;
import cn.smart.util.ThreadlocalUtil;
import com.yy.entity.BaseEntity;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Component
@Intercepts({// 指定要拦截的方法签名,这里是拦截Executor的update方法@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),// 可以添加更多要拦截的方法签名...
})
public class StatementHanderInterceptor implements Interceptor {private static List<String> tables = CollUtil.newArrayList("product","category");private static Map<String,List<String>> tableColumns = new HashMap<>();static {tableColumns.put("product",CollUtil.newArrayList("name","price"));}@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler =(StatementHandler)invocation.getTarget();//要想监控表,首先要从拦截器中拿到sql语句,看sql语句干了什么,对那些表和那些字段做了什么BoundSql boundSql = statementHandler.getBoundSql();String sql = boundSql.getSql();
//        使用JSqlParser解析器解析sql语句net.sf.jsqlparser.statement.Statement statement = CCJSqlParserUtil.parse(sql);if(statement instanceof Update){Update update = (Update)statement;String name = update.getTable().getName();if(tables.contains(name)){List<String> updataSets = tableColumns.get(name);ArrayList<UpdateSet> updateSets = update.getUpdateSets();for (UpdateSet updateSet : updateSets) {String columnName = updateSet.getColumns().get(0).getColumnName();if(updataSets.contains(columnName)){sendMessage(   "修改了字段"+updateSet,name);}}}}else if(statement instanceof Insert){Table table = ((Insert) statement).getTable();String name = table.getName();if(tables.contains(name)){sendMessage("添加了数据",name);}}return invocation.proceed();}private void sendMessage(String option,String tableName){String url= "https://oapi.dingtalk.com/robot/send?access_token=1cfb9a7b20e849a26b572a8ff98f62ee2a220028cd1452901a486e131435621f";JSONArray array = new JSONArray();array.add("18236435312");JSONObject msg = new JSONObject();msg.set("msgtype","text");msg.set("text",new JSONObject().set("content","警告:"+ThreadlocalUtil.get().getNickName()+"-> "+option+" ,表名是:"+tableName));msg.set("at",new JSONObject().set("atMobiles",array));String json = JSONUtil.toJsonStr(msg);String body = HttpRequest.post(url).body(json).execute().body();}}

遇到的问题:

因为这个pagehelper是从stater中继承过来的,可以在stater中也加一个4.6版本的jsqlparser依赖

 

相关文章:

使用mybatis的statementHander拦截器监控表和字段并发送钉钉消息

新建mybatis的statementHander拦截器拦截器 类 面试题&#xff1a; 2.实现 解析Sql时引入JSqlParser JSqlParser 是一个 SQL 语句解析器。 它将 SQL转换为可遍历的 Java 类层次结构。 <dependency><groupId>com.github.jsqlparser</groupId><artifac…...

信贷系统——基础信贷概念

摘要 信贷是金融领域中的一个重要概念,指的是金融机构(如银行、信用合作社等)向个人、企业或政府提供资金的过程。在信贷过程中,金融机构向借款人提供资金,借款人则承诺在未来的某个时间点按照约定的条件和利率偿还借款。这种借款通常是在合同中明确约定的,包括贷款金额、…...

分页查询及其拓展应用案例

分页查询 分页查询是处理大量数据时常用的技术&#xff0c;通过分页可以将数据分成多个小部分&#xff0c;方便用户逐页查看。SQLAlchemy 提供了简单易用的方法来实现分页查询。 本篇我们也会在最终实现这样的分页效果&#xff1a; 1. 什么是分页查询 分页查询是将查询结果按照…...

【UE5.1】NPC人工智能——02 NPC移动到指定位置

效果 步骤 1. 新建一个蓝图&#xff0c;父类选择“AI控制器” 这里命名为“BP_NPC_AIController”&#xff0c;表示专门用于控制NPC的AI控制器 2. 找到我们之前创建的所有NPC的父类“BP_NPC” 打开“BP_NPC”&#xff0c;在类默认值中&#xff0c;将“AI控制器类”一项设置为“…...

有关电力电子技术的一些相关仿真和分析:⑤交-直-交全桥逆变+全波整流结构电路(MATLAB/Siumlink仿真)

全桥逆变+全波整流结构 参数:Vin=500V, Vo=200V, T=2:1:1, RL=10Ω, fs=100kHz, L=1mH, C=100uF (1)给定输入电压,输出电压和主电路参数,仿真研究电路工作原理,分析工作时序; (2)调节负载电阻,实现电流连续和断续,并仿真验证; (3)调节占空比,分析占空比与电…...

记录一次Android推流、录像踩坑过程

背景&#xff1a; 按照需求&#xff0c;需要支持APP在手机息屏时进行推流、录像。 技术要点&#xff1a; 1、手机在息屏时能够打开camera获取预览数据 2、获取预览数据时进行编码以及合成视频 一、息屏时获取camera预览数据&#xff1a; ①Camera.setPreviewDisplay(SurfaceH…...

VsCode 与远程服务器 ssh免密登录

首先配置信息 加入下列信息 Host qb-zn HostName 8.1xxx.2xx.3xx User root ForwardAgent yes Port 22 IdentityFile ~/.ssh/id_rsa 找到自己的公钥&#xff0c;不带pub是私钥&#xff0c;打死都不能给别人。复制公钥 拿到公钥后&#xff0c;来到远程服务器 vim ~/.ss…...

7/13 - 7/15

vo.setId(rs.getLong("id"))什么意思&#xff1f; vo.setId(rs.getLong("id")); 这行代码是在Java中使用ResultSet对象&#xff08;通常用于从数据库中检索数据&#xff09;获取一个名为"id"的列&#xff0c;并将其作为long类型设置为一个对象…...

烟雾监测与太阳能源:实验装置在其中的作用

太阳光在烟雾中的散射效应研究实验装置是一款模拟阳光透过烟雾环境的设备。此装置能帮助探究阳光在烟雾中的传播特性、散射特性及其对阳光的影响。 该装置主要包括光源单元、烟雾发生装置、光学组件、以及系统。光源单元负责产生类似于太阳光的光线&#xff0c;通常选用高亮度的…...

QT下,如何获取控制台输入

最近工作中为了测试某个模块&#xff0c;需要把原先输入模块部分&#xff0c;改成控制台输入来方便测试。在QT中&#xff0c;我们可以使用 QTextStream 类来读取用户的输入来达到目的。下面是一个简单的例子&#xff1a; #include <QCoreApplication> #include <QTex…...

mybatis动态传入参数 pgsql 日期 Interval ,day,minute

mybatis动态传入参数 pgsql 日期 Interval 在navicat中&#xff0c;标准写法 SELECT * FROM test WHERE time > (NOW() - INTERVAL 5 day)在mybatis中&#xff0c;错误写法 SELECT * FROM test WHERE time > (NOW() - INTERVAL#{numbers,jdbcTypeINTEGER} day)报错内…...

常见CSS属性

常见CSS属性。 1. display: 定义&#xff1a;display 属性控制元素如何渲染在文档流中&#xff0c;影响了元素是否占用空间、位置及盒子模型的行为。 使用说明&#xff1a;它可以设置为如block, inline, inline-block, flex, grid, none等值&#xff0c;用于决定元素显示模式…...

WSL-Ubuntu20.04训练环境配置

1.YOLOv8训练环境配置 训练环境配置的话就仍然以YOLOv8为例&#xff0c;来说明如何配置深度学习训练环境。这部分内容比较简单&#xff0c;主要是安装miniAnaconda以及安装torch和torchvision. 首先是miniAnaconda的安装(参考官网的教程Miniconda — Anaconda )&#xff0c;执行…...

运维检查:mysql表自增id是否快要用完

数据库表中最大自增ID用完会报错。判断是否接近或达到自增ID类型的最大值&#xff1a;‌ 对于MySQL中的自增ID&#xff0c;‌如果使用的是int类型&#xff0c;‌其无符号&#xff08;‌unsigned&#xff09;‌的最大值可以达到2^32 - 1&#xff0c;‌即4294967295。‌如果使用的…...

深入理解FFmpeg--libavformat接口使用(一)

libavformat&#xff08;lavf&#xff09;是一个用于处理各种媒体容器格式的库。它的主要两个目的是去复用&#xff08;即将媒体文件拆分为组件流&#xff09;和复用的反向过程&#xff08;以指定的容器格式写入提供的数据&#xff09;。它还有一个I/O模块&#xff0c;支持多种…...

坚持日更的意义何在?

概述 日更&#xff0c;就是每天更新一次或一篇文章。 坚持日更&#xff0c;就是坚持每天更新一次或一篇文章。 这里用了坚持&#xff0c;实际上不是恰当的表述&#xff0c;正确的感觉应该是让日更当作习惯&#xff0c;然后&#xff0c;让自己习惯每天去更新一篇文章。 日更…...

内容长度不同的div如何自动对齐展示

平时我们经常会遇到页面内容div结构相同页&#xff0c;这时为了美观我们会希望div会对齐展示&#xff0c;但当div里的文字长度不一时又不想写固定高度&#xff0c;就会出现div长度长长短短&#xff0c;此时实现样式可以这样写&#xff1a; .e-commerce-Wrap {display: flex;fle…...

Qt中https的使用,报错TLS initialization failed和不能打开ssl.lib问题解决

前言 在现代应用程序中&#xff0c;安全地传输数据变得越来越重要。Qt提供了一套完整的网络API来支持HTTP和HTTPS通信。然而&#xff0c;在实际开发过程中&#xff0c;开发者可能会遇到SSL相关的错误&#xff0c;例如“TLS initialization failed”&#xff0c;cantt open ssl…...

P2p网络性能测度及监测系统模型

P2p网络性能测度及监测系统模型 网络IP性能参数 IP包传输时延时延变化误差率丢失率虚假率吞吐量可用性连接性测度单向延迟测度单向分组丢失测度往返延迟测度 OSI中的位置-> 网络层 用途 面相业务的网络分布式计算网络游戏IP软件电话流媒体分发多媒体通信 业务质量 通过…...

zookeeper相关总结

1. ZooKeeper 的架构 ZooKeeper 采用主从架构&#xff08;Leader-Follower 模型&#xff09;&#xff0c;包括以下组件&#xff1a; Leader&#xff1a;负责处理所有写请求和协调事务一致性。Follower&#xff1a;处理读请求并转发写请求给 Leader。参与 Leader 选举和事务提…...

华硕笔记本性能优化神器:G-Helper轻量控制工具完全指南

华硕笔记本性能优化神器&#xff1a;G-Helper轻量控制工具完全指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, E…...

Parsec虚拟显示驱动实战教程:5步创建完美游戏串流显示环境

Parsec虚拟显示驱动实战教程&#xff1a;5步创建完美游戏串流显示环境 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd Parsec虚拟显示驱动&#xff08;Parsec VDD&#xff09;是一…...

终极AMD Ryzen性能调优指南:SMUDebugTool完全掌握手册

终极AMD Ryzen性能调优指南&#xff1a;SMUDebugTool完全掌握手册 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…...

1987年6月14日下午13-15点出生性格、运势和命运

这篇文章讨论终极命题&#xff1a;出生时间只是一个随机数据点&#xff0c;真正的命运由你自己书写。我们将探讨如何利用“1987年5月27日中午11-13点”这个符号&#xff0c;作为自我激励的起点&#xff0c;而非束缚。第一步&#xff1a;解构“出生时间”的神秘性 请明确&#x…...

事件相机数据处理与GRU网络硬件加速技术解析

1. 事件相机与GRU网络硬件加速概述事件相机&#xff08;Event Camera&#xff09;是一种革命性的视觉传感器&#xff0c;其工作原理与传统帧式相机截然不同。它通过独立工作的像素阵列异步检测亮度变化&#xff0c;当某个像素的亮度变化超过预设阈值时&#xff0c;会立即生成一…...

告别PS和蓝湖!用PxCook离线搞定前端切图与标注(附学成在线实战)

前端开发者的效率革命&#xff1a;PxCook离线工作流全解析 在快节奏的前端开发领域&#xff0c;效率工具的选择往往决定了项目交付的速度和质量。传统的工作流程中&#xff0c;设计师使用Photoshop完成设计稿后&#xff0c;前端开发者需要反复在PS中测量尺寸、提取颜色值、导出…...

Vue3项目里SignalR怎么用?一个聊天室Demo带你从配置到上线(.NET 6 + Vue 3)

Vue3与SignalR实战&#xff1a;构建高互动聊天室的全栈指南 引言 在当今追求实时交互体验的Web应用中&#xff0c;传统的HTTP请求-响应模式已无法满足即时通讯、实时通知等场景需求。SignalR作为ASP.NET Core生态中的实时通信库&#xff0c;通过自动选择最佳传输协议&#xff0…...

全志V853开发环境搭建指南:从Ubuntu配置到SDK编译全流程

1. 项目概述&#xff1a;从零开始构建一个V853开发环境拿到一块全志V853开发板&#xff0c;第一件事是什么&#xff1f;不是急着写代码&#xff0c;也不是马上烧录固件&#xff0c;而是把整个编译环境给搭起来。这听起来像是基础操作&#xff0c;但恰恰是很多新手&#xff0c;甚…...

ARM NEON中的VMLAL/VMLSL指令详解与优化实践

1. ARM SIMD指令集概述在嵌入式系统和移动计算领域&#xff0c;ARM架构凭借其出色的能效比占据了主导地位。随着多媒体处理、机器学习等计算密集型任务的普及&#xff0c;单指令多数据流(SIMD)技术成为提升处理器性能的关键手段。ARM的Advanced SIMD扩展(通常称为NEON技术)提供…...

保姆级教程:用UltraISO给U盘刻录Ubuntu 22.04启动盘,一次成功不踩坑

零基础实战&#xff1a;用UltraISO打造Ubuntu 22.04启动盘的终极指南 第一次接触Linux系统安装的新手&#xff0c;往往会在制作启动盘这一步遇到各种意想不到的问题。U盘明明已经刻录完成&#xff0c;却在启动时出现黑屏、报错甚至根本无法识别——这些困扰过无数初学者的坑&am…...