监控表数据变化mq消息对象里有个tableName字段,写代码时需要用if一层层添加
if(tableName.equals(account)){
accountService.addAccount();
}esle if(tableName.equals(role)){
roleService.addRole();
}
·
·
·
·
等等等,有多少个表变化就需要多少个if,并且谢增是还要维护这个if,很是难受,
所以想通过策略模式拆分if,使每个监控table有自己的Class,每个Class只用关注自己对应变化的业务,而不用操心写if
第一步:
首先我们需要一个接口:BaseTableHandler,用于定义每个实现类要做的事
public interface BaseTableHandler {
void syncTableMsg(InstanceMsgDto instanceMsgDto);
}
第二步:
需要个枚举:ChangeTableProcessEnum,定义有哪些表的变化我们需要监控
public enum ChangeTableProcessEnum {
SYS_ACCOUNT("sys_account","账号表"),
SYS_ACC_PFM("sys_acc_pfm","账号平台表"),
SYS_ACC_PWD("sys_acc_pwd","账号密码表");
private String tableName;
private String desc;
ChangeTableProcessEnum(String tableName,String desc) {
this.tableName = tableName;
this.desc = desc;
}
public String getTableName() {
return tableName;
}
public String getDesc() {
return desc;
}
public static ChangeTableProcessEnum getChangeTableProcessEnum(String tableName)
{
for(ChangeTableProcessEnum stateEnum:ChangeTableProcessEnum.values())
{
if(stateEnum.tableName.equals(tableName))
{
return stateEnum;
}
}
return null;
}
}
第三步:
我们需要一个自定义注解:ChangerTableType,标注哪些Handler是需要监控的
@Component
@ChangerTableType(value = ChangeTableProcessEnum.SYS_ACCOUNT)
public class SysAccountHandler implements BaseTableHandler{
@Override
public void syncTableMsg(InstanceMsgDto instanceMsgDto) {
System.out.println("这里是"+instanceMsgDto.getTableName().equals());
}
}
第四步:
创建每个业务的实现类:SysAccPfmHandler,SysAccountHandler(两个举例),并且实现第一步创建的接口BaseTableHandler,加上我们自己的注解@ChangerTableType(value = ChangeTableProcessEnum.SYS_ACCOUNT)
syncTableMsg方法中就实现自己的业务逻辑
第一个class
@Component
@ChangerTableType(value = ChangeTableProcessEnum.SYS_ACCOUNT)
public class SysAccountHandler implements BaseTableHandler{
@Override
public void syncTableMsg(InstanceMsgDto instanceMsgDto) {
System.out.println("这里是"+instanceMsgDto.getTableName().equals());
}
}
第二个class
@Component
@ChangerTableType(value = ChangeTableProcessEnum.SYS_ACC_PFM)
public class SysAccPfmHandler implements BaseTableHandler{
@Override
public void syncTableMsg(InstanceMsgDto instanceMsgDto) {
System.out.println("这里是"+instanceMsgDto.getTableName());
}
}
第五步:
最重要的将前四步如何进行关联起来,需要建个TableConfig实现ApplicationRunner在启动项目时取出每个业务类
@Component
public class TableConfig implements ApplicationRunner {
@Autowired
private ApplicationContext context;
public static final ConcurrentMap<ChangeTableProcessEnum, BaseTableHandler> msgStrategyMap = Maps.newConcurrentMap();
@Override
public void run(ApplicationArguments args) {
context.getBeansWithAnnotation(ChangerTableType.class).values().forEach(entrySet ->{
msgStrategyMap.put(entrySet.getClass().getAnnotationsByType(ChangerTableType.class)[0].value(),
(BaseTableHandler) entrySet);
});
}
}
第六步:
怎么使用?
@Test
public void createAccount()
{
InstanceMsgDto i = new InstanceMsgDto();
i.setTableName("sys_account");
String message = JSON.toJSONString(i);
handler(message);
InstanceMsgDto a = new InstanceMsgDto();
a.setTableName("sys_acc_pfm");
message = JSON.toJSONString(a);
handler(message);
}
public void handler(String message){
try {
InstanceMsgDto instanceMsgDto = JSONObject.parseObject(message,InstanceMsgDto.class);
BaseTableHandler handler = TableConfig.msgStrategyMap.get(ChangeTableProcessEnum.getChangeTableProcessEnum(instanceMsgDto.getTableName()));
handler.syncTableMsg(instanceMsgDto);
} catch (Exception e) {
log.error("createAccount is error:{}", e);
}
}
最后执行结果:
这里是sys_account
这里是sys_acc_pfm
以后新增是只用加个枚举,新建个业务对应的**Handler ,每个Handler只用关注自己的业务
通过接收到的message不同自动执行对应的Handler业务,而公共部分不用修改及关注。