binlog中记录数据的增、删、改操作;用模板方法模式和静态工厂模式来处理binlog解析
依赖
<dependency>
<groupId>com.zendesk</groupId>
<artifactId>mysql-binlog-connector-java</artifactId>
<version>0.25.5</version>
</dependency>
获取binlog文件进行解析
public class Test {
/**
* bin文件前缀
*/
private static final String filePrefix = "mysql-bin";
public static void main(String[] args) {
// 获取前缀为mysql-bin开头的,并且不是.index的文件
File[] logFiles = new File("D:/logs/binlog/").listFiles((f, name) -> {
String suffix = name.substring(name.indexOf(".") + 1);
return name.startsWith(filePrefix) && !"index".equals(suffix);
});
for(File f:logFiles) {
EventDeserializer eventDeserializer = new EventDeserializer();
eventDeserializer.setCompatibilityMode(
EventDeserializer.CompatibilityMode.DATE_AND_TIME_AS_LONG,
EventDeserializer.CompatibilityMode.CHAR_AND_BINARY_AS_BYTE_ARRAY
);
try (
BinaryLogFileReader bfr = new BinaryLogFileReader(f, eventDeserializer);
) {
for (Event event; (event = bfr.readEvent()) != null; )
// 使用静态工厂创建解析实例
BinlogEventFactory.executeAnalysis(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
使用工厂模式,根据操作类型创建对应实例
public class BinlogEventFactory {
public static void executeAnalysis(Event event) throws Exception {
if(TableMapEventData.class.isInstance(event.getData())) {
new TableMapEventAnalysis().analysis(event);
} else if(EventType.isDelete(event.getHeader().getEventType())) {
// 删除操作
new DeleteEventAnalysis().analysis(event);
} else if(EventType.isUpdate(event.getHeader().getEventType())) {
// 更新操作
new UpdateEventAnalysis().analysis(event);
} else if(EventType.isWrite(event.getHeader().getEventType())) {
// 保存操作
new SaveEventAnalysis().analysis(event);
}
}
}
接口
public interface BinlogService {
void analysis(Event event) throws Exception;
}
用来处理表信息的实现
public class TableMapEventAnalysis implements BinlogService {
@Override
public void analysis(Event event) {
TableMapEventData tableMapEventData = event.getData();
// 需要将tableId与table的关系存下来方便获取表名
System.out.println(tableMapEventData.getTable() + ":" + tableMapEventData.getTableId());
}
}
通过一个抽象类来定义我们的模板
将公共代码放入模板中,并提供一个具体处理的抽象方法供子类实现
public abstract class BinlogServiceImpl implements BinlogService {
protected String tableName;
protected List<String> rows;
@Override
public void analysis(Event event) throws Exception {
// binlog中没有表名,只有TableMapEventData中才有表名
long tableId = getTableId(event.getData());
// 可以根据table获取到表名
tableName = "获取到的表名";
// binlog中没有具体的列,只有列的位置如:0,1,2,3,可以根据表名查询表的所有字段
// 可以通过 show columns from table 事先查询字段放入缓存
rows = Arrays.asList("获取到的字段列表");
System.out.println("必要信息初始完成");
handle(event);
}
// 具体处理方法
protected abstract void handle(Event event);
private long getTableId(EventData data) throws Exception {
Class<?> clazz = data.getClass();
Method method = clazz.getMethod("getTableId");
if(null == method) {
return -1;
}
return (long) method.invoke(data);
}
}
所有增、删、改操作均继承抽象类;此时只需要关心自己本身需要的操作即可
添加数据
public class SaveEventAnalysis extends BinlogServiceImpl {
@Override
protected void handle(Event event) {
WriteRowsEventData eventData = event.getData();
System.out.println("插入数据操作,表:" + tableName + ", 列:" + String.join(",", rows));
}
}
修改数据
public class UpdateEventAnalysis extends BinlogServiceImpl {
@Override
protected void handle(Event event) {
UpdateRowsEventData updateRowsEventData = event.getData();
System.out.println("更新数据操作,表:" + tableName + ", 列:" + String.join(",", rows));
}
}
删除数据
public class DeleteEventAnalysis extends BinlogServiceImpl {
@Override
protected void handle(Event event) {
DeleteRowsEventData eventData = event.getData();
System.out.println("删除数据操作,表:" + tableName + ", 列:" + String.join(",", rows));
}
}