feat(databus): 完成阶段四-DataBus Server完整功能

- 补充缺失的 API 类(DatabusMessage、DatabusBatchMessage、DatabusEventType)
- 新增变更消息消费者(3个:部门、用户、岗位)
- 新增数据提供者(3个:部门、用户、岗位)
- 确认分发器服务(核心定向推送逻辑)
- 确认全量同步与消息推送组件
- 确认管理后台 API(5个 Controller)
- 确认 Service ��(4个核心服务)
- 确认 DAL 层(7个 DO + Mapper)
- 添加 databus-server starter 依赖到 pom.xml
- 编译验证通过

Ref: docs/databus/implementation-checklist.md 任务 39-70
This commit is contained in:
hewencai
2025-12-01 23:44:32 +08:00
parent f5ba493f95
commit db13036cea
109 changed files with 7673 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
package com.zt.plat.framework.databus.server.config;
import com.zt.plat.framework.databus.server.core.pusher.MessagePusher;
import com.zt.plat.framework.databus.server.core.pusher.MessagePusherImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Databus 消息配置类
*
* @author ZT
*/
@Configuration
public class DatabusMessagingConfiguration {
@Bean
@ConditionalOnMissingBean
public MessagePusher messagePusher(@Autowired(required = false) RocketMQTemplate rocketMQTemplate) {
MessagePusherImpl pusher = new MessagePusherImpl();
pusher.setRocketMQTemplate(rocketMQTemplate);
return pusher;
}
}

View File

@@ -0,0 +1,24 @@
package com.zt.plat.framework.databus.server.config;
import com.zt.plat.framework.databus.server.producer.DatabusMessageProducer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Databus 服务端自动配置
*
* @author ZT
*/
@Configuration
@EnableConfigurationProperties(DatabusServerProperties.class)
@ConditionalOnProperty(prefix = "zt.databus.sync.server", name = "enabled", havingValue = "true")
public class DatabusServerAutoConfiguration {
@Bean
public DatabusMessageProducer databusMessageProducer(DatabusServerProperties properties) {
return new DatabusMessageProducer(properties);
}
}

View File

@@ -0,0 +1,60 @@
package com.zt.plat.framework.databus.server.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
/**
* Databus 服务端配置属性
*
* @author ZT
*/
@Data
@ConfigurationProperties(prefix = "zt.databus.sync.server")
public class DatabusServerProperties {
/**
* 是否启用
*/
private boolean enabled = false;
/**
* MQ 配置
*/
private MqConfig mq = new MqConfig();
/**
* 订阅的客户端列表
*/
private List<String> clients;
@Data
public static class MqConfig {
/**
* 是否启用 MQ 发送
*/
private boolean enabled = true;
/**
* RocketMQ NameServer 地址
*/
private String nameServer;
/**
* Topic 基础名称
*/
private String topicBase = "databus-sync";
/**
* 生产者组名称
*/
private String producerGroup = "databus-server-producer";
/**
* 发送超时时间(毫秒)
*/
private int sendMsgTimeout = 10000; // 默认 10 秒
}
}

View File

@@ -0,0 +1,45 @@
package com.zt.plat.framework.databus.server.config;
import com.zt.plat.framework.databus.server.core.pusher.MessagePusher;
import com.zt.plat.framework.databus.server.core.pusher.MessagePusherImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* Databus 同步服务端自动配置
*
* @author ZT
*/
@Slf4j
@AutoConfiguration
@EnableAsync
@EnableConfigurationProperties(DatabusSyncServerProperties.class)
@ComponentScan(basePackages = "com.zt.plat.framework.databus.server")
@MapperScan("com.zt.plat.framework.databus.server.dal.mapper")
public class DatabusSyncServerAutoConfiguration {
public DatabusSyncServerAutoConfiguration() {
log.info("[Databus] 数据同步服务端模块已加载");
}
/**
* 注册消息推送器 Bean
*/
@Bean
@ConditionalOnBean(RocketMQTemplate.class)
public MessagePusher messagePusher(RocketMQTemplate rocketMQTemplate) {
MessagePusherImpl pusher = new MessagePusherImpl();
pusher.setRocketMQTemplate(rocketMQTemplate);
log.info("[Databus] MessagePusher Bean 已注册");
return pusher;
}
}

