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

}
相关推荐
七月丶2 小时前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞2 小时前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
阿白的白日梦3 小时前
winget基础管理---更新/修改源为国内源
windows
九狼3 小时前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
SimonKing3 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean3 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven975 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java
皮皮林55114 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河14 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化