1.基础组件
1.1注解类控制代码执行启动、停止、顺序
java
复制代码
/**
* @author : test
* @description : 数据同步注解
* @date : 2025/4/18
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SyncMeta {
/**
* 执行服务名称
* @return
*/
String name() default "";
/**
* 是否启用
*
* @return
*/
boolean isEnable() default false;
/**
* 顺序
* @return
*/
int order() default 0;
}
1.2数据获取基类
1.2.1数据获取基类接口(interface)
java
复制代码
/**
* @author : test
* @description :
* @date : 2025/4/18
*/
public interface BaseDataAcquisition {
/**
* 获取第三方数据
*/
void acquire();
}
1.2.2数据获取基类抽象类(abstract)实现接口
java
复制代码
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author : test
* @description :
* @date : 2025/4/18
*/
@Slf4j
public class BaseDataAcquisitionImpl<M extends BaseMapper<T>, T> implements BaseDataAcquisition {
@Autowired
protected M baseMapper;
@Autowired
protected SyncUrlProperties syncUrlProperties;
@Resource
protected ThirdDatabaseMapper thirdDatabaseMapper;
@Override
public void acquire() {
acquireData(DataSouceEnum.DATASOURCE);
}
/**
* 数据来源方式
*/
protected void acquireData(DataSouceEnum dataSouceEnum) {
List<T> allData = new ArrayList<>();
switch (dataSouceEnum) {
case DATASOURCE:
allData = getThirdDataFromDB();
break;
case INTERFACE:
allData = getDataFromUrl();
break;
default:
break;
}
if (CollUtil.isEmpty(allData)) {
log.error("采集数据为空,请确认数据采集方式");
return;
}
//数据抽取,新增
addExtraData(allData);
//数据处理
dealData(allData);
//集合切分,数据批处理
List<List<T>> parts = Lists.partition(allData, 1000);
parts.stream().forEach(list -> saveOrUpdate(list));
//数据抽取处理
extraDeal();
}
/**
* 用来重写
*
* @return
*/
protected List<T> getThirdDataFromDB() {
return null;
}
/**
* 用来重写
*
* @return
*/
protected List<T> getDataFromUrl() {
return covert(null);
}
/**
* 用来重写
* 数据保存和更新
* @param part
*/
protected void saveOrUpdate(List<T> part) {
}
/**
* 用来重写
* 数据转换
* @param body
*/
protected List<T> covert(String body) {
List<T> allData = new ArrayList<>();
return allData;
}
/**
* 用来重写
* 新增抽取数据
* @param allData
*/
protected void addExtraData(List<T> allData) {
}
/**
* 用来重写
* 数据处理
* @param allData
*/
protected void dealData(List<T> allData) {
}
/**
* 用来重写
* 抽取数据处理
* @param allData
*/
protected void extraDeal() {
}
}
2.数据抽取实现
2.1人员数据抽取示例
java
复制代码
@Service
@SyncMeta(name = Constants.PERSON_SERVICE, isEnable = false, order = 2)
@Slf4j
public class PersonDataAcquisitionImpl extends BaseDataAcquisitionImpl<ThirdPersonMapper, ThirdPerson>{
/**
* 三方数据获取
*/
@Override
protected List getThirdDataFromDB() {
return thirdDatabaseMapper.getAllThirdPerson();
}
@Override
protected List getDataFromUrl() {
String url = syncUrlProperties.getPersonUrl();
String body = HttpRequest.get(url)
.timeout(3000)
//.body(new JSONObject()) get请求发送body会报错,post请求需放开注释
.execute().body();
return covert(body);
}
@Override
protected void saveOrUpdate(List part) {
this.baseMapper.batchSaveOrUpdate(part);
}
@Override
protected List covert(String body) {
List<ThirdPerson> thirdPeople = new ArrayList<>();
//todo 转换请求结果
return thirdPeople;
}
}
2.2组织数据抽取示例
java
复制代码
/**
* @author : test
* @description :
* @date : 2025/4/18
*/
@Service
@SyncMeta(name = Constants.ORG_SERVICE, isEnable = false, order = 1)
@Slf4j
public class OrgDataAcquisitionImpl extends BaseDataAcquisitionImpl<ThirdOrgMapper, ThirdOrg> {
@Autowired
private ThirdRedisOrgCache thirdRedisOrgCache;
/**
* 数据库方式获取数据
*/
@Override
protected List<ThirdOrg> getThirdDataFromDB() {
return thirdDatabaseMapper.getAllThirdOrg();
}
/**
* url方式获取数据
*/
@Override
protected List<ThirdOrg> getDataFromUrl() {
String url = syncUrlProperties.getOrgUrl();
String body = HttpRequest.get(url)
.timeout(5000)
//.body(new JSONObject()) get请求发送body会报错,post请求需放开注释
.execute().body();
return covert(body);
}
/**
* 数据更新或保存
*/
@Override
protected void saveOrUpdate(List<ThirdOrg> part) {
this.baseMapper.batchSaveOrUpdate(part);
}
/**
* 数据转换
*/
@Override
protected List<ThirdOrg> covert(String body) {
List<ThirdOrg> thirdOrgs = new ArrayList<>();
//todo 转换请求结果
return thirdOrgs;
}
/**
* 数据新增
*/
@Override
protected void addExtraData(List<ThirdOrg> allData) {
ThirdOrg thirdOrg = new ThirdOrg();
thirdOrg.setName(Constants.NO_ORG_NAME_NAME);
thirdOrg.setThirdCode(Constants.NO_ORG_NAME_CODE);
thirdOrg.setType(0);
allData.add(thirdOrg);
}
/**
* 数据处理
*/
@Override
protected void extraDeal() {
thirdRedisOrgCache.initData();
}
}
2.3 mybatis 数据批量新增更新操作
xml
复制代码
<insert id="batchSaveOrUpdate">
insert into third_person(
NAME, CODE, SEX, PHONE, CARD_NUMBER, ID_CARD, EMAIL, ENTRY_DATE, CAR_NUMBER, THIRD_ORG_CODE, THIRD_DORM_CODE, TYPE
)
values
<foreach collection="pojoList" item="item" index="index" separator=",">
(#{item.name},#{item.code},#{item.sex},#{item.phone},#{item.cardNumber},
#{item.idCard},#{item.email},#{item.entryDate},#{item.carNumber},
#{item.thirdOrgCode},#{item.thirdDormCode},#{item.type})
</foreach>
ON DUPLICATE KEY UPDATE
NAME = values(NAME),
SEX = values(SEX),
PHONE = values(PHONE),
CARD_NUMBER = values(CARD_NUMBER),
EMAIL = values(EMAIL),
ID_CARD = values(ID_CARD),
ENTRY_DATE = values(ENTRY_DATE),
THIRD_ORG_CODE = values(THIRD_ORG_CODE),
THIRD_DORM_CODE = values(THIRD_DORM_CODE),
TYPE = values(TYPE),
UPDATE_TIME = now()
</insert>
3.数据抽取触发
java
复制代码
/**
*
* @author : test
* @description :
* @date : 2025/4/18
*/
@Service
public class DataAcquisitionStrategy {
public void process(List<String> serviceNames) {
Map<String, BaseDataAcquisition> allServiceMap = AppContextHelper.getContext().getBeansOfType(BaseDataAcquisition.class);
List<BaseDataAcquisition> allAcquisitionService = allServiceMap.values().stream().collect(Collectors.toList());
List<BaseDataAcquisition> processServices = allAcquisitionService.stream().filter(service -> {
SyncMeta syncMeta = service.getClass().getAnnotation(SyncMeta.class);
if (CollUtil.isNotEmpty(serviceNames)) {
return syncMeta != null && syncMeta.isEnable() && serviceNames.contains(syncMeta.name());
} else {
return syncMeta != null && syncMeta.isEnable();
}
}).collect(Collectors.toList());
TreeMap<Integer, BaseDataAcquisition> sortedMap = new TreeMap<>();
processServices.forEach(service->{
SyncMeta syncMeta = service.getClass().getAnnotation(SyncMeta.class);
sortedMap.put(syncMeta.order(), service);
});
sortedMap.values().forEach(service-> service.acquire());
}
}