参考:
https://blog.csdn.net/m0_37583655/article/details/119148470(代码缺失,而且没有源码)
下面是源码:
引入maven
<dependency>
<groupId>com.github.shyiko</groupId>
<artifactId>mysql-binlog-connector-java</artifactId>
<version>0.16.1</version>
</dependency>
yml配置文件:
binlog:
config:
host: 127.0.0.1
port: 3306
username: admin
password: root
配置类:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "binlog.config")
@Data
public class BinlogConfig {
String host;
int port;
String username;
String password;
}
主要代码:
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@Slf4j
@Component
public class BinLogRunner implements CommandLineRunner {
@Autowired
private BinlogConfig config;
private HashMap<String,Long> listenerMap =new HashMap<>();
//需要监控的数据表 schema.tableName
private List<String> listenerTableList = Arrays.asList("schema.tableName");
private void putListenerMap(String database,String table , Long tableId){
String key = database+"."+table;
if(listenerTableList.contains(key)){
listenerMap.put(key,tableId);
}
}
private String getTableName(Long tableId){
for (String key : listenerMap.keySet()) {
Long aLong = listenerMap.get(key);
if(aLong.equals(tableId)){
return key;
}
}
return null;
}
@Override
public void run(String... args) throws Exception {
String host = config.getHost();
int port = config.getPort();
String username = config.getUsername();
String password = config.getPassword();
if(CollectionUtils.isEmpty(listenerTableList)) {
return;
}
BinaryLogClient client = new BinaryLogClient(host, port, username, password);
client.registerEventListener(event -> {
EventType eventType = event.getHeader().getEventType();
if (eventType == EventType.TABLE_MAP) {
TableMapEventData tableData = event.getData();
String db = tableData.getDatabase();
String table = tableData.getTable();
long tableId = tableData.getTableId();
// 第一遍 会显示数据库 第二遍有tableId
// log.info("当前数据库: "+db+"."+table+" tableId:"+tableId);
putListenerMap(db,table,tableId);
}
if(EventType.isUpdate(eventType)||EventType.isWrite(eventType)||EventType.isDelete(eventType)){
long tableId = 0L;
String tableName = null;
// 如果日志是更新记录
if (EventType.isUpdate(eventType)) {
UpdateRowsEventData update = event.getData();
tableId = update.getTableId();
tableName = getTableName(tableId);
if(tableName == null){
return;
}
} else if (EventType.isWrite(eventType)) {
WriteRowsEventData write = event.getData();
tableId = write.getTableId();
tableName = getTableName(tableId);
if(tableName == null){
return;
}
} else if (EventType.isDelete(eventType)) {
DeleteRowsEventData delete = event.getData();
tableId = delete.getTableId();
tableName = getTableName(tableId);
if(tableName == null){
return;
}
}
tableUpdate(tableName);
}else{
return;
}
});
client.connect();
}
private void tableUpdate(String tableName){
log.info("--------------------tableName: "+tableName);
}
}
重难点:
client.registerEventListener(event -> {
// 当数据更新的时候 会触发这里 触发两遍
EventType eventType = event.getHeader().getEventType();
if (eventType == EventType.TABLE_MAP) {
// 第一遍类型 EventType.TABLE_MAP
// 数据包含 tableName 和 tableId
}
if(EventType.isUpdate(eventType)
||EventType.isWrite(eventType)
||EventType.isDelete(eventType)){
// 第二遍类型会是 增 删 改
// 数据包含: 具体数据和tableId
}
})
所以用tableId去查找tableName
注意: tableId 可能会变化,不能当作key