JAVA设计模式:注解+模板+接口

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());
    }
    
  

}
相关推荐
yanjiaweiya22 分钟前
云原生-集群管理
java·开发语言·云原生
gadiaola30 分钟前
【JavaSE面试篇】Java集合部分高频八股汇总
java·面试
艾迪的技术之路1 小时前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗9801 小时前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师1 小时前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
Gavynlee2 小时前
plantuml用法总结
设计模式
咖啡啡不加糖2 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南2 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端