一、责任链设计模式搭建骨架图
什么是责任链模式:责任链设计模式
背景说明:
责任链模式包含一份请求对象和一系列执行对象,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。这里的场景是:找到某个Handler
处理掉请求。
反向同步功能实现里边,需要同步多种类型的数据源到我们自己的库,例如关系型mysql、oracle,大数据hive,索引es等等。单从反向同步这个功能来说,我需要执行一个请求,能根据不同的类型处理不同的同步操作,只处理一个具体Handler的(记住这里,也可以一口气处理所有链条上的,处理完一个handler接着触发下一个handler,处理所有的类似拦截器Filter),并且处理具体同步逻辑和返回处理结果。
二、责任链具体搭建
以反向同步为例
2.1、顶层抽象处理ScanHandler
可以看到具体handler继承了他并重写了这个抽象的某些方法
例如:非关系型数据同步的ElasticSearch直接继承了该抽象并重写了方法实现功能
public abstract class ScanHandler implements AutoCloseable {
public DataSource dataSource;
public abstract ZmgrMetaInfo handle(Map<String, String> table) throws Exception;
public abstract ScanParamVO buildScanParamVO();
public abstract void buildConnection() throws Exception;
/**
* 释放资源
*/
public abstract void closeConnection() throws Exception;
/**
* 查询库表列表信息
*/
public abstract List<Map<String, String>> scanAllObjectsInfo() throws Exception;
/**
* 表视图等信息
*/
public abstract Map<String, String> scanObjectInfo(String objectCode, String objectType) throws Exception;
/**
* 字段信息
*/
public abstract List<Map<String, String>> scanTableColumnInfo(Map<String, String> table) throws Exception;
/**
* 索引信息
*/
public abstract List<Map<String, String>> scanTableIndexInfo(Map<String, String> table) throws Exception;
/**
* 约束信息
*/
public abstract List<Map<String, String>> scanTableConstraintInfo(Map<String, String> object) throws Exception;
/**
* 分区信息
*/
public abstract List<Map<String, String>> scanTablePartitions(Map<String, String> table) throws Exception;
public DataSource getDatasource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public String getSchemaCode() {
return dataSource.getParamValue(DataSource.Database.SCHEMA);
}
public String getUsername() {
return dataSource.getParamValue(DataSource.Database.USERNAME);
}
@Override
public void close() throws Exception {
closeConnection();
}
public RepeatedAttachDTO buildCompareCollections(ZmgrMetaInfo remoteMetaInfo, ZmgrMetaData zmgrMetaData) {
DbMetaService dbMetaService = (DbMetaService) SpringContextUtil.getBean("dbMetaService");
RepeatedAttachDTO repeatedAttachDTO = new RepeatedAttachDTO();
// 本地约束集合
repeatedAttachDTO
.setLocalConstraintList(dbMetaService.getZmgrMetaConstraintListByMetaDataId(zmgrMetaData.getMetaDataId()));
// 索引名称约束集合
repeatedAttachDTO.setIndexCode(remoteMetaInfo.getZmgrMetaIndexList().stream().map(ZmgrMetaIndex::getIndexCode)
.collect(Collectors.toList()));
// 远程约束集合
repeatedAttachDTO.setRemoteConstraintList(remoteMetaInfo.getZmgrMetaConstraintList());
// 远程主键集合
repeatedAttachDTO.setRemotePkList(
repeatedAttachDTO.getRemoteConstraintList().stream().filter(c -> "0".equals(c.getConstraintType()))
.map(ZmgrMetaConstraint::getColumnCode).collect(Collectors.toList()));
// 本地主键集合
repeatedAttachDTO.setLocalPkList(
repeatedAttachDTO.getLocalConstraintList().stream().filter(c -> "0".equals(c.getConstraintType()))
.map(ZmgrMetaConstraint::getColumnCode).collect(Collectors.toList()));
// 远程约束-约束编码集合
repeatedAttachDTO.setRemoteConstraintCodeList(repeatedAttachDTO.getRemoteConstraintList().stream()
.map(ZmgrMetaConstraint::getConstraintCode).collect(Collectors.toList()));
// 本地约束-约束编码集合
repeatedAttachDTO.setLocalConstraintCodeList(repeatedAttachDTO.getLocalConstraintList().stream()
.map(ZmgrMetaConstraint::getConstraintCode).collect(Collectors.toList()));
// 落地新增集合
repeatedAttachDTO.setInsertConstraintList(repeatedAttachDTO.getLocalConstraintList().stream().filter(
c -> !ArrayUtil.containsIgnoreCase(repeatedAttachDTO.getRemoteConstraintCodeList(), c.getConstraintCode()))
.collect(Collectors.toList()));
// 落地更新集合
repeatedAttachDTO.setUpdateConstraintList(repeatedAttachDTO.getLocalConstraintList().stream().filter(
c -> ArrayUtil.containsIgnoreCase(repeatedAttachDTO.getRemoteConstraintCodeList(), c.getConstraintCode()))
.collect(Collectors.toList()));
// 落地删除集合
repeatedAttachDTO.setDeleteConstraintList(repeatedAttachDTO.getRemoteConstraintList().stream().filter(
c -> !ArrayUtil.containsIgnoreCase(repeatedAttachDTO.getLocalConstraintCodeList(), c.getConstraintCode()))
.collect(Collectors.toList()));
return repeatedAttachDTO;
}
public void deleteConstraint(ZmgrMetaData zmgrMetaData, String dbType, SqlSessionFactory sqlSessionFactory,
List<String> result, RepeatedAttachDTO repeatedAttachDTO) {
DbMetaService dbMetaService = (DbMetaService) SpringContextUtil.getBean("dbMetaService");
MyBatisSql myBatisSql = null;
if (!repeatedAttachDTO.getDeleteConstraintList().isEmpty()) {
for (ZmgrMetaConstraint constraint : repeatedAttachDTO.getDeleteConstraintList()) {
if ("0".equals(constraint.getConstraintType())
|| ArrayUtil.containsIgnoreCase(repeatedAttachDTO.getRemotePkList(), constraint.getColumnCode())) {
continue;
}
constraint.setMetaDataId(zmgrMetaData.getMetaDataId());
Map<String, Object> deleteMap = dbMetaService.rebuildConstraintInfo(constraint,
zmgrMetaData.getMetaDataCode(), dbType);
deleteMap.put("dbType", dbType);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableDropConstraint", deleteMap, sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public void insertConstraint(ZmgrMetaData zmgrMetaData, String dbType, SqlSessionFactory sqlSessionFactory,
List<String> result, RepeatedAttachDTO repeatedAttachDTO) {
MyBatisSql myBatisSql = null;
DbMetaService dbMetaService = (DbMetaService) SpringContextUtil.getBean("dbMetaService");
if (!repeatedAttachDTO.getInsertConstraintList().isEmpty()) {
for (ZmgrMetaConstraint insertConstraint : repeatedAttachDTO.getInsertConstraintList()) {
if ("0".equals(insertConstraint.getConstraintType()) || ArrayUtil
.containsIgnoreCase(repeatedAttachDTO.getIndexCode(), insertConstraint.getConstraintCode())) {
continue;
}
if ("2".equals(insertConstraint.getConstraintType()) && ArrayUtil
.containsIgnoreCase(repeatedAttachDTO.getRemotePkList(), insertConstraint.getColumnCode())) {
continue;
}
Map<String, Object> insertConstraintMap = dbMetaService.rebuildConstraintInfo(insertConstraint,
zmgrMetaData.getMetaDataCode(), dbType);
insertConstraintMap.put("dbType", dbType);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableAddConstraint", insertConstraintMap,
sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public void updateConstraint(ZmgrMetaData zmgrMetaData, String dbType, SqlSessionFactory sqlSessionFactory,
List<String> result, RepeatedAttachDTO repeatedAttachDTO) {
MyBatisSql myBatisSql = null;
DbMetaService dbMetaService = (DbMetaService) SpringContextUtil.getBean("dbMetaService");
if (!repeatedAttachDTO.getUpdateConstraintList().isEmpty()) {
for (ZmgrMetaConstraint updateConstraint : repeatedAttachDTO.getUpdateConstraintList()) {
if ("0".equals(updateConstraint.getConstraintType()) || ArrayUtil
.containsIgnoreCase(repeatedAttachDTO.getIndexCode(), updateConstraint.getConstraintCode())) {
continue;
}
Map<String, Object> updateConstraintMap = dbMetaService.rebuildConstraintInfo(updateConstraint,
zmgrMetaData.getMetaDataCode(), dbType);
updateConstraintMap.put("dbType", dbType);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableDropConstraint", updateConstraintMap,
sqlSessionFactory);
result.add(myBatisSql.toString());
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableAddConstraint", updateConstraintMap,
sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public void extractHandler(ZmgrMetaData zmgrMetaData, String dbType, SqlSessionFactory sqlSessionFactory,
List<String> result, RepeatedAttachDTO repeatedAttachDTO) {
MyBatisSql myBatisSql;
List<String> localPkList = repeatedAttachDTO.getLocalPkList();
List<String> remotePkList = repeatedAttachDTO.getRemotePkList();
if (localPkList.size() != remotePkList.size() || !localPkList.containsAll(remotePkList)) {
if (!remotePkList.isEmpty()) {
Map delParams = new HashMap();
delParams.put("dbType", dbType);
delParams.put("tableCode", zmgrMetaData.getMetaDataCode());
delParams.put("constraintType", 0);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableDropConstraint", delParams, sqlSessionFactory);
result.add(myBatisSql.toString());
}
if (!localPkList.isEmpty()) {
Map addParams = new HashMap();
addParams.put("dbType", dbType);
addParams.put("tableCode", zmgrMetaData.getMetaDataCode());
addParams.put("constraintType", 0);
addParams.put("pkList", localPkList);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableAddConstraint", addParams, sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public void addIndex(String dbType, SqlSessionFactory sqlSessionFactory, List<String> result,
List<Map<String, Object>> insertIndexList) {
MyBatisSql myBatisSql = null;
if (!insertIndexList.isEmpty()) {
for (Map<String, Object> insertIndexMap : insertIndexList) {
insertIndexMap.put("dbType", dbType);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableCreateIndex", insertIndexMap, sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public void updateIndex(String dbType, SqlSessionFactory sqlSessionFactory, List<String> result,
RepeatedAttachDTO repeatedAttachDTO) {
MyBatisSql myBatisSql = null;
if (!repeatedAttachDTO.getUpdateIndexList().isEmpty()) {
for (Map<String, Object> updateIndex : repeatedAttachDTO.getUpdateIndexList()) {
updateIndex.put("dbType", dbType);
String indexCode = MapParamUtil.getStringValue(updateIndex, "indexCode");
String indexType = MapParamUtil.getStringValue(updateIndex, "indexType");
String colCode = MapParamUtil.getStringValue(updateIndex, "colCode");
ZmgrMetaIndex remoteIndex = repeatedAttachDTO.getRemoteIndexMap().get(indexCode.toLowerCase());
if ("oracle".equalsIgnoreCase(dbType)) {
remoteIndex.setIndexType(OracleSql.translateIndexTypeCode(remoteIndex.getIndexType()));
}
else {
remoteIndex.setIndexType(MysqlSql.translateIndexTypeCode(remoteIndex.getIndexType()));
}
// 修改索引要求索引名、索引字段、索引顺序、索引类型一致
if (!StringUtils.equalsIgnoreCase(indexType, remoteIndex.getIndexType())
|| !StringUtils.equalsIgnoreCase(colCode, remoteIndex.getColumnCode())) {
updateIndex.put("originIndexCode", indexCode);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableDropIndex", updateIndex, sqlSessionFactory);
result.add(myBatisSql.toString());
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableCreateIndex", updateIndex, sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
}
public void deleteIndex(ZmgrMetaData zmgrMetaData, String dbType, SqlSessionFactory sqlSessionFactory,
List<String> result, List<ZmgrMetaIndex> deleteIndexList) {
MyBatisSql myBatisSql;
if (!deleteIndexList.isEmpty()) {
for (ZmgrMetaIndex index : deleteIndexList) {
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("tableCode", zmgrMetaData.getMetaDataCode());
parameterMap.put("originIndexCode", index.getIndexCode());
parameterMap.put("dbType", dbType);
myBatisSql = MyBatisSqlUtils.getMyBatisSql("alterTableDropIndex", parameterMap, sqlSessionFactory);
result.add(myBatisSql.toString());
}
}
}
public RepeatedAttachDTO buildIndexCompareCollections(String dbType, ZmgrMetaInfo remoteMetaInfo,
ZmgrMetaData zmgrMetaData) {
RepeatedAttachDTO repeatedAttachDTO = new RepeatedAttachDTO();
List<ZmgrMetaIndex> remoteIndexList = null;
remoteIndexList = remoteMetaInfo.getZmgrMetaIndexList();
Map<String, ZmgrMetaIndex> remoteIndexMap = new HashMap<>();
remoteIndexList.forEach(i -> remoteIndexMap.put(i.getIndexCode().toLowerCase(), i));
DbMetaService dbMetaService = (DbMetaService) SpringContextUtil.getBean("dbMetaService");
List<Map<String, Object>> localIndexList = dbMetaService.rebuildIndexInfo(zmgrMetaData.getMetaDataId(),
zmgrMetaData.getMetaDataCode(), dbType);
List<String> remoteIndexCodeList = remoteIndexList.stream().map(ZmgrMetaIndex::getIndexCode)
.collect(Collectors.toList());
List<String> localIndexCodeList = localIndexList.stream().map(c -> MapParamUtil.getStringValue(c, "indexCode"))
.collect(Collectors.toList());
// 处理新增的索引
repeatedAttachDTO.setInsertIndexList(localIndexList.stream()
.filter(
c -> !ArrayUtil.containsIgnoreCase(remoteIndexCodeList, MapParamUtil.getStringValue(c, "indexCode")))
.collect(Collectors.toList()));
// 处理修改的索引
repeatedAttachDTO.setUpdateIndexList(localIndexList.stream()
.filter(c -> ArrayUtil.containsIgnoreCase(remoteIndexCodeList, MapParamUtil.getStringValue(c, "indexCode")))
.collect(Collectors.toList()));
// 处理删除的索引
repeatedAttachDTO.setDeleteIndexList(
remoteIndexList.stream().filter(c -> !ArrayUtil.containsIgnoreCase(localIndexCodeList, c.getIndexCode()))
.collect(Collectors.toList()));
repeatedAttachDTO.setRemoteIndexMap(remoteIndexMap);
return repeatedAttachDTO;
}
}
2.2、关系型的数据类型同步则在ScanHandler该抽象套了一层,实现统一的关系型同步处理逻辑,
关系型的同步则直接继承ScanAbstractDatabaseHandler ,例如:
ScanAbstractDatabaseHandler
public abstract class ScanAbstractDatabaseHandler extends ScanHandler {
protected Connection connection;
@Override
public void buildConnection() throws Exception {
connection = DatabaseUtil.getConnection(getDatasource(),0);
}
@Override
public void closeConnection() throws Exception {
if (connection != null) {
connection.close();
}
}
@Override
public ZmgrMetaInfo handle(Map<String, String> table) throws Exception {
LoggerUtil.info("开始扫描{}对象:{}", dataSource.getDatasourceType(), table.get("OBJECT_NAME"));
ZmgrMetaInfo metaInfo = null;
try {
metaInfo = buildMetaInfo(table);
LoggerUtil.info("扫描{}对象成功:{}", dataSource.getDatasourceType(), table.get("OBJECT_NAME"));
}
catch (Exception e) {
LoggerUtil.info("扫描{}对象失败:{},失败原因:{}", dataSource.getDatasourceType(),
table.get("OBJECT_NAME"), e.getMessage());
throw new SyDevOpsRuntimeException(e);
}
return metaInfo;
}
@Override
public ScanParamVO buildScanParamVO() {
ScanParamVO params = new ScanParamVO();
params.setComponentId(dataSource.getDatasourceId());
params.setComponentType(dataSource.getDatasourceType());
params.setUrl(dataSource.getParamValue(DataSource.Database.URL));
params.setUser(dataSource.getParamValue(DataSource.Database.USERNAME));
params.setPassword(dataSource.getParamValue(DataSource.Database.PASSCODE));
params.setSchemaCode(getSchemaCode());
return params;
}
public Connection getConnection() {
return connection;
}
}
具体关注: metaInfo = buildMetaInfo(table);
public ZmgrMetaInfo buildMetaInfo(Map<String, String> table) throws Exception {
......
// 字段信息
List<Map<String, String>> realColumns = scanTableColumnInfo(table);
List<ZmgrMetaColumnsInfo> columnsInfoList = new ArrayList<>();
if (realColumns != null) {
for (Map<String, String> columnMap : realColumns) {
ZmgrMetaColumnsInfo columnsInfo = new ZmgrMetaColumnsInfo();
ZmgrMetaColumns columns = new ZmgrMetaColumns();
columns.setColumnName(columnMap.get("COLUMN_NAME"));
columns.setColumnCode(columnMap.get("COLUMN_CODE"));
if (Objects.equals(dataSource.getDatasourceType(), Common.TableType.GOLDENDB)) {
columns.setColumnType(columnMap.get("GOLD_COLUMN_TYPE"));
}
else {
columns.setColumnType(columnMap.get("COLUMN_TYPE"));
}
columns.setColumnDesc(columnMap.get("COMMENTS"));
if (StringUtils.isNotEmpty(columnMap.get("COLUMN_SORT"))) {
columns.setColumnSort(Integer.parseInt(columnMap.get("COLUMN_SORT")));
}
columns.setDefaultValue(columnMap.get("DEFAULT_VALUE"));
columnsInfo.setZmgrMetaColumns(columns);
List<ZmgrMetaColumnsParams> columnsParamsList = new ArrayList<>();
BuildBeanUtil.addColumnParams("columnLength", columnMap.get("DATA_LENGTH"),
"字段长度", columnsParamsList);
BuildBeanUtil.addColumnParams("isPrimary", columnMap.get("IS_PRIMARY"),
"是否主键", columnsParamsList);
BuildBeanUtil.addColumnParams("isNull", columnMap.get("IS_NULL"),
"是否可为空", columnsParamsList);
BuildBeanUtil.addColumnParams("columnEmpty", "Y".equals(columnMap.get("IS_NULL")) ? "0" : "1",
"非空约束", columnsParamsList);
BuildBeanUtil.addColumnParams("dataPrecision", columnMap.get("DATA_PRECISION"),
"数据精度", columnsParamsList);
BuildBeanUtil.addColumnParams("dataScale", columnMap.get("DATA_SCALE"),
"", columnsParamsList);
columnsInfo.setZmgrMetaColumnsParamsList(columnsParamsList);
columnsInfoList.add(columnsInfo);
}
}
metaInfo.setZmgrMetaColumnsInfoList(columnsInfoList);
// 索引信息
List<Map<String, String>> realIndexes = scanTableIndexInfo(table);
List<ZmgrMetaIndex> indexList = new ArrayList<>();
if (realIndexes != null) {
for (Map<String, String> indexMap : realIndexes) {
ZmgrMetaIndex index = new ZmgrMetaIndex();
index.setIndexCode(indexMap.get("INDEX_NAME"));
index.setIndexType(indexMap.get("TYPE"));
index.setColumnCode(indexMap.get("COLUMN_NAME"));
if (DataSource.GP.equals(dataSource.getDatasourceType())) {
String gpIndexKey = indexMap.get("INDKEY");
String[] columnSorts = gpIndexKey.split(" ", -1);
StringBuilder sb = new StringBuilder();
for (String columnSort : columnSorts) {
sb.append(columnsInfoList.get(Integer.parseInt(columnSort) - 1)
.getZmgrMetaColumns().getColumnCode()).append(",");
}
index.setColumnCode(sb.substring(0, sb.length() - 1));
index.setIndexTypeValue(indexMap.get("INDEX_TYPE_VALUE"));
index.setTableSpace(indexMap.get("TABLE_SPACE"));
if (indexMap.get("FILL_FACTOR") != null) {
index.setFillfactor(Integer.parseInt(indexMap.get("FILL_FACTOR")));
}
}
indexList.add(index);
}
}
metaInfo.setZmgrMetaIndexList(indexList);
if (ScanFactory.TABLE.equalsIgnoreCase(objectType)) {
// 约束信息
List<Map<String, String>> realConstraints = scanTableConstraintInfo(table);
List<ZmgrMetaConstraint> constraintList = new ArrayList<>();
if (realConstraints != null) {
for (Map<String, String> constraintsMap : realConstraints) {
ZmgrMetaConstraint constraint = new ZmgrMetaConstraint();
constraint.setConstraintCode(constraintsMap.get("CONSTRAINT_NAME"));
constraint.setConstraintType(constraintsMap.get("CONSTRAINT_TYPE"));
constraint.setConstraintTable(constraintsMap.get("TABLE_NAME"));
constraint.setColumnCode(constraintsMap.get("COLUMN_NAME"));
constraint.setConstraintRefTable(constraintsMap.get("REFERENCED_TABLE_NAME"));
constraint.setConstraintRefColumn(constraintsMap.get("REFERENCED_COLUMN_NAME"));
constraint.setConstraintValue(constraintsMap.get("CONSTRAINT_VALUE"));
constraint.setConstraintTablespace(constraintsMap.get("TABLE_SPACE"));
if (constraintsMap.get("FILL_FACTOR") != null) {
constraint.setConstraintFillfactor(Integer.parseInt(constraintsMap.get("FILL_FACTOR")));
}
constraintList.add(constraint);
}
}
metaInfo.setZmgrMetaConstraintList(constraintList);
}
// 分区信息 如果有的话
List<Map<String, String>> realPartitions = scanTablePartitions(table);
if (realPartitions != null && !realPartitions.isEmpty()) {
List<ZmgrMetaPartition> partitionList = new ArrayList<>();
for (Map<String, String> partitionMap : realPartitions) {
ZmgrMetaPartition partition = new ZmgrMetaPartition();
partition.setColumnCode(partitionMap.get("COLUMN_NAME"));
partition.setPartitionCode(partitionMap.get("PARTITION_CODE"));
partition.setPartitionName(partitionMap.get("PARTITION_NAME"));
partition.setPartitionValue(partitionMap.get("PARTITION_VALUE"));
partitionList.add(partition);
}
metaInfo.setZmgrMetaPartitionList(partitionList);
}
return metaInfo;
}
说明:
// 字段信息
List<Map<String, String>> realColumns = scanTableColumnInfo(table);
// 索引信息
List<Map<String, String>> realIndexes = scanTableIndexInfo(table);
// 约束信息
List<Map<String, String>> realConstraints = scanTableConstraintInfo(table);
下一章:https://blog.youkuaiyun.com/RuiKe1400360107/article/details/113281119