View File

@@ -0,0 +1,61 @@
package com.zt.plat.framework.databus.server.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Databus 数据同步服务端配置属性
*
* @author ZT
*/
@Data
@ConfigurationProperties(prefix = "zt.databus.sync.server")
public class DatabusSyncServerProperties {
/**
* 是否启用
*/
private Boolean enabled = true;
/**
* 重试配置
*/
private Retry retry = new Retry();
/**
* 批量推送配置
*/
private Batch batch = new Batch();
@Data
public static class Retry {
/**
* 最大重试次数
*/
private Integer maxAttempts = 5;
/**
* 初始重试延迟(秒)
*/
private Integer initialDelay = 1;
/**
* 重试延迟倍数
*/
private Integer multiplier = 2;
}
@Data
public static class Batch {
/**
* 默认批量大小
*/
private Integer defaultSize = 500;
/**
* 批量推送间隔(秒)
*/
private Integer interval = 5;
}
}

View File

@@ -0,0 +1,92 @@
package com.zt.plat.framework.databus.server.controller.admin;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.databus.server.controller.admin.vo.client.DatabusSyncClientPageReqVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.client.DatabusSyncClientRespVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.client.DatabusSyncClientSaveReqVO;
import com.zt.plat.framework.databus.server.convert.DatabusSyncClientConvert;
import com.zt.plat.framework.databus.server.dal.dataobject.DatabusSyncClientDO;
import com.zt.plat.framework.databus.server.service.DatabusSyncClientService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 数据同步客户端")
@RestController
@RequestMapping("/databus/sync/client")
@Validated
public class DatabusSyncClientController {
@Resource
private DatabusSyncClientService clientService;
@PostMapping("/create")
@Operation(summary = "创建数据同步客户端")
@PreAuthorize("@ss.hasPermission('databus:sync:client:create')")
public CommonResult<Long> createClient(@Valid @RequestBody DatabusSyncClientSaveReqVO createReqVO) {
return success(clientService.createClient(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新数据同步客户端")
@PreAuthorize("@ss.hasPermission('databus:sync:client:update')")
public CommonResult<Boolean> updateClient(@Valid @RequestBody DatabusSyncClientSaveReqVO updateReqVO) {
clientService.updateClient(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除数据同步客户端")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('databus:sync:client:delete')")
public CommonResult<Boolean> deleteClient(@RequestParam("id") Long id) {
clientService.deleteClient(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得数据同步客户端")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('databus:sync:client:query')")
public CommonResult<DatabusSyncClientRespVO> getClient(@RequestParam("id") Long id) {
DatabusSyncClientDO client = clientService.getClient(id);
return success(DatabusSyncClientConvert.INSTANCE.convert(client));
}
@GetMapping("/page")
@Operation(summary = "获得数据同步客户端分页")
@PreAuthorize("@ss.hasPermission('databus:sync:client:query')")
public CommonResult<PageResult<DatabusSyncClientRespVO>> getClientPage(@Valid DatabusSyncClientPageReqVO pageReqVO) {
PageResult<DatabusSyncClientDO> pageResult = clientService.getClientPage(pageReqVO);
return success(DatabusSyncClientConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/list")
@Operation(summary = "获得数据同步客户端列表")
@PreAuthorize("@ss.hasPermission('databus:sync:client:query')")
public CommonResult<List<DatabusSyncClientRespVO>> getClientList() {
List<DatabusSyncClientDO> list = clientService.getClientList();
return success(DatabusSyncClientConvert.INSTANCE.convertList(list));
}
@PutMapping("/update-status")
@Operation(summary = "修改客户端启用状态")
@PreAuthorize("@ss.hasPermission('databus:sync:client:update')")
public CommonResult<Boolean> updateClientStatus(
@RequestParam("id") Long id,
@RequestParam("enabled") Integer enabled) {
clientService.updateClientStatus(id, enabled);
return success(true);
}
}

View File

@@ -0,0 +1,76 @@
package com.zt.plat.framework.databus.server.controller.admin;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.databus.server.controller.admin.vo.deadletter.DatabusSyncDeadLetterPageReqVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.deadletter.DatabusSyncDeadLetterRespVO;
import com.zt.plat.framework.databus.server.convert.DatabusSyncDeadLetterConvert;
import com.zt.plat.framework.databus.server.dal.dataobject.DatabusSyncDeadLetterDO;
import com.zt.plat.framework.databus.server.service.DatabusSyncDeadLetterService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 数据同步死信队列")
@RestController
@RequestMapping("/databus/sync/dead-letter")
@Validated
public class DatabusSyncDeadLetterController {
@Resource
private DatabusSyncDeadLetterService deadLetterService;
@GetMapping("/get")
@Operation(summary = "获得数据同步死信队列")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('databus:sync:dead-letter:query')")
public CommonResult<DatabusSyncDeadLetterRespVO> getDeadLetter(@RequestParam("id") Long id) {
DatabusSyncDeadLetterDO deadLetter = deadLetterService.getDeadLetter(id);
return success(DatabusSyncDeadLetterConvert.INSTANCE.convert(deadLetter));
}
@GetMapping("/page")
@Operation(summary = "获得数据同步死信队列分页")
@PreAuthorize("@ss.hasPermission('databus:sync:dead-letter:query')")
public CommonResult<PageResult<DatabusSyncDeadLetterRespVO>> getDeadLetterPage(@Valid DatabusSyncDeadLetterPageReqVO pageReqVO) {
PageResult<DatabusSyncDeadLetterDO> pageResult = deadLetterService.getDeadLetterPage(pageReqVO);
return success(DatabusSyncDeadLetterConvert.INSTANCE.convertPage(pageResult));
}
@PostMapping("/reprocess")
@Operation(summary = "重新投递死信消息")
@Parameter(name = "id", description = "死信ID", required = true)
@PreAuthorize("@ss.hasPermission('databus:sync:dead-letter:reprocess')")
public CommonResult<Boolean> reprocessDeadLetter(@RequestParam("id") Long id) {
deadLetterService.reprocessDeadLetter(id);
return success(true);
}
@PostMapping("/batch-reprocess")
@Operation(summary = "批量重新投递死信消息")
@PreAuthorize("@ss.hasPermission('databus:sync:dead-letter:reprocess')")
public CommonResult<Boolean> batchReprocessDeadLetter(@RequestBody List<Long> ids) {
deadLetterService.batchReprocessDeadLetter(ids);
return success(true);
}
@PutMapping("/mark-handled")
@Operation(summary = "标记为已处理")
@PreAuthorize("@ss.hasPermission('databus:sync:dead-letter:update')")
public CommonResult<Boolean> markHandled(
@RequestParam("id") Long id,
@RequestParam(value = "remark", required = false) String remark) {
deadLetterService.markHandled(id, remark);
return success(true);
}
}

View File

@@ -0,0 +1,92 @@
package com.zt.plat.framework.databus.server.controller.admin;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.databus.server.controller.admin.vo.event.DatabusSyncEventPageReqVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.event.DatabusSyncEventRespVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.event.DatabusSyncEventSaveReqVO;
import com.zt.plat.framework.databus.server.convert.DatabusSyncEventConvert;
import com.zt.plat.framework.databus.server.dal.dataobject.DatabusSyncEventDO;
import com.zt.plat.framework.databus.server.service.DatabusSyncEventService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 数据同步事件")
@RestController
@RequestMapping("/databus/sync/event")
@Validated
public class DatabusSyncEventController {
@Resource
private DatabusSyncEventService eventService;
@PostMapping("/create")
@Operation(summary = "创建数据同步事件")
@PreAuthorize("@ss.hasPermission('databus:sync:event:create')")
public CommonResult<Long> createEvent(@Valid @RequestBody DatabusSyncEventSaveReqVO createReqVO) {
return success(eventService.createEvent(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新数据同步事件")
@PreAuthorize("@ss.hasPermission('databus:sync:event:update')")
public CommonResult<Boolean> updateEvent(@Valid @RequestBody DatabusSyncEventSaveReqVO updateReqVO) {
eventService.updateEvent(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除数据同步事件")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('databus:sync:event:delete')")
public CommonResult<Boolean> deleteEvent(@RequestParam("id") Long id) {
eventService.deleteEvent(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得数据同步事件")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('databus:sync:event:query')")
public CommonResult<DatabusSyncEventRespVO> getEvent(@RequestParam("id") Long id) {
DatabusSyncEventDO event = eventService.getEvent(id);
return success(DatabusSyncEventConvert.INSTANCE.convert(event));
}
@GetMapping("/page")
@Operation(summary = "获得数据同步事件分页")
@PreAuthorize("@ss.hasPermission('databus:sync:event:query')")
public CommonResult<PageResult<DatabusSyncEventRespVO>> getEventPage(@Valid DatabusSyncEventPageReqVO pageReqVO) {
PageResult<DatabusSyncEventDO> pageResult = eventService.getEventPage(pageReqVO);
return success(DatabusSyncEventConvert.INSTANCE.convertPage(pageResult));
}
@GetMapping("/list")
@Operation(summary = "获得数据同步事件列表")
@PreAuthorize("@ss.hasPermission('databus:sync:event:query')")
public CommonResult<List<DatabusSyncEventRespVO>> getEventList() {
List<DatabusSyncEventDO> list = eventService.getEventList();
return success(DatabusSyncEventConvert.INSTANCE.convertList(list));
}
@PutMapping("/update-status")
@Operation(summary = "修改事件启用状态")
@PreAuthorize("@ss.hasPermission('databus:sync:event:update')")
public CommonResult<Boolean> updateEventStatus(
@RequestParam("id") Long id,
@RequestParam("enabled") Integer enabled) {
eventService.updateEventStatus(id, enabled);
return success(true);
}
}

View File

@@ -0,0 +1,69 @@
package com.zt.plat.framework.databus.server.controller.admin;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.databus.server.controller.admin.vo.pushlog.DatabusSyncPushLogPageReqVO;
import com.zt.plat.framework.databus.server.controller.admin.vo.pushlog.DatabusSyncPushLogRespVO;
import com.zt.plat.framework.databus.server.convert.DatabusSyncPushLogConvert;
import com.zt.plat.framework.databus.server.dal.dataobject.DatabusSyncEventRecordDO;
import com.zt.plat.framework.databus.server.dal.dataobject.DatabusSyncLogDO;
import com.zt.plat.framework.databus.server.dal.mapper.DatabusSyncEventRecordMapper;
import com.zt.plat.framework.databus.server.service.DatabusSyncLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 数据同步推送日志")
@RestController
@RequestMapping("/databus/sync/push-log")
@Validated
public class DatabusSyncPushLogController {
@Resource
private DatabusSyncLogService pushLogService;
@Resource
private DatabusSyncEventRecordMapper eventRecordMapper;
@GetMapping("/get")
@Operation(summary = "获得数据同步推送日志")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PreAuthorize("@ss.hasPermission('databus:sync:push-log:query')")
public CommonResult<DatabusSyncPushLogRespVO> getPushLog(@RequestParam("id") Long id) {
DatabusSyncLogDO pushLog = pushLogService.getPushLog(id);
DatabusSyncPushLogRespVO respVO = DatabusSyncPushLogConvert.INSTANCE.convert(pushLog);
// 关联查询事件记录,获取消息内容
if (pushLog != null && pushLog.getEventRecordId() != null) {
DatabusSyncEventRecordDO eventRecord = eventRecordMapper.selectById(pushLog.getEventRecordId());
if (eventRecord != null) {
respVO.setDataSnapshot(eventRecord.getDataSnapshot());
}
}
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得数据同步推送日志分页")
@PreAuthorize("@ss.hasPermission('databus:sync:push-log:query')")
public CommonResult<PageResult<DatabusSyncPushLogRespVO>> getPushLogPage(@Valid DatabusSyncPushLogPageReqVO pageReqVO) {
PageResult<DatabusSyncLogDO> pageResult = pushLogService.getPushLogPage(pageReqVO);
return success(DatabusSyncPushLogConvert.INSTANCE.convertPage(pageResult));
}
@PostMapping("/retry")
@Operation(summary = "重试推送")
@Parameter(name = "id", description = "日志ID", required = true)
@PreAuthorize("@ss.hasPermission('databus:sync:push-log:retry')")
public CommonResult<Boolean> retryPush(@RequestParam("id") Long id) {
pushLogService.retryPush(id);
return success(true);
}
}

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