feat(property): 添加自动抄表功能

This commit is contained in:
2025-08-27 19:27:02 +08:00
parent 78d97e14ee
commit 4d76a4df45
14 changed files with 275 additions and 201 deletions

View File

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.domain.TreeNode;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -103,4 +104,17 @@ public class TbMeterInfoController extends BaseController {
@PathVariable("ids") Long[] ids) {
return toAjax(tbMeterInfoService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 生成 社区/建组/单元/楼栋/(水电气表)树结构
*
* @param meterType 水电气类型
*
* @return (水电气表)树结构
*/
@GetMapping("/tree/{meterType}")
public R<List<TreeNode<Long>>> queryMeterInfoTree(@PathVariable("meterType") Long meterType) {
return R.ok(tbMeterInfoService.queryMeterInfoTree(meterType));
}
}

View File

@@ -32,8 +32,8 @@ public class TbMeterRecordBo extends BaseEntity {
/**
* 仪表编号
*/
@NotBlank(message = "仪表编号不能为空", groups = { AddGroup.class, EditGroup.class })
private String meterId;
@NotNull(message = "仪表编号不能为空", groups = { AddGroup.class, EditGroup.class })
private Long meterId;
/**
* 设备类型(1-电表2-水表3-气表)

View File

@@ -33,7 +33,7 @@ public class TbMeterRecord extends TenantEntity {
/**
* 仪表编号
*/
private String meterId;
private Long meterId;
/**
* 设备类型(1-电表2-水表3-气表)

View File

@@ -0,0 +1,33 @@
package org.dromara.property.domain.enums;
import lombok.Getter;
/**
* @author lsm
* @apiNote MeterRecordTypeEnum
* @since 2025/8/27
*/
@Getter
public enum MeterRecordTypeEnum {
/**
* 手动上报
*/
MANUAL_RECORD(1L),
/**
* 自动上报
*/
AUTO_RECORD(2L),
/**
* 用户上报
*/
USER_RECORD(3L);
private final Long code;
MeterRecordTypeEnum(Long code) {
this.code = code;
}
}

View File

@@ -37,7 +37,7 @@ public class TbMeterRecordVo implements Serializable {
* 仪表编号
*/
@ExcelProperty(value = "仪表编号")
private String meterId;
private Long meterId;
/**
* 设备类型(1-电表2-水表3-气表)

View File

@@ -1,15 +1,18 @@
package org.dromara.property.rocketmq.consumer;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.dromara.property.rocketmq.RocketMqConstants;
import org.dromara.property.rocketmq.domain.MeterResult;
import org.dromara.property.service.smartDevicesService.ITbMeterRecordService;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @author lsm
@@ -21,17 +24,19 @@ import java.util.Arrays;
@RequiredArgsConstructor
@RocketMQMessageListener(
topic = RocketMqConstants.TOPIC,
consumerGroup = RocketMqConstants.GROUP,
consumerGroup = RocketMqConstants.METER_GROUP,
selectorExpression = RocketMqConstants.METER_RECORD
)
public class MeterRecordConsumer implements RocketMQListener<MessageExt> {
private final ITbMeterRecordService meterRecordService;
@Override
public void onMessage(MessageExt ext) {
log.info("消费仪表上报数据,数据长度={}", ext.getBody().length);
try {
String message = new String(ext.getBody());
log.info("物业仪表上报数据,数据={}", message);
List<MeterResult> meterResults = JSONUtil.toList(new String(ext.getBody()), MeterResult.class);
meterRecordService.autoWriteMeterRecord(meterResults);
} catch (Exception e) {
log.error("消费仪表上报数据处理失败,", e);
}

View File

@@ -0,0 +1,20 @@
package org.dromara.property.rocketmq.domain;
import lombok.Data;
import java.util.List;
/**
* @author lsm
* @apiNote MeterResult
* @since 2025/8/27
*/
@Data
public class MeterResult {
private String ip;
private String recordTime;
private List<Float> collectionValue;
}

View File

@@ -1,8 +1,10 @@
package org.dromara.property.service.impl.smartDevicesImpl;
import cn.hutool.core.lang.Assert;
import org.dromara.common.core.domain.TreeNode;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.TreeUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,9 +12,15 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.property.domain.bo.TbFloorBo;
import org.dromara.property.domain.vo.TbBuildingVo;
import org.dromara.property.domain.vo.TbCommunityVo;
import org.dromara.property.domain.vo.TbFloorVo;
import org.dromara.property.service.ITbBuildingService;
import org.dromara.property.service.ITbCommunityService;
import org.dromara.property.service.ITbFloorService;
import org.dromara.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.dromara.property.domain.bo.smartDevicesBo.TbMeterInfoBo;
import org.dromara.property.domain.vo.smartDevicesVo.TbMeterInfoVo;
@@ -21,6 +29,7 @@ import org.dromara.property.mapper.smartDevicesMapper.TbMeterInfoMapper;
import org.dromara.property.service.smartDevicesService.ITbMeterInfoService;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
@@ -39,6 +48,8 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService {
private final TbMeterInfoMapper baseMapper;
private final ITbFloorService floorService;
private final ITbBuildingService buildingService;
private final ITbCommunityService communityService;
/**
* 查询水电气
@@ -94,6 +105,7 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TbMeterInfo> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(TbMeterInfo::getId);
lqw.like(StringUtils.isNotBlank(bo.getHostIp()), TbMeterInfo::getHostIp, bo.getHostIp());
lqw.like(StringUtils.isNotBlank(bo.getMeterName()), TbMeterInfo::getMeterName, bo.getMeterName());
lqw.eq(StringUtils.isNotBlank(bo.getMeterCode()), TbMeterInfo::getMeterCode, bo.getMeterCode());
lqw.eq(StringUtils.isNotBlank(bo.getFactoryNo()), TbMeterInfo::getFactoryNo, bo.getFactoryNo());
@@ -160,4 +172,71 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService {
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 查询水电气树结构
*
* @param meterType 水电气类型
* @return 水电气树结构
*/
@Override
public List<TreeNode<Long>> queryMeterInfoTree(Long meterType) {
// 默认加载社区树
List<TreeNode<Long>> treeList = new ArrayList<>();
List<TbCommunityVo> tbCommunityVos = communityService.queryAll();
if (tbCommunityVos == null || tbCommunityVos.isEmpty()) {
return treeList;
}
List<TreeNode<Long>> l1 = tbCommunityVos.stream().map(item -> {
TreeNode<Long> node = new TreeNode<>();
node.setLevel(1);
node.setCode(item.getId());
node.setParentCode(0L);
node.setLabel(item.getCommunityName());
return node;
}).toList();
treeList.addAll(l1);
List<TbBuildingVo> tbBuildingVos = buildingService.queryAll();
if (tbBuildingVos == null || tbBuildingVos.isEmpty()) {
return treeList;
}
List<TreeNode<Long>> l2 = tbBuildingVos.stream().map(item -> {
TreeNode<Long> node = new TreeNode<>();
node.setLevel(2);
node.setCode(item.getId());
node.setParentCode(item.getCommunityId());
node.setLabel(item.getBuildingName());
return node;
}).toList();
treeList.addAll(l2);
List<TbFloorVo> tbFloorVos = floorService.queryAll();
if (tbFloorVos == null || tbFloorVos.isEmpty()) {
return treeList;
}
List<TreeNode<Long>> l3 = tbFloorVos.stream().map(item -> {
TreeNode<Long> node = new TreeNode<>();
node.setLevel(3);
node.setCode(item.getId());
node.setParentCode(item.getBuildingId());
node.setLabel(item.getFloorName());
return node;
}).toList();
treeList.addAll(l3);
TbMeterInfoBo bo = new TbMeterInfoBo();
bo.setMeterType(meterType);
List<TbMeterInfoVo> meterInfoVos = this.queryList(bo);
if (meterInfoVos != null && !meterInfoVos.isEmpty()) {
List<TreeNode<Long>> l4 = meterInfoVos.stream().map(item -> {
TreeNode<Long> node = new TreeNode<>();
node.setLevel(4);
node.setCode(item.getId());
node.setParentCode(item.getFloorId());
node.setLabel(item.getMeterName());
return node;
}).toList();
treeList.addAll(l4);
}
return TreeUtils.build(treeList, 0L);
}
}

View File

@@ -1,5 +1,9 @@
package org.dromara.property.service.impl.smartDevicesImpl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONObject;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -9,22 +13,31 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.property.domain.bo.smartDevicesBo.TbMeterInfoBo;
import org.dromara.property.domain.enums.MeterRecordTypeEnum;
import org.dromara.property.domain.vo.smartDevicesVo.TbMeterInfoVo;
import org.dromara.property.rocketmq.domain.MeterResult;
import org.dromara.property.service.smartDevicesService.ITbMeterInfoService;
import org.dromara.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.dromara.property.domain.bo.smartDevicesBo.TbMeterRecordBo;
import org.dromara.property.domain.vo.smartDevicesVo.TbMeterRecordVo;
import org.dromara.property.domain.entity.smartDevices.TbMeterRecord;
import org.dromara.property.mapper.smartDevicesMapper.TbMeterRecordMapper;
import org.dromara.property.service.smartDevicesService.ITbMeterRecordService;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 抄记录Service业务层处理
*
* @author lsm
* @date 2025-07-19
* @since 2025-07-19
*/
@Slf4j
@RequiredArgsConstructor
@@ -32,6 +45,7 @@ import java.util.Collection;
public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
private final TbMeterRecordMapper baseMapper;
private final ITbMeterInfoService tbMeterInfoService;
/**
* 查询抄记录
@@ -40,7 +54,7 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
* @return 抄记录
*/
@Override
public TbMeterRecordVo queryById(Long id){
public TbMeterRecordVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
@@ -74,7 +88,7 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TbMeterRecord> lqw = Wrappers.lambdaQuery();
lqw.orderByAsc(TbMeterRecord::getId);
lqw.eq(StringUtils.isNotBlank(bo.getMeterId()), TbMeterRecord::getMeterId, bo.getMeterId());
lqw.eq(bo.getMeterId() != null, TbMeterRecord::getMeterId, bo.getMeterId());
lqw.eq(bo.getMeterType() != null, TbMeterRecord::getMeterType, bo.getMeterType());
lqw.eq(bo.getReaderId() != null, TbMeterRecord::getReaderId, bo.getReaderId());
lqw.eq(bo.getReadingTime() != null, TbMeterRecord::getReadingTime, bo.getReadingTime());
@@ -118,7 +132,7 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(TbMeterRecord entity){
private void validEntityBeforeSave(TbMeterRecord entity) {
//TODO 做一些数据校验,如唯一约束
}
@@ -131,9 +145,84 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 自动写入抄表记录
*
* @param results 推送消息
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void autoWriteMeterRecord(List<MeterResult> results) {
log.info("自动写入抄表记录, msg:{}", results);
for (MeterResult result : results) {
// 取出同一个采集器ip下所有设备
TbMeterInfoBo infoBo = new TbMeterInfoBo();
infoBo.setHostIp(result.getIp());
List<TbMeterInfoVo> infoList = tbMeterInfoService.queryList(infoBo);
if (CollUtil.isEmpty(infoList)) {
log.info("当前采集器ip下无设备, ip:{}", result.getIp());
continue;
}
// 获取设备id
Collection<Long> meterIds = infoList.stream().map(TbMeterInfoVo::getId).toList();
// 取出上次抄表记录
LambdaQueryWrapper<TbMeterRecord> lqw = new LambdaQueryWrapper<>();
lqw.in(TbMeterRecord::getMeterId, meterIds)
.orderByDesc(TbMeterRecord::getReadingTime)
.last("limit " + meterIds.size());
List<TbMeterRecord> recordOld = baseMapper.selectList(lqw);
List<TbMeterRecord> recordNew = new ArrayList<>(infoList.size());
boolean hasOldRecords = CollUtil.isNotEmpty(recordOld);
log.info("当前采集器ip下{}抄表记录, ip:{}", hasOldRecords ? "" : "", result.getIp());
// 创建meterId到旧记录的映射提高查找效率
Map<Long, TbMeterRecord> oldRecordMap = hasOldRecords ?
recordOld.stream().collect(Collectors.toMap(TbMeterRecord::getMeterId, Function.identity())) :
Collections.emptyMap();
for (TbMeterInfoVo info : infoList) {
TbMeterRecord record = new TbMeterRecord();
record.setMeterId(info.getId());
record.setMeterType(info.getMeterType());
record.setReaderId(1L);
record.setReadingTime(DateUtil.parse(result.getRecordTime(), "yyyy-MM-dd HH:mm:ss"));
// 获取当前读数
BigDecimal currentReading = BigDecimal.valueOf(
result.getCollectionValue().get(Integer.parseInt(info.getMeterCode()))
);
record.setCurrentReading(currentReading);
// 设置上次读数
if (hasOldRecords) {
TbMeterRecord oldRecord = oldRecordMap.get(info.getId());
if (oldRecord != null) {
record.setPreviousReading(oldRecord.getCurrentReading());
} else {
// 如果没有找到对应的旧记录,使用默认值
record.setPreviousReading(BigDecimal.ZERO);
}
} else {
record.setPreviousReading(BigDecimal.ZERO);
}
record.setReadingMethod(MeterRecordTypeEnum.AUTO_RECORD.getCode());
recordNew.add(record);
}
boolean flag = baseMapper.insertBatch(recordNew);
Assert.isTrue(flag, "批量写入抄表记录失败!");
}
}
}

View File

@@ -1,5 +1,6 @@
package org.dromara.property.service.smartDevicesService;
import org.dromara.common.core.domain.TreeNode;
import org.dromara.property.domain.vo.smartDevicesVo.TbMeterInfoVo;
import org.dromara.property.domain.bo.smartDevicesBo.TbMeterInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -65,4 +66,13 @@ public interface ITbMeterInfoService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 查询水电气树结构
*
* @param meterType 水电气类型
*
* @return 水电气树结构
*/
List<TreeNode<Long>> queryMeterInfoTree(Long meterType);
}

View File

@@ -4,6 +4,7 @@ import org.dromara.property.domain.vo.smartDevicesVo.TbMeterRecordVo;
import org.dromara.property.domain.bo.smartDevicesBo.TbMeterRecordBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.property.rocketmq.domain.MeterResult;
import java.util.Collection;
import java.util.List;
@@ -65,4 +66,11 @@ public interface ITbMeterRecordService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 自动写入抄表记录
*
* @param results 推送消息
*/
void autoWriteMeterRecord(List<MeterResult> results);
}

View File

@@ -1,75 +0,0 @@
package org.dromara.sis.config;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author lsm
* @apiNote RocketMQClusterConfig
* @since 2025/8/26
*/
@Configuration
public class RocketMQClusterConfig {
// 从配置文件中读取 cluster 的配置
@Value("${rocketmq.cluster1.name-server}")
private String nameServer1;
@Value("${rocketmq.cluster1.producer.group}")
private String producerGroup1;
// 为第一个集群创建生产者实例
@Bean({"clusterProducerOne"})
public DefaultMQProducer clusterProducerOne() throws Exception {
DefaultMQProducer producer = new DefaultMQProducer(producerGroup1);
producer.setNamesrvAddr(nameServer1);
// 设置发送超时时间
producer.setSendMsgTimeout(5000);
// 设置重试次数
producer.setRetryTimesWhenSendFailed(2);
producer.setRetryTimesWhenSendAsyncFailed(2);
return producer;
}
// 使用上面的生产者实例创建 RocketMQTemplate
@Bean("rocketMQTemplateClusterOne")
public RocketMQTemplate rocketMQTemplateClusterOne(@Qualifier("clusterProducerOne") DefaultMQProducer producer) {
RocketMQTemplate template = new RocketMQTemplate();
template.setProducer(producer);
return template;
}
// 从配置文件中读取 cluster 的配置
// @Value("${rocketmq.cluster2.name-server}")
// private String nameServer2;
//
// @Value("${rocketmq.cluster2.producer.group}")
// private String producerGroup2;
//
// // 为第二个集群创建生产者实例
// @Bean({"clusterProducerTwo"})
// public DefaultMQProducer clusterProducerTwo() throws Exception {
// DefaultMQProducer producer = new DefaultMQProducer(producerGroup2);
// producer.setNamesrvAddr(nameServer2);
// // 设置发送超时时间
// producer.setSendMsgTimeout(5000);
// // 设置重试次数
// producer.setRetryTimesWhenSendFailed(2);
// producer.setRetryTimesWhenSendAsyncFailed(2);
// return producer;
// }
//
// // 使用上面的生产者实例创建 RocketMQTemplate
// @Bean("rocketMQTemplateClusterTwo")
// public RocketMQTemplate rocketMQTemplateClusterTwo(@Qualifier("clusterProducerTwo") DefaultMQProducer producer) {
// RocketMQTemplate template = new RocketMQTemplate();
// template.setProducer(producer);
// return template;
// }
}

View File

@@ -1,44 +0,0 @@
package org.dromara.sis.rocketmq.consumer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.dromara.sis.rocketmq.RocketMqConstants;
import org.dromara.sis.rocketmq.producer.ProducerService;
import org.springframework.stereotype.Component;
/**
* @author lsm
* @apiNote MeterRecordConsumer
* @since 2025/8/25
*/
@Slf4j
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(
topic = RocketMqConstants.TOPIC,
consumerGroup = RocketMqConstants.METER_GROUP,
selectorExpression = RocketMqConstants.METER_RECORD,
nameServer = "${rocketmq.cluster1.name-server}"
)
public class MeterRecordConsumer implements RocketMQListener<MessageExt> {
private final ProducerService producerService;
@Override
public void onMessage(MessageExt ext) {
try {
if (ext.getBody() == null) {
log.info("仪表上报消息数据,不转发!");
} else {
producerService.defaultSend(RocketMqConstants.TOPIC, RocketMqConstants.METER_RECORD, new String(ext.getBody()));
log.info("转发仪表上报数据处理成功");
}
} catch (Exception e) {
log.error("转发仪表上报数据处理失败,", e);
}
}
}

View File

@@ -1,65 +0,0 @@
package org.dromara.sis.rocketmq.producer;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
/**
* @author lsm
* @apiNote ProducerService
* @since 2025/8/26
*/
@Slf4j
@Component
public class ProducerService {
@Autowired
@Qualifier("rocketMQTemplateClusterOne")
private RocketMQTemplate rocketMQTemplateClusterOne;
// @Autowired
// @Qualifier("rocketMQTemplateClusterTwo")
// private RocketMQTemplate rocketMQTemplateClusterTwo;
/**
* 向mq写入消息
*
* @param topic 消息topic
* @param tag 消息tag
* @param msg 消息
*/
public void defaultSend(String topic, String tag, String msg) {
try {
String destination = topic + ":" + tag;
// 使用 RocketMQTemplate 的同步发送方法
rocketMQTemplateClusterOne.syncSend(destination, msg);
log.info("发送RocketMQOne消息成功, nameServer:{}", rocketMQTemplateClusterOne.getProducer().getNamesrvAddr());
} catch (Exception e) {
log.error("发送RocketMQOne消息失败", e);
}
}
/**
* 向mq写入消息
*
* @param topic 消息topic
* @param tag 消息tag
* @param msg 消息
*/
// public void clusterSend(String topic, String tag, String msg) {
// try {
// String destination = topic + ":" + tag;
// // 使用 RocketMQTemplate 的同步发送方法
// rocketMQTemplateClusterTwo.syncSend(destination, msg);
//
// log.info("发送RocketMQTwo消息成功, nameServer:{}", rocketMQTemplateClusterTwo.getProducer().getNamesrvAddr());
// } catch (Exception e) {
// log.error("发送RocketMQTwo消息失败", e);
// }
// }
}