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

}
相关推荐
小王C语言12 分钟前
【C++初阶】--- list容器功能模拟实现
c++·windows·list
zru_960214 分钟前
Java 中常用队列用法详解
java·开发语言
enyp801 小时前
c++ 类和动态内存分配
java·开发语言·c++
东阳马生架构2 小时前
Sentinel源码—6.熔断降级和数据统计的实现二
java·sentinel
爱吃烤鸡翅的酸菜鱼2 小时前
Java【网络原理】(4)HTTP协议
java·网络·后端·网络协议·http
无际单片机编程2 小时前
嵌入式C语言位操作的几种常见用法
java·c语言·stm32·单片机·嵌入式硬件
xoxo-Rachel2 小时前
SpringBoot 基本原理
java·spring boot·spring
凌冰_2 小时前
IDEA2024 pom.xml依赖文件包报红解决
xml·java·intellij-idea
陈璆鸣3 小时前
【java+Mysql】学生信息管理系统
java·mysql·用户登录·学生信息·成绩信息
东阳马生架构3 小时前
Sentinel源码—7.参数限流和注解的实现
java