Canal的使用场景!!!

发布于:2024-04-11 ⋅ 阅读:(146) ⋅ 点赞:(0)

 1、保持redis和mysql连接的一致性:通常使用延迟双删功能(具有弊端)

解决方案:可以使用canal监听数据库的变化(删改),一旦出现此类操作,立即删除redis中的对应数据,直至下次使用该数据时,从数据库中查找后(新数据)写入redis中。

2、如何监听表的字段:可以使用mybatis的拦截器进行(见下文)

更优方案:通过canal监听数据库的变化(会返回一个json串,可以解析json串来监听数据表或者数据表中的字段名)

 

一、MyBatis拦截器-笔试题

1.笔试题

ORM使用的是mybatis,请提供记录字段级变更日志的技术方案。

需求:

1.可以指定表进行监控

2.可以指定表中的某些字段进行监控

2.实现

2.1 引入解析器

什么是JSqlParser?

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

添加依赖

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

</dependency>

2.2 添加拦截器

@Component
@Intercepts({
        // 指定要拦截的方法签名,这里是拦截Executor的update方法
        @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
        // 可以添加更多要拦截的方法签名...
})
@Slf4j
public class MonitorInterceptor implements Interceptor {

    private static List<String> MONITOR_TABLES = CollUtil.newArrayList("205_product");
    private static List<String> MONITOR_COLUMNS = CollUtil.newArrayList("price");
    @Override

    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler =    (StatementHandler)(invocation.getTarget());
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        net.sf.jsqlparser.statement.Statement statement = CCJSqlParserUtil.parse(sql);
        if(statement instanceof Update){
            Update update = (Update)statement;
            String table = update.getTable().getName();

            if(MONITOR_TABLES.contains(table)){
                log.info("表 {} 更改了", table);
                ArrayList<UpdateSet> updateSets = update.getUpdateSets();
                updateSets.forEach(item -> item.getColumns().forEach(item2 -> {
                    if(MONITOR_COLUMNS.contains(item2.getColumnName())){
                        sendDingding(table);
                    }
                }));

            }
        }
        return invocation.proceed();
    }

    private void sendDingding(String table){
        String url = "https://oapi.dingtalk.com/robot/send?access_token=ddaea71f9ed09a0cd0fe1a28e18fadb618a4e0cee829c0534d48b3273dd9e644";

        JSONObject msg = new JSONObject();
        msg.set("msgtype", "markdown");
        msg.set("markdown", new JSONObject()
                .set("title", LocalUserUtil.getLocalUser().getNickName()+ " 更改了表 " + table )
                .set("text"," 更改了价格请审核 "));

        msg.set("at", new JSONObject().set("isAtAll", true));

        String json = JSONUtil.toJsonStr(msg);
        String result = HttpRequest.post(url)
                .body(json)
                .execute().body();
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到