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

}
相关推荐
Wang15305 小时前
jdk内存配置优化
java·计算机网络
0和1的舞者5 小时前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
蒜丶5 小时前
Windows 11 22H2 跳过联网激活
windows
Wang15305 小时前
Java多线程死锁排查
java·计算机网络
小小星球之旅6 小时前
CompletableFuture学习
java·开发语言·学习
jiayong236 小时前
知识库概念与核心价值01
java·人工智能·spring·知识库
皮皮林5517 小时前
告别 OOM:EasyExcel 百万数据导出最佳实践(附开箱即用增强工具类)
java
Da Da 泓7 小时前
多线程(七)【线程池】
java·开发语言·线程池·多线程
To Be Clean Coder7 小时前
【Spring源码】getBean源码实战(三)
java·mysql·spring
Wokoo78 小时前
开发者AI大模型学习与接入指南
java·人工智能·学习·架构