Merge branch 'dev' into 'test'

feat(databus): 完成阶段一+二-数据契约层与数据提供者

See merge request jygk/dsc!4
This commit is contained in:
wencai he
2025-12-04 06:13:11 +00:00
163 changed files with 11680 additions and 8 deletions

View File

@@ -17,7 +17,8 @@
<module>zt-spring-boot-starter-web</module>
<module>zt-spring-boot-starter-security</module>
<module>zt-spring-boot-starter-websocket</module>
<module>zt-spring-boot-starter-databus-server</module>
<module>zt-spring-boot-starter-databus-client</module>
<module>zt-spring-boot-starter-monitor</module>
<module>zt-spring-boot-starter-protection</module>
<!-- <module>zt-spring-boot-starter-config</module>-->

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.zt.plat</groupId>
<artifactId>zt-framework</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zt-spring-boot-starter-databus-client</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>DataBus 客户端组件,负责接收数据变更并同步</description>
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<dependencies>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-common</artifactId>
</dependency>
<!-- Databus API事件类型枚举等 -->
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-databus-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- System API用于默认Handler实现 -->
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-system-api</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- MQ 相关 -->
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-spring-boot-starter-mq</artifactId>
</dependency>
<!-- Redis 相关 (用于幂等) -->
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-spring-boot-starter-redis</artifactId>
</dependency>
<!-- Web 相关 (用于HTTP接收) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,23 @@
package com.zt.plat.framework.databus.client.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
/**
* Databus 同步客户端自动配置
*
* @author ZT
*/
@Slf4j
@AutoConfiguration
@EnableConfigurationProperties(DatabusSyncClientProperties.class)
@ComponentScan(basePackages = "com.zt.plat.framework.databus.client")
public class DatabusSyncClientAutoConfiguration {
public DatabusSyncClientAutoConfiguration() {
log.info("[Databus] 数据同步客户端模块已加载");
}
}

View File

@@ -0,0 +1,43 @@
package com.zt.plat.framework.databus.client.core.controller;
import com.zt.plat.framework.databus.client.core.processor.MessageProcessor;
import com.zt.plat.module.databus.enums.DatabusEventType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
/**
* 同步消息HTTP接收控制器
*
* @author ZT
*/
@Slf4j
@RestController
@RequestMapping("${zt.databus.sync.client.http.endpoint:/databus/sync/receive}")
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "zt.databus.sync.client.http", name = "enabled", havingValue = "true")
public class SyncMessageController {
private final MessageProcessor messageProcessor;
/**
* 接收同步消息
*
* @param eventType 事件类型
* @param message 消息体
*/
@PostMapping("/{eventType}")
public void receive(@PathVariable("eventType") String eventType, @RequestBody String message) {
log.debug("[Databus Client] 接收到HTTP消息, eventType={}", eventType);
DatabusEventType type = DatabusEventType.valueOf(eventType);
if (type == null) {
log.warn("[Databus Client] 未知的事件类型: {}", eventType);
return;
}
messageProcessor.process(message, type);
}
}

View File

@@ -0,0 +1,19 @@
package com.zt.plat.framework.databus.client.core.idempotent;
/**
* 幂等存储接口
*
* @author ZT
*/
public interface IdempotentStore {
/**
* 检查并记录消息是否已处理
*
* @param syncId 同步ID
* @param expireSeconds 过期时间(秒)
* @return true-未处理(可以处理), false-已处理(应该跳过)
*/
boolean checkAndMark(String syncId, int expireSeconds);
}

View File

@@ -0,0 +1,30 @@
package com.zt.plat.framework.databus.client.core.idempotent;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* 基于 Redis 的幂等存储实现
*
* @author ZT
*/
@Component
@RequiredArgsConstructor
public class RedisIdempotentStore implements IdempotentStore {
private static final String KEY_PREFIX = "databus:sync:idempotent:";
private final StringRedisTemplate stringRedisTemplate;
@Override
public boolean checkAndMark(String syncId, int expireSeconds) {
String key = KEY_PREFIX + syncId;
Boolean success = stringRedisTemplate.opsForValue()
.setIfAbsent(key, "1", expireSeconds, TimeUnit.SECONDS);
return Boolean.TRUE.equals(success);
}
}

View File

@@ -0,0 +1,54 @@
package com.zt.plat.framework.databus.client.core.message;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 数据同步消息(服务端推送格式)
*
* @author ZT
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SyncMessage {
/**
* 同步ID唯一标识
*/
private String syncId;
/**
* 事件记录ID
*/
private Long eventRecordId;
/**
* 事件类型
*/
private String eventType;
/**
* 事件动作
*/
private String eventAction;
/**
* 业务数据快照JSON字符串
*/
private String dataSnapshot;
/**
* 数据版本
*/
private Integer dataVersion;
/**
* 时间戳
*/
private Long timestamp;
}

Some files were not shown because too many files have changed in this diff Show More