diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/EchartsDataUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/EchartsDataUtils.java index cc5b62e..49d31bb 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/EchartsDataUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/EchartsDataUtils.java @@ -215,7 +215,10 @@ public class EchartsDataUtils { if ("percentile95".equals(metricName) && !fixedPercentile95Value.equals(0)) { return fixedPercentile95Value; } - + // deployDevice特殊处理 + if ("deployDevice".equals(metricName)) { + return fixedPercentile95Value; + } // 智能补全策略 if (hasRealData) { // 数据集中有真实数据:所有缺失点都补null @@ -259,7 +262,11 @@ public class EchartsDataUtils { dataNames.forEach(name -> { List seriesData = new ArrayList<>(); for (int i = 0; i < dataSize; i++) { - if (i == 0) { + // deployDevice特殊处理:始终补空字符串 + if ("deployDevice".equals(name)) { + seriesData.add(""); + } + else if (i == 0) { // 第一个点补0 seriesData.add(0); } else { @@ -291,21 +298,35 @@ public class EchartsDataUtils { } /** - * 查找percentile95的固定值(第一个非零值) + * 查找特殊字段的固定值 + * percentile95: 第一个非零值 + * deployDevice: 第一个非空值,没值填充空字符串 */ private static Object findFixedValueForPercentile95(List list, Map> dataExtractors) { - if (!dataExtractors.containsKey("percentile95")) { - return 0; - } - - Function extractor = dataExtractors.get("percentile95"); - for (T item : list) { - Object value = extractor.apply(item); - if (value != null) { - return value; + // 处理percentile95字段 + if (dataExtractors.containsKey("percentile95")) { + Function extractor = dataExtractors.get("percentile95"); + for (T item : list) { + Object value = extractor.apply(item); + if (value != null && !isZeroValue(value)) { + return value; + } } } - return 0; + + // 处理deployDevice字段 + if (dataExtractors.containsKey("deployDevice")) { + Function extractor = dataExtractors.get("deployDevice"); + for (T item : list) { + Object value = extractor.apply(item); + if (value != null) { + return value; + } + } + return ""; // deployDevice没值返回空字符串 + } + + return 0; // 默认返回0 } /** diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpeedUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpeedUtils.java index 4a36bf4..80f1631 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpeedUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpeedUtils.java @@ -155,7 +155,7 @@ public class SpeedUtils { throws NoSuchFieldException, IllegalAccessException { if (list == null || list.isEmpty()) { - return null; + return "Kb"; } BigDecimal totalInSpeedBit = BigDecimal.ZERO; diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml index 63fc12c..4268586 100644 --- a/ruoyi-modules/pom.xml +++ b/ruoyi-modules/pom.xml @@ -13,6 +13,7 @@ ruoyi-gen ruoyi-job ruoyi-file + ruoyi-mtragent ruoyi-modules diff --git a/ruoyi-modules/ruoyi-mtragent/pom.xml b/ruoyi-modules/ruoyi-mtragent/pom.xml new file mode 100644 index 0000000..b9ad8ff --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/pom.xml @@ -0,0 +1,100 @@ + + 4.0.0 + + com.ruoyi + ruoyi-modules + 3.6.6 + + + ruoyi-modules-mtragent + + + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + + org.apache.rocketmq + rocketmq-client + 4.9.0 + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + com.alibaba.nacos + nacos-client + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.mysql + mysql-connector-j + + + + + com.ruoyi + ruoyi-common-log + + + + + com.ruoyi + ruoyi-common-swagger + + + + + com.ruoyi + ruoyi-common-security + + + org.projectlombok + lombok + + + + + org.yaml + snakeyaml + 1.28 + + + + + org.springframework.boot + spring-boot-starter-web + + + diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/RuoYiMtragentApplication.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/RuoYiMtragentApplication.java new file mode 100644 index 0000000..d14b928 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/RuoYiMtragentApplication.java @@ -0,0 +1,25 @@ +package com.ruoyi.mtragent; + +import com.ruoyi.common.security.annotation.EnableCustomConfig; +import com.ruoyi.common.security.annotation.EnableRyFeignClients; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableAsync; + +/** + * 平台管理模块 + * + * @author ruoyi + */ +@EnableCustomConfig +@EnableRyFeignClients +@SpringBootApplication +@EnableAsync +public class RuoYiMtragentApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiMtragentApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ RuoYiMtragent模块启动成功 ლ(´ڡ`ლ)゙"); + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ConsumerConfig.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ConsumerConfig.java new file mode 100644 index 0000000..0d1cd75 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ConsumerConfig.java @@ -0,0 +1,77 @@ +package com.ruoyi.mtragent.config; + +import com.ruoyi.mtragent.consumer.RocketMsgListener; +import com.ruoyi.mtragent.enums.MessageTopic; +import com.ruoyi.mtragent.model.ConsumerMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +/** + * 消费者配置 + */ +@RefreshScope +@Configuration +@Slf4j +public class ConsumerConfig { + + @Autowired + private ConsumerMode consumerMode; + + @Autowired + private RocketMsgListener rocketMsgListener; + + @Bean + public DefaultMQPushConsumer getRocketMQConsumer() { + //构建客户端连接 + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getAgentGroup()); + // + consumer.setNamesrvAddr(consumerMode.getNamesrvAddr()); + consumer.setConsumeThreadMin(consumerMode.getConsumeThreadMin()); + consumer.setConsumeThreadMax(consumerMode.getConsumeThreadMax()); + consumer.registerMessageListener(rocketMsgListener); + /** + * 1. CONSUME_FROM_LAST_OFFSET:第一次启动从队列最后位置消费,后续再启动接着上次消费的进度开始消费 + * 2. CONSUME_FROM_FIRST_OFFSET:第一次启动从队列初始位置消费,后续再启动接着上次消费的进度开始消费 + * 3. CONSUME_FROM_TIMESTAMP:第一次启动从指定时间点位置消费,后续再启动接着上次消费的进度开始消费 + * 以上所说的第一次启动是指从来没有消费过的消费者,如果该消费者消费过,那么会在broker端记录该消费者的消费位置,如果该消费者挂了再启动,那么自动从上次消费的进度开始 + */ + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + /** + * CLUSTERING (集群模式) :默认模式,同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消息加起来才是所 + * 订阅topic整体,从而达到负载均衡的目的 + * BROADCASTING (广播模式) :同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息,也就是一个消费会被多次分发,被多个consumer消费。 + * 需要注意的是,在广播模式下,每个Consumer都会独立地处理相同的消息副本。这可能会导致一些潜在的问题,例如消息重复处理或者资源浪费。因此,在使用广播模式时,请确保消息的处理逻辑是幂等的,并仔细考虑系统资源的消耗。 + */ + // consumer.setMessageModel(MessageModel.BROADCASTING); + + consumer.setVipChannelEnabled(false); + consumer.setConsumeMessageBatchMaxSize(consumerMode.getConsumeMessageBatchMaxSize()); + try { + /** + * 订阅topic,可以对指定消息进行过滤,例如:"TopicTest","tagl||tag2||tag3",*或null表示topic所有消息 + * 由于官方并没有给直接订阅全部消息示例 所以使用list列表循环订阅所有topic + */ + // 获取所有topic列表 + MessageTopic messageTopic = new MessageTopic(); + List allTopics = messageTopic.RocketMQTopicList(); + //订阅所有topic + for (String topic : allTopics) { + consumer.subscribe(topic,"*"); + } + consumer.start(); + log.info("消费者初始化成功:{}", consumer); + } catch (MQClientException e) { + e.printStackTrace(); + log.error("消费者初始化失败:{}",e.getMessage()); + } + return consumer; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ProducerConfig.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ProducerConfig.java new file mode 100644 index 0000000..89c3f79 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/config/ProducerConfig.java @@ -0,0 +1,56 @@ +package com.ruoyi.mtragent.config; + +import com.ruoyi.mtragent.model.ProducerMode; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * mq搭建地址连接 + * 生产者初者连接信息 具体看nacos配置 + */ +@Configuration +@Slf4j +public class ProducerConfig { + + /** + * 远程调用连接信息 + */ + public static DefaultMQProducer producer; + + /** + * 连接客户端信息配置 具体看nacos配置 + */ + @Autowired + private ProducerMode producerMode; + + @Bean + public DefaultMQProducer getRocketMQProducer() { + producer = new DefaultMQProducer(producerMode.getAgentGroup()); + producer.setNamesrvAddr(producerMode.getNamesrvAddr()); + //如果需要同一个jvm中不同的producer往不同的mq集群发送消息,需要设置不同的instanceName + if(producerMode.getMaxMessageSize()!=null){ + producer.setMaxMessageSize(producerMode.getMaxMessageSize()); + } + if(producerMode.getSendMsgTimeout()!=null){ + producer.setSendMsgTimeout(producerMode.getSendMsgTimeout()); + } + //如果发送消息失败,设置重试次数,默认为2次 + if(producerMode.getRetryTimesWhenSendFailed()!=null){ + producer.setRetryTimesWhenSendFailed(producerMode.getRetryTimesWhenSendFailed()); + } + producer.setVipChannelEnabled(false); + try { + producer.start(); + log.info("生产者初始化成功:{}",producer.toString()); + } catch (MQClientException e) { + log.error("生产者初始化失败:{}",e.getMessage()); + } + return producer; + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgListener.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgListener.java new file mode 100644 index 0000000..b7eb193 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgListener.java @@ -0,0 +1,94 @@ +package com.ruoyi.mtragent.consumer; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.mtragent.domain.DeviceMessage; +import com.ruoyi.mtragent.enums.MessageCodeEnum; +import com.ruoyi.mtragent.handler.MessageHandler; +import com.ruoyi.mtragent.producer.ConsumeException; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.common.message.MessageExt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.io.UnsupportedEncodingException; +import java.util.List; + +/** + * 消息监听 + */ +@Slf4j +@Component +public class RocketMsgListener implements MessageListenerConcurrently { + @Autowired + private MessageHandler messageHandler; + + /** + * 消费消息 + * @param list msgs.size() >= 1 + * DefaultMQPushConsumer.consumeMessageBatchMaxSize=1,you can modify here + * 这里只设置为1,当设置为多个时,list中只要有一条消息消费失败,就会整体重试 + * @param consumeConcurrentlyContext 上下文信息 + * @return 消费状态 成功(CONSUME_SUCCESS)或者 重试 (RECONSUME_LATER) + */ + @Override + public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) { + try{ + //消息不等于空情况 + if (!CollectionUtils.isEmpty(list)) { + //获取topic + for (MessageExt messageExt : list) { + // 解析消息内容 + String body = new String(messageExt.getBody()); + log.info("接受到的消息为:{}", body); + String tags = messageExt.getTags(); + String topic = messageExt.getTopic(); + String msgId = messageExt.getMsgId(); + String keys = messageExt.getKeys(); + int reConsume = messageExt.getReconsumeTimes(); + // 消息已经重试了3次,如果不需要再次消费,则返回成功 + if (reConsume == 3) { + // TODO 补偿信息 + log.error("消息消费三次失败,消息内容:{}", body); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//根据业务返回是否正常 + } + if(MessageCodeEnum.TR_AGENT_UP.getCode().equals(topic)){ + // 拿到信息 + DeviceMessage message = JSON.parseObject(body, DeviceMessage.class); + // 处理消息 + messageHandler.handleMessage(message); + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//业务处理成功 + } + // 根据不同的topic处理不同的业务 这里以订单消息为例子 + } + } + // 消息消费失败 + //broker会根据设置的messageDelayLevel发起重试,默认16次 + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } catch (Exception e) { + // 调用 handleException 方法处理异常并返回处理结果 + return handleException(e); + } + } + + /** + * 异常处理 + * + * @param e 捕获的异常 + * @return 消息消费结果 + */ + private static ConsumeConcurrentlyStatus handleException(final Exception e) { + Class exceptionClass = e.getClass(); + if (exceptionClass.equals(UnsupportedEncodingException.class)) { + log.error(e.getMessage()); + } else if (exceptionClass.equals(ConsumeException.class)) { + log.error(e.getMessage()); + } else{ + log.error(e.getMessage()); + } + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgTransactionListenerImpl.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgTransactionListenerImpl.java new file mode 100644 index 0000000..0a594d1 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/consumer/RocketMsgTransactionListenerImpl.java @@ -0,0 +1,30 @@ +package com.ruoyi.mtragent.consumer; + +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; + +/** + * 事物消息监听 + */ +public class RocketMsgTransactionListenerImpl implements TransactionListener { + + @Override + public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { + // 在这里执行本地事务,比如数据库操作等 + // 如果本地事务执行成功,返回 COMMIT_MESSAGE + // 如果本地事务执行失败,返回 ROLLBACK_MESSAGE + // 如果本地事务执行中,可以返回 UNKNOW,RocketMQ 将会检查事务状态,并根据状态处理消息 + return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态 + } + + @Override + public LocalTransactionState checkLocalTransaction(MessageExt msg) { + // 检查本地事务状态,如果本地事务执行成功,返回 COMMIT_MESSAGE + // 如果本地事务执行失败,返回 ROLLBACK_MESSAGE + // 如果本地事务仍在执行中,返回 UNKNOW,RocketMQ 将会继续检查事务状态 + return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态 + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/controller/RocketMqController.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/controller/RocketMqController.java new file mode 100644 index 0000000..4de796b --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/controller/RocketMqController.java @@ -0,0 +1,139 @@ +package com.ruoyi.mtragent.controller; + + +import com.ruoyi.common.security.annotation.InnerAuth; +import com.ruoyi.mtragent.producer.MessageProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 消息测试类Controller + */ +@RestController +@RequestMapping("/api/rocketMessage") +public class RocketMqController { + + + + /** + * 发送同步消息 + */ + @PostMapping("/sendSynchronizeMessage") + private Map sendSynchronizeMessage(){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 + SendResult sendResult = messageProducer.sendSynchronizeMessage("order-message","order_message_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + + /** + * 发送单向消息 + */ + @PostMapping("/sendOnewayMessage") + private Map sendOnewayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + messageProducer.sendOnewayMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("msg","发送成功"); + result.put("code",200); + return result; + } + + + /** + * 批量发送消息 + */ + @PostMapping("/sendBatchMessage") + private Map sendBatchMessage(){ + // 根据实际需求创建消息列表并返回 + List messages = new ArrayList<>(); + // 添加消息到列表 + messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes())); + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendBatchMessage(messages); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送事物消息 + */ + @PostMapping("/sendThingMessage") + private Map sendThingMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendThingMessage("order-message","order_timeout_tag","title","content"); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送有序的消息 + */ + @PostMapping("/sendOrderlyMessage") + private Map sendOrderlyMessage(){ + // 根据实际需求创建消息列表并返回 + List messages = new ArrayList<>(); + // 添加消息到列表 + messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes())); + messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes())); + Integer messageQueueNumber = 3; + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendOrderlyMessage(messages,messageQueueNumber); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + /** + * 发送延迟消息 + */ + @PostMapping("/sendDelayMessage") + private Map sendDelayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendDelayMessage("order-message","order_timeout_tag","title","content",4); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + + + /** + * 发送异步的消息 + */ + @InnerAuth + @PostMapping("/sendAsyncProducerMessage") + private Map sendAsyncProducerMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){ + MessageProducer messageProducer = new MessageProducer(); + //调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的 + SendResult sendResult = messageProducer.sendAsyncProducerMessage(topic,tag,key,value); + Map result = new HashMap<>(); + result.put("data",sendResult); + return result; + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/DeviceMessage.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/DeviceMessage.java new file mode 100644 index 0000000..2721a4b --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/DeviceMessage.java @@ -0,0 +1,10 @@ +package com.ruoyi.mtragent.domain; + +import lombok.Data; + +@Data +public class DeviceMessage { + private String clientId; + private String dataType; + private String data; +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/InitialHeartbeatListen.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/InitialHeartbeatListen.java new file mode 100644 index 0000000..d98fff6 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/InitialHeartbeatListen.java @@ -0,0 +1,37 @@ +package com.ruoyi.mtragent.domain; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; +import lombok.Data; + +/** + * 心跳信息对象 initial_heartbeat_listen + * + * @author gyt + * @date 2025-09-08 + */ +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class InitialHeartbeatListen extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 客户端ID */ + private String clientId; + /** 节点 */ + private String logicalNode; + /** sn */ + private String sn; + + /** 强度值 */ + @Excel(name = "强度值") + private Long strength; + /** 服务名称 */ + private String name; + /** 版本 */ + private String version; + /** 服务启动时间 */ + private Long startupTime; + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/RmAgentManagement.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/RmAgentManagement.java new file mode 100644 index 0000000..59d77a2 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/RmAgentManagement.java @@ -0,0 +1,86 @@ +package com.ruoyi.mtragent.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; +import lombok.Data; + +import java.util.Date; + +/** + * Agent管理对象 rm_agent_management + * + * @author gyt + * @date 2025-09-15 + */ +@Data +public class RmAgentManagement extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 主键ID */ + private Long id; + + /** 硬件SN码 */ + @Excel(name = "硬件SN码") + private String hardwareSn; + + /** 资源名称 */ + @Excel(name = "资源名称") + private String resourceName; + + /** 内网IP地址 */ + @Excel(name = "内网IP地址") + private String internalIp; + + /** Agent状态:0-离线,1-在线,2-异常 */ + @Excel(name = "Agent状态:0-离线,1-在线,2-异常") + private String status; + + /** Agent版本号 */ + @Excel(name = "Agent版本号") + private String agentVersion; + + /** 执行方式 */ + @Excel(name = "执行方式") + private Integer method; + + /** 定时更新时间(cron表达式) */ + @Excel(name = "定时更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date scheduledUpdateTime; + /** 文件地址格式 */ + @Excel(name = "文件地址格式") + private Long fileUrlType; + + /** 文件地址 */ + @Excel(name = "文件地址") + private String fileUrl; + /** 文件目录 */ + @Excel(name = "文件目录") + private String fileDirectory; + + /** 最后一次更新结果(success/failure) */ + @Excel(name = "最后一次更新结果", readConverterExp = "s=uccess/failure") + private String lastUpdateResult; + + /** 最后一次更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "最后一次更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date lastUpdateTime; + /** 生效服务器id */ + private String includeIds; + /** 生效服务器名称 */ + private String includeNames; + /** 查询条件名称 */ + private String queryName; + /** 文件MD5 */ + private String fileMd5; + /** 客户端id */ + private String clientId; + /** 部署设备 */ + private String deployDevice; + /** 管理网公网Ip */ + private String managePublicIp; + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/AgentUpdateMsgVo.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/AgentUpdateMsgVo.java new file mode 100644 index 0000000..8a99b61 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/AgentUpdateMsgVo.java @@ -0,0 +1,15 @@ +package com.ruoyi.mtragent.domain.vo; + +import lombok.Data; + +@Data +public class AgentUpdateMsgVo { + /**文件地址,外网HTTP(S)地址 */ + private String fileUrl; + /** 文件MD5 */ + private String fileMd5; + /** 执行方式:0、立即执行;1、定时执行; */ + private Integer method; + /** 定时时间,执行方式为1、定时执行时该字段必传 */ + private long policyTime; +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyTypeVo.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyTypeVo.java new file mode 100644 index 0000000..7820899 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyTypeVo.java @@ -0,0 +1,20 @@ +package com.ruoyi.mtragent.domain.vo; + +import lombok.Data; + +import java.time.Instant; + +@Data +public class PolicyTypeVo { + + /** 服务器监控策略信息 */ + private String monitors; + /** 服务器脚本策略信息 */ + private String scripts; + /** agent更新信息 */ + private String versions; + /** 路由信息 */ + private String routes; + /** 时间戳 */ + private Long timestamp = Instant.now().getEpochSecond(); +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyVo.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyVo.java new file mode 100644 index 0000000..1901461 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/PolicyVo.java @@ -0,0 +1,14 @@ +package com.ruoyi.mtragent.domain.vo; + +import lombok.Data; + +import java.time.Instant; +import java.util.List; + +@Data +public class PolicyVo { + /** 更新时间戳 */ + private Long upTime = Instant.now().getEpochSecond(); + /** 更新内容 */ + private List contents; +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/RspVo.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/RspVo.java new file mode 100644 index 0000000..a6f2227 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/domain/vo/RspVo.java @@ -0,0 +1,29 @@ +package com.ruoyi.mtragent.domain.vo; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.time.Instant; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class RspVo { + /** + * 状态码,0、失败;1、成功 + */ + private Integer resCode; + /** + * 描述 + */ + private String resMag; + /** + * 描述 + */ + private String resMsg; + + private String result; + /** + * 时间戳 + */ + private Long timestamp = Instant.now().getEpochSecond(); +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/AlarmTypeEnum.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/AlarmTypeEnum.java new file mode 100644 index 0000000..f138a33 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/AlarmTypeEnum.java @@ -0,0 +1,15 @@ +package com.ruoyi.mtragent.enums; + +import lombok.Getter; + +@Getter +public enum AlarmTypeEnum { + 服务器下线("1", "服务器下线"), + 交换机下线("2", "交换机下线"); + private final String code; + private final String msg; + AlarmTypeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageCodeEnum.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageCodeEnum.java new file mode 100644 index 0000000..d8c3a72 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageCodeEnum.java @@ -0,0 +1,65 @@ +package com.ruoyi.mtragent.enums; + + +import lombok.Getter; + +/** + * 用于传递topic和 tag + * 也用于接收消息后判断不同的消息处理不同的业务 + */ +@Getter +public enum MessageCodeEnum { + + /** + * agent数据采集的信息 + */ + AGENT_MESSAGE_TOPIC("agent_up","agent数据采集的信息topic"), + + TONGRAN_AGENT_UP("tongran_agent_up","agent数据采集的信息topic"), + + TR_AGENT_UP("tr_agent_up","agent数据采集的信息topic v1.1"), + + /** + * 系统消息 + */ + NOTE_MESSAGE_TOPIC("system-message","系统消息服务模块topic名称"), + /** + * 用户消息 + */ + USER_MESSAGE_TOPIC("user-message","用户消息服务模块topic名称"), + + /** + * 订单消息 + */ + ORDER_MESSAGE_TOPIC("order-message","订单消息服务模块topic名称"), + + /** + * 用户消息tag + */ + USER_MESSAGE_TAG("user_message_tag","用户消息推送"), + + /** + * 系统消息tag + */ + NOTE_MESSAGE_TAG("system_message_tag","系统消息推送"), + + /** + * 订单消息 + */ + ORDER_MESSAGE_TAG("order_message_tag","订单消息推送"), + + /** + * 订单处理编号 + */ + ORDER_TIMEOUT_TAG("order_timeout_tag","订单超时处理"); + + + private final String code; + private final String msg; + + MessageCodeEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageTopic.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageTopic.java new file mode 100644 index 0000000..74c7b2b --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/MessageTopic.java @@ -0,0 +1,21 @@ +package com.ruoyi.mtragent.enums; + + +import java.util.ArrayList; +import java.util.List; + +/** + * 定义topic列表 + */ +public class MessageTopic { + + //在这里添加topic 用于批量订阅 + public List RocketMQTopicList(){ + List getTopicLists=new ArrayList<>(); + // agent采集消息 +// getTopicLists.add("agent_up"); + getTopicLists.add("tr_mtragent_up"); + return getTopicLists; + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/PushMethodEnum.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/PushMethodEnum.java new file mode 100644 index 0000000..e01f246 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/PushMethodEnum.java @@ -0,0 +1,14 @@ +package com.ruoyi.mtragent.enums; + +import lombok.Getter; + +@Getter +public enum PushMethodEnum { + 企业微信("1", "企业微信"); + private final String code; + private final String msg; + PushMethodEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/ServerLogoEnum.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/ServerLogoEnum.java new file mode 100644 index 0000000..8e18b74 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/ServerLogoEnum.java @@ -0,0 +1,21 @@ +package com.ruoyi.mtragent.enums; + +import lombok.Getter; + +@Getter +public enum ServerLogoEnum { + 交换卷文件的可用空间("systemSwapSizeFreeCollect", "交换卷/文件的可用空间(字节)"), + 内存利用率("memoryUtilizationCollect", "内存利用率"), + 可用交换空间百分比("systemSwapSizePercentCollect", "可用交换空间百分比"), + 可用内存("memorySizeAvailableCollect", "可用内存"), + 可用内存百分比("memorySizePercentCollect", "可用内存百分比"), + 正在运行的进程数("procNumRunCollect", "正在运行的进程数"), + 登录用户数("systemUsersNumCollect", "登录用户数"), + 进程数("procNumCollect", "进程数"); + private final String code; + private final String msg; + ServerLogoEnum(String code, String msg){ + this.code = code; + this.msg = msg; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/SwitchLogo.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/SwitchLogo.java new file mode 100644 index 0000000..b4d3dfb --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/enums/SwitchLogo.java @@ -0,0 +1,17 @@ +package com.ruoyi.mtragent.enums; + +import lombok.Getter; + +@Getter +public enum SwitchLogo { + 设备CPU使用率("hwEntityCpuUsage", "设备CPU使用率"), + 设备内存使用率("hwEntityMemUsage", "设备内存使用率(%)"), + 系统平均功率("hwAveragePower", "系统平均功率(%)"), + 系统实时功率("hwCurrentPower", "系统实时功率(%)"); + private final String code; + private final String msg; + SwitchLogo(String code, String msg){ + this.code = code; + this.msg = msg; + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/handler/MessageHandler.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/handler/MessageHandler.java new file mode 100644 index 0000000..2ba6d16 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/handler/MessageHandler.java @@ -0,0 +1,92 @@ +package com.ruoyi.mtragent.handler; + +import com.ruoyi.common.core.enums.MsgEnum; +import com.ruoyi.mtragent.domain.DeviceMessage; +import com.ruoyi.mtragent.domain.vo.RspVo; +import com.ruoyi.mtragent.service.IRmAgentManagementService; +import com.ruoyi.mtragent.utils.JsonDataParser; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +/** + * 设备消息处理器 + */ +@Slf4j +@Component +@EnableScheduling +public class MessageHandler { + + private final Map> messageHandlers = new HashMap<>(); + // 心跳状态 + private static final String HEARTBEAT_STATUS_PREFIX = "heartbeat:status:"; + // 心跳时间 + private static final String HEARTBEAT_TIME_PREFIX = "heartbeat:time:"; + // 心跳告警 + private static final String HEARTBEAT_ALERT_PREFIX = "heartbeat:alert:"; + String HEARTBEAT_RECOVERY_COUNT_PREFIX = "heartbeat:recovery:count:"; + + String HEARTBEAT_COUNT_PREFIX = "heartbeat:count:"; + private static final long HEARTBEAT_TIMEOUT = 30000; // 3分钟超时 + + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private IRmAgentManagementService rmAgentManagementService; + + + /** + * 初始化处理器映射 + */ + @PostConstruct + public void init() { + registerHandler(MsgEnum.Agent版本更新应答.getValue(), this::handleAgentUpdateRspMessage); + + // 其他类型消息可以单独注册处理器 + registerHandler(MsgEnum.注册.getValue(), this::handleRegisterMessage); + } + private void handleRegisterMessage(DeviceMessage message) { + + } + /** + * agent更新响应 + * @param message + */ + private void handleAgentUpdateRspMessage(DeviceMessage message) { + List rspVoList = JsonDataParser.parseJsonData(message.getData(), RspVo.class); + } + + /** + * 注册消息处理器 + */ + private void registerHandler(String dataType, Consumer handler) { + messageHandlers.put(dataType, handler); + } + + /** + * 处理设备消息(对外暴露的主方法) + */ + public void handleMessage(DeviceMessage message) { + String dataType = message.getDataType(); + Consumer handler = messageHandlers.get(dataType); + + if (handler != null) { + handler.accept(message); + } else { + log.warn("未知数据类型:{}", dataType); + } + } + + // ========== 具体的消息处理方法 ========== + + +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/mapper/RmAgentManagementMapper.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/mapper/RmAgentManagementMapper.java new file mode 100644 index 0000000..6238a68 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/mapper/RmAgentManagementMapper.java @@ -0,0 +1,65 @@ +package com.ruoyi.mtragent.mapper; + + +import com.ruoyi.mtragent.domain.RmAgentManagement; + +import java.util.List; + +/** + * Agent管理Mapper接口 + * + * @author gyt + * @date 2025-09-15 + */ +public interface RmAgentManagementMapper +{ + /** + * 查询Agent管理 + * + * @param id Agent管理主键 + * @return Agent管理 + */ + public RmAgentManagement selectRmAgentManagementById(Long id); + + /** + * 查询Agent管理列表 + * + * @param rmAgentManagement Agent管理 + * @return Agent管理集合 + */ + public List selectRmAgentManagementList(RmAgentManagement rmAgentManagement); + + /** + * 新增Agent管理 + * + * @param rmAgentManagement Agent管理 + * @return 结果 + */ + public int insertRmAgentManagement(RmAgentManagement rmAgentManagement); + + /** + * 修改Agent管理 + * + * @param rmAgentManagement Agent管理 + * @return 结果 + */ + public int updateRmAgentManagement(RmAgentManagement rmAgentManagement); + + /** + * 删除Agent管理 + * + * @param id Agent管理主键 + * @return 结果 + */ + public int deleteRmAgentManagementById(Long id); + + /** + * 批量删除Agent管理 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteRmAgentManagementByIds(Long[] ids); + + void updateRmAgentManagementBySn(RmAgentManagement rmAgentManagement); +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ConsumerMode.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ConsumerMode.java new file mode 100644 index 0000000..fbb4fc7 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ConsumerMode.java @@ -0,0 +1,30 @@ +package com.ruoyi.mtragent.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +/** + * 消费者初始化 + * 消费者连接信息 具体看nacos配置 + */ +@Data +@Configuration +@Component +public class ConsumerMode { + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.conumer.groupName}") + private String groupName ; + @Value("${suning.rocketmq.conumer.consumeThreadMin}") + private int consumeThreadMin; + @Value("${suning.rocketmq.conumer.consumeThreadMax}") + private int consumeThreadMax; + @Value("${suning.rocketmq.conumer.consumeMessageBatchMaxSize}") + private int consumeMessageBatchMaxSize; + @Value("${suning.rocketmq.conumer.agentTopic}") + private String agentTopic; + @Value("${suning.rocketmq.conumer.agentGroup}") + private String agentGroup; +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ProducerMode.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ProducerMode.java new file mode 100644 index 0000000..452ce0b --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/model/ProducerMode.java @@ -0,0 +1,29 @@ +package com.ruoyi.mtragent.model; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 生产者初始化 + */ +@RefreshScope +@Data +@Configuration +public class ProducerMode { + @Value("${suning.rocketmq.producer.groupName}") + private String groupName; + @Value("${suning.rocketmq.producer.agentTopic}") + private String agentTopic; + @Value("${suning.rocketmq.producer.agentGroup}") + private String agentGroup; + @Value("${suning.rocketmq.namesrvAddr}") + private String namesrvAddr; + @Value("${suning.rocketmq.producer.maxMessageSize}") + private Integer maxMessageSize; + @Value("${suning.rocketmq.producer.sendMsgTimeout}") + private Integer sendMsgTimeout; + @Value("${suning.rocketmq.producer.retryTimesWhenSendFailed}") + private Integer retryTimesWhenSendFailed; +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/ConsumeException.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/ConsumeException.java new file mode 100644 index 0000000..4ff7081 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/ConsumeException.java @@ -0,0 +1,23 @@ +package com.ruoyi.mtragent.producer; + +/** + * @author 影子 + * 用于捕捉异常非受检异常(unchecked exception) + * RuntimeException 和其子类的异常在编译时不需要进行强制性的异常处理,可以选择在运行时进行捕获和处理 + * 可选择使用 + */ +public class ConsumeException extends RuntimeException{ + private static final long serialVersionUID = 4093867789628938836L; + + public ConsumeException(String message) { + super(message); + } + + public ConsumeException(Throwable cause) { + super(cause); + } + + public ConsumeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/MessageProducer.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/MessageProducer.java new file mode 100644 index 0000000..9fbe92d --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/producer/MessageProducer.java @@ -0,0 +1,225 @@ +package com.ruoyi.mtragent.producer; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.mtragent.consumer.RocketMsgTransactionListenerImpl; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.exception.MQBrokerException; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.producer.TransactionSendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.remoting.common.RemotingHelper; +import org.apache.rocketmq.remoting.exception.RemotingException; + +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import static com.ruoyi.mtragent.config.ProducerConfig.producer; + + +/** + * 消息发送 + */ +@Slf4j +public class MessageProducer { + + + /** + * 同步发送消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 通过调用 send() 方法发送消息,阻塞等待服务器响应。 + */ + public SendResult sendSynchronizeMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + SendResult result = producer.send(msg); + return result; + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException | InterruptedException | RemotingException | MQBrokerException e) { + log.error("消息发送失败! body:{}",body); + } + return null; + } + + /** + * 单向发送消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 单向发送:通过调用 sendOneway() 方法发送消息,不关心发送结果,适用于对可靠性要求不高的场景。 + */ + public void sendOnewayMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + producer.sendOneway(msg); + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException | InterruptedException | RemotingException e) { + log.error("消息发送失败! body:{}",body); + } + } + + + /** + * 批量发送消息 + * @param messages 消息列表 + * 批量发送:通过调用 send() 方法并传入多条消息,实现批量发送消息。 + */ + public SendResult sendBatchMessage(List messages){ + String body = messages.toString(); + try { + System.out.println("生产者发送消息:"+ messages); + // 发送批量消息 + SendResult sendResult = producer.send(messages); + return sendResult; + } catch (MQClientException | InterruptedException | RemotingException e) { + log.error("消息发送失败! body:{}",body); + } catch (MQBrokerException e) { + throw new RuntimeException(e); + } + return null; + } + + + /** + * 事务消息发送 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 事务消息发送:通过使用事务监听器实现本地事务执行和消息发送的一致性。 + */ + public SendResult sendThingMessage(String topic, String tag, String key, String value){ + String body = "topic:【"+topic+"】, tag:【"+tag+"】, key:【"+key+"】, value:【"+value+"】"; + try { + // 实例化事务生产者 + TransactionMQProducer transactionMQProducer = new TransactionMQProducer(producer.getProducerGroup()); + transactionMQProducer.setNamesrvAddr(producer.getNamesrvAddr()); + // 设置事务监听器 + transactionMQProducer.setTransactionListener(new RocketMsgTransactionListenerImpl()); + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + // 发送事务消息 + TransactionSendResult sendResult = transactionMQProducer.sendMessageInTransaction(msg, null); + return sendResult; + } catch (UnsupportedEncodingException e) { + log.error("消息初始化失败!body:{}",body); + + } catch (MQClientException e) { + log.error("消息发送失败! body:{}",body); + } + return null; + } + + + /** + * 发送有序的消息 + * @param messagesList Message集合 + * @param messageQueueNumber 消息队列数量,根据实际情况设定 + * 顺序发送: messageQueueNumber 表示消息的业务标识,可以根据具体需求进行设置来保证消息按顺序发送。 + */ + public SendResult sendOrderlyMessage(List messagesList, Integer messageQueueNumber) { + SendResult result = null; + for (Message message : messagesList) { + try { + result = producer.send(message, (list, msg, arg) -> { + Integer queueNumber = (Integer) arg; + //int queueIndex = queueNumber % list.size(); + return list.get(queueNumber); + }, messageQueueNumber);//根据编号取模,选择消息队列 + } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) { + log.error("发送有序消息失败"); + return result; + } + } + return result; + } + + /** + * 发送延迟消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 延迟发送:通过设置延迟级别来实现延迟发送消息。 + */ + public SendResult sendDelayMessage(String topic, String tag, String key, String value, Integer level) + { + SendResult result = null; + try + { + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + //设置消息延迟级别,我这里设置5,对应就是延时一分钟 + // "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h" + msg.setDelayTimeLevel(level); + // 发送消息到一个Broker + result = producer.send(msg); + // 通过sendResult返回消息是否成功送达 + log.info("发送延迟消息结果:======sendResult:{}", result); + DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + log.info("发送时间:{}", format.format(new Date())); + return result; + } + catch (Exception e) + { + e.printStackTrace(); + log.error("延迟消息队列推送消息异常:{},推送内容:{}", e.getMessage(), result); + } + return result; + } + /** + * 发送异步的消息 + * @param topic 主题 + * @param tag 标签 + * @param key 自定义的key,根据业务来定 + * @param value 消息的内容 + * 通过调用 send() 方法,并传入一个 SendCallback 对象,在发送消息的同时可以继续处理其他逻辑,消息发送结果通过回调函数通知。 + */ + public SendResult sendAsyncProducerMessage(String topic, String tag, String key, String value){ + + try { + //创建一个消息实例,指定主题、标签和消息体。 + Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET)); + System.out.println("生产者发送消息:"+ JSON.toJSONString(value)); + producer.send(msg,new SendCallback() { + // 异步回调的处理 + @Override + public void onSuccess(SendResult sendResult) { + System.out.printf("%-10d 异步发送消息成功 %s %n", msg, sendResult.getMsgId()); + } + @Override + public void onException(Throwable e) { + System.out.printf("%-10d 异步发送消息失败 %s %n", msg, e); + e.printStackTrace(); + } + }); + } catch (MQClientException e) { + e.printStackTrace(); + } catch (RemotingException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + return null; + } + +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/IRmAgentManagementService.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/IRmAgentManagementService.java new file mode 100644 index 0000000..57010ae --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/IRmAgentManagementService.java @@ -0,0 +1,56 @@ +package com.ruoyi.mtragent.service; + + +import com.ruoyi.mtragent.domain.RmAgentManagement; + +import java.util.List; + +/** + * Agent管理Service接口 + * + * @author gyt + * @date 2025-09-15 + */ +public interface IRmAgentManagementService +{ + /** + * 查询Agent管理 + * + * @param id Agent管理主键 + * @return Agent管理 + */ + public RmAgentManagement selectRmAgentManagementById(Long id); + + /** + * 查询Agent管理列表 + * + * @param rmAgentManagement Agent管理 + * @return Agent管理集合 + */ + public List selectRmAgentManagementList(RmAgentManagement rmAgentManagement); + + + /** + * 保存最后更新结果 + * + * @param rmAgentManagement Agent管理 + * @return 结果 + */ + public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement); + + + + /** + * 手动立即更新agent + * @param rmAgentManagement + * @return + */ + int updateAgentNow(RmAgentManagement rmAgentManagement); + + /** + * 配置更新策略 + * @param rmAgentManagement + * @return + */ + int addUpdatePolicy(RmAgentManagement rmAgentManagement); +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/impl/RmAgentManagementServiceImpl.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/impl/RmAgentManagementServiceImpl.java new file mode 100644 index 0000000..6b916c5 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/service/impl/RmAgentManagementServiceImpl.java @@ -0,0 +1,202 @@ +package com.ruoyi.mtragent.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.ruoyi.common.core.constant.SecurityConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.enums.MsgEnum; +import com.ruoyi.common.core.utils.DateUtils; +import com.ruoyi.mtragent.domain.DeviceMessage; +import com.ruoyi.mtragent.domain.RmAgentManagement; +import com.ruoyi.mtragent.domain.vo.AgentUpdateMsgVo; +import com.ruoyi.mtragent.domain.vo.PolicyTypeVo; +import com.ruoyi.mtragent.domain.vo.PolicyVo; +import com.ruoyi.mtragent.mapper.RmAgentManagementMapper; +import com.ruoyi.mtragent.model.ProducerMode; +import com.ruoyi.mtragent.producer.MessageProducer; +import com.ruoyi.mtragent.service.IRmAgentManagementService; +import com.ruoyi.system.api.RemoteRevenueConfigService; +import com.ruoyi.system.api.domain.RmResourceRegistrationRemote; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Agent管理Service业务层处理 + * + * @author gyt + * @date 2025-09-15 + */ +@Service +@Slf4j +public class RmAgentManagementServiceImpl implements IRmAgentManagementService +{ + @Autowired + private RmAgentManagementMapper rmAgentManagementMapper; + @Autowired + private RemoteRevenueConfigService remoteRevenueConfigService; + @Autowired + private ProducerMode producerMode; + + /** + * 查询Agent管理 + * + * @param id Agent管理主键 + * @return Agent管理 + */ + @Override + public RmAgentManagement selectRmAgentManagementById(Long id) + { + RmAgentManagement agentManagement = rmAgentManagementMapper.selectRmAgentManagementById(id); + if(agentManagement != null){ + if(agentManagement.getClientId() != null){ + // 赋其他值 + setPropties(agentManagement); + } + } + return agentManagement; + } + + /** + * 查询Agent管理列表 + * + * @param rmAgentManagement Agent管理 + * @return Agent管理 + */ + @Override + public List selectRmAgentManagementList(RmAgentManagement rmAgentManagement) + { + List managementList = rmAgentManagementMapper.selectRmAgentManagementList(rmAgentManagement); + for (RmAgentManagement agentManagement : managementList) { + if(agentManagement.getClientId()!=null){ + // 查询注册表信息赋值 + setPropties(agentManagement); + } + } + return managementList; + } + + /** + * 根据注册表赋值 + * @param agentManagement + */ + public void setPropties(RmAgentManagement agentManagement){ + String clientId = agentManagement.getClientId(); + // 设置其他信息 + RmResourceRegistrationRemote queryRegist = new RmResourceRegistrationRemote(); + queryRegist.setClientId(clientId); + R registMsgR = remoteRevenueConfigService.getListByHardwareSn(queryRegist, SecurityConstants.INNER); + if(registMsgR != null && registMsgR.getData() != null){ + RmResourceRegistrationRemote registMsg = registMsgR.getData(); + agentManagement.setStatus(registMsg.getOnlineStatus()); + agentManagement.setHardwareSn(registMsg.getHardwareSn()); + } + } + + /** + * 保存最后更新结果 + * + * @param rmAgentManagement Agent管理 + * @return 结果 + */ + public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement){ + rmAgentManagementMapper.updateRmAgentManagementBySn(rmAgentManagement); + } + + /** + * 配置更新策略v1.1 + * @param rmAgentManagement + * @return + */ + @Override + public int addUpdatePolicy(RmAgentManagement rmAgentManagement) { + processAgentData(rmAgentManagement); + return 1; + } + + /** + * 手动立即更新 + * @param rmAgentManagement 更新信息 + * @return + */ + @Override + public int updateAgentNow(RmAgentManagement rmAgentManagement) { + processAgentData(rmAgentManagement); + return 1; + } + + /** + * 处理agen更新数据 + * @param rmAgentManagement + */ + public void processAgentData(RmAgentManagement rmAgentManagement){ + String clientIds = rmAgentManagement.getDeployDevice(); + String[] clientIdArr = clientIds.split("\n"); + for (String clientId : clientIdArr) { + // 创建新的对象,避免污染原始数据 + RmAgentManagement currentAgent = new RmAgentManagement(); + // 复制原始对象的属性 + BeanUtils.copyProperties(rmAgentManagement, currentAgent); + // 设置当前循环的 clientId + currentAgent.setClientId(clientId); + currentAgent.setDeployDevice(clientId); + // 查询该资源是否已经配置 + RmAgentManagement agentQueryParam = new RmAgentManagement(); + agentQueryParam.setClientId(clientId); + List agentManagements = rmAgentManagementMapper.selectRmAgentManagementList(agentQueryParam); + if(!agentManagements.isEmpty()){ + // 如果存在,修改 + currentAgent.setLastUpdateTime(DateUtils.getNowDate()); + if("0".equals(rmAgentManagement.getMethod())){ + currentAgent.setScheduledUpdateTime(null); + } + rmAgentManagementMapper.updateRmAgentManagement(currentAgent); + }else{ + // 如果不存在,添加 + currentAgent.setLastUpdateTime(DateUtils.getNowDate()); + if("0".equals(rmAgentManagement.getMethod())){ + currentAgent.setScheduledUpdateTime(null); + } + rmAgentManagementMapper.insertRmAgentManagement(currentAgent); + } + // 构建更新策略 + AgentUpdateMsgVo agentUpdateMsgVo = new AgentUpdateMsgVo(); + agentUpdateMsgVo.setFileUrl(rmAgentManagement.getFileUrl()); + agentUpdateMsgVo.setFileMd5(rmAgentManagement.getFileMd5()); + agentUpdateMsgVo.setMethod(rmAgentManagement.getMethod()); + if(rmAgentManagement.getMethod() == 1){ + Date scheduledUpdateTime = rmAgentManagement.getScheduledUpdateTime(); + long scheduledTime = scheduledUpdateTime.toInstant().getEpochSecond(); + agentUpdateMsgVo.setPolicyTime(scheduledTime); + } + try { + PolicyVo policyVo = new PolicyVo(); + List list = new ArrayList<>(); + list.add(agentUpdateMsgVo); + policyVo.setContents(list); + String policyVoStr = JSONObject.toJSONString(policyVo); + PolicyTypeVo policyTypeVo = new PolicyTypeVo(); + policyTypeVo.setVersions(policyVoStr); + String configJson = JSONObject.toJSONString(policyTypeVo); + DeviceMessage deviceMessage = new DeviceMessage(); + deviceMessage.setClientId(clientId); + deviceMessage.setDataType(MsgEnum.获取最新策略应答.getValue()); + deviceMessage.setData(configJson); + MessageProducer messageProducer = new MessageProducer(); + + messageProducer.sendAsyncProducerMessage( + producerMode.getAgentTopic(), + "", + "", + JSONObject.toJSONString(deviceMessage) + ); + } catch (Exception e) { + log.error("发送设备配置失败,deviceId: {}", rmAgentManagement.getHardwareSn(), e); + } + } + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/JsonDataParser.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/JsonDataParser.java new file mode 100644 index 0000000..dc22373 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/JsonDataParser.java @@ -0,0 +1,41 @@ +package com.ruoyi.mtragent.utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class JsonDataParser { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 通用JSON解析方法(兼容对象和数组) + * @param jsonStr JSON字符串 + * @param valueType 目标实体类类型 + * @return 实体类List集合 + */ + public static List parseJsonData(String jsonStr, Class valueType) { + if (!StringUtils.hasText(jsonStr)) { + return new ArrayList<>(); + } + + try { + JsonNode rootNode = objectMapper.readTree(jsonStr); + + if (rootNode.isArray()) { + // 处理数组格式JSON + return objectMapper.readValue(jsonStr, + objectMapper.getTypeFactory().constructCollectionType(List.class, valueType)); + } else { + // 处理单个对象格式JSON + List result = new ArrayList<>(1); + result.add(objectMapper.readValue(jsonStr, valueType)); + return result; + } + } catch (Exception e) { + throw new RuntimeException("JSON解析失败: " + e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/SwitchJsonDataParser.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/SwitchJsonDataParser.java new file mode 100644 index 0000000..144d5ce --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/SwitchJsonDataParser.java @@ -0,0 +1,149 @@ +package com.ruoyi.mtragent.utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class SwitchJsonDataParser { + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * 通用JSON解析方法(兼容对象和数组) + * @param jsonStr JSON字符串 + * @param valueType 目标实体类类型 + * @return 实体类List集合 + */ + public static List parseJsonData(String jsonStr, Class valueType) { + if (!StringUtils.hasText(jsonStr)) { + return new ArrayList<>(); + } + + try { + JsonNode rootNode = objectMapper.readTree(jsonStr); + + if (rootNode.isArray()) { + // 处理数组格式JSON + if (isStringArrayContainingJsonObjects((ArrayNode) rootNode)) { + // 处理包含JSON对象字符串的数组 - 转换为真正的对象数组 + ArrayNode processedArray = processStringJsonArrayToObjectArray((ArrayNode) rootNode); + return convertJsonArrayToList(processedArray, valueType); + } else { + // 处理普通JSON数组 + processJsonArray((ArrayNode) rootNode); + return convertJsonArrayToList((ArrayNode) rootNode, valueType); + } + } else { + // 处理单个对象格式JSON + if (rootNode.isObject()) { + processJsonObject((ObjectNode) rootNode); + } + List result = new ArrayList<>(1); + result.add(objectMapper.treeToValue(rootNode, valueType)); + return result; + } + } catch (Exception e) { + throw new RuntimeException("JSON解析失败: " + e.getMessage(), e); + } + } + + /** + * 将JsonArray转换为List + */ + private static List convertJsonArrayToList(ArrayNode arrayNode, Class valueType) throws Exception { + List result = new ArrayList<>(); + for (int i = 0; i < arrayNode.size(); i++) { + JsonNode element = arrayNode.get(i); + result.add(objectMapper.treeToValue(element, valueType)); + } + return result; + } + + /** + * 判断是否是包含JSON对象字符串的字符串数组 + */ + private static boolean isStringArrayContainingJsonObjects(ArrayNode arrayNode) { + if (arrayNode.size() == 0) return false; + + JsonNode firstElement = arrayNode.get(0); + if (firstElement.isTextual()) { + try { + String strValue = firstElement.textValue(); + // 检查是否是JSON对象格式的字符串 + if (strValue.startsWith("{") && strValue.endsWith("}")) { + objectMapper.readTree(strValue); + return true; + } + } catch (Exception e) { + return false; + } + } + return false; + } + + /** + * 处理包含JSON对象字符串的字符串数组,转换为真正的对象数组 + */ + private static ArrayNode processStringJsonArrayToObjectArray(ArrayNode arrayNode) { + ArrayNode resultArray = objectMapper.createArrayNode(); + + for (int i = 0; i < arrayNode.size(); i++) { + JsonNode element = arrayNode.get(i); + if (element.isTextual()) { + try { + String jsonString = element.textValue(); + JsonNode jsonNode = objectMapper.readTree(jsonString); + + if (jsonNode.isObject()) { + // 处理JSON对象中的 noSuchInstance + processJsonObject((ObjectNode) jsonNode); + resultArray.add(jsonNode); + } else { + resultArray.add(element); + } + } catch (Exception e) { + // 如果解析失败,保持原样 + resultArray.add(element); + } + } else { + resultArray.add(element); + } + } + + return resultArray; + } + + /** + * 处理JSON数组 + */ + private static void processJsonArray(ArrayNode arrayNode) { + for (int i = 0; i < arrayNode.size(); i++) { + JsonNode element = arrayNode.get(i); + if (element.isObject()) { + processJsonObject((ObjectNode) element); + } else if (element.isArray()) { + processJsonArray((ArrayNode) element); + } + } + } + + /** + * 处理JSON对象 + */ + private static void processJsonObject(ObjectNode objectNode) { + objectNode.fields().forEachRemaining(entry -> { + JsonNode value = entry.getValue(); + if (value.isTextual() && "noSuchInstance".equals(value.textValue())) { + objectNode.putNull(entry.getKey()); + } else if (value.isObject()) { + processJsonObject((ObjectNode) value); + } else if (value.isArray()) { + processJsonArray((ArrayNode) value); + } + }); + } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/TableRouterUtil.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/TableRouterUtil.java new file mode 100644 index 0000000..4ed00c6 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/TableRouterUtil.java @@ -0,0 +1,99 @@ +package com.ruoyi.mtragent.utils; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.LinkedHashSet; +import java.util.Set; + +public class TableRouterUtil { + + // 日期格式 + private static final DateTimeFormatter YEAR_MONTH_FORMAT = + DateTimeFormatter.ofPattern("yyyy_MM"); + private static final DateTimeFormatter DATE_TIME_FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + // 表名前缀 + private static final String TABLE_PREFIX = "eps_initial_traffic"; + // 表名前缀 + private static final String TABLE_PREFIX_INITIAL = "initial_bandwidth_traffic"; + + + /** + * 根据创建时间获取表名 + * @param createTime 记录创建时间 + * @return 对应的分表名称 + * @throws IllegalArgumentException 如果createTime为null + * + * 示例: + * 2023-08-05 14:30:00 → eps_initial_traffic_2023_08_1_10 + * 2023-08-15 09:15:00 → eps_initial_traffic_2023_08_11_20 + * 2023-08-25 18:45:00 → eps_initial_traffic_2023_08_21_31 + */ + public static String getTableName(LocalDateTime createTime) { + if (createTime == null) { + throw new IllegalArgumentException("创建时间不能为null"); + } + + String yearMonth = createTime.format(YEAR_MONTH_FORMAT); + int day = createTime.getDayOfMonth(); + + return String.format("%s_%s_%s", + TABLE_PREFIX_INITIAL, + yearMonth, + getDayRange(day)); + } + + /** + * 获取时间范围内涉及的所有表名 + * @param startTime 开始时间 (格式: "yyyy-MM-dd HH:mm:ss") + * @param endTime 结束时间 (格式: "yyyy-MM-dd HH:mm:ss") + * @return 按时间顺序排列的表名集合 + */ + public static Set getTableNamesBetween(String startTime, String endTime) { + LocalDateTime start = parseDateTime(startTime); + LocalDateTime end = parseDateTime(endTime); + validateTimeRange(start, end); + + Set tableNames = new LinkedHashSet<>(); + LocalDateTime current = start.withHour(0).withMinute(0).withSecond(0); + + while (!current.isAfter(end)) { + tableNames.add(getTableName(current)); + current = current.plusDays(1); + } + + return tableNames; + } + // 解析字符串为LocalDateTime + private static LocalDateTime parseDateTime(String dateTimeStr) { + if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) { + throw new IllegalArgumentException("时间字符串不能为空"); + } + try { + return LocalDateTime.parse(dateTimeStr, DATE_TIME_FORMATTER); + } catch (Exception e) { + throw new IllegalArgumentException("时间格式必须为: yyyy-MM-dd HH:mm:ss", e); + } + } + + // 获取日期区间 + private static String getDayRange(int day) { + if (day < 1 || day > 31) { + throw new IllegalArgumentException("日期必须在1-31之间"); + } + + if (day <= 10) return "1_10"; + if (day <= 20) return "11_20"; + return "21_31"; + } + + // 验证时间范围 + private static void validateTimeRange(LocalDateTime start, LocalDateTime end) { + if (start == null || end == null) { + throw new IllegalArgumentException("时间范围参数不能为null"); + } + if (start.isAfter(end)) { + throw new IllegalArgumentException("开始时间不能晚于结束时间"); + } + } +} diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/WeChatWorkBot.java b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/WeChatWorkBot.java new file mode 100644 index 0000000..0bfca31 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/java/com/ruoyi/mtragent/utils/WeChatWorkBot.java @@ -0,0 +1,285 @@ +package com.ruoyi.mtragent.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class WeChatWorkBot { + private static final ObjectMapper mapper = new ObjectMapper(); + + /** + * 发送基于模板的文本消息 + * @param webhookUrl webhook地址 + * @param template 消息模板,例如:"项目[项目名称]在[时间]发生[事件类型]" + * @param fieldValues 字段值的映射,key为中文字段名,value为实际值(支持String、Number、Boolean等) + * @return 是否发送成功 + */ + public static boolean sendTemplateMessage(String webhookUrl, String template, + Map fieldValues) { + return sendTemplateMessage(webhookUrl, template, fieldValues, null, null, false); + } + + /** + * 发送基于模板的文本消息(支持@功能) + * @param webhookUrl webhook地址 + * @param template 消息模板 + * @param fieldValues 字段值的映射 + * @param mentionedMobiles 被@的用户列表(手机号) + * @param mentionedAll 是否@所有人 + * @return 是否发送成功 + */ + public static boolean sendTemplateMessage(String webhookUrl, String template, + Map fieldValues, + String[] mentionedMobiles, boolean mentionedAll) { + return sendTemplateMessage(webhookUrl, template, fieldValues, null, mentionedMobiles, mentionedAll); + } + + /** + * 发送基于模板的文本消息(完整参数) + * @param webhookUrl webhook地址 + * @param template 消息模板 + * @param fieldValues 字段值的映射 + * @param defaultValue 未找到字段时的默认值 + * @param mentionedMobiles 被@的用户列表(手机号) + * @param mentionedAll 是否@所有人 + * @return 是否发送成功 + */ + public static boolean sendTemplateMessage(String webhookUrl, String template, + Map fieldValues, Object defaultValue, + String[] mentionedMobiles, boolean mentionedAll) { + try { + String actualContent = processTemplate(template, fieldValues, defaultValue); + return sendTextMessage(webhookUrl, actualContent, mentionedMobiles, mentionedAll); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 处理模板,替换字段占位符 + * @param template 消息模板 + * @param fieldValues 字段值映射 + * @param defaultValue 默认值 + * @return 处理后的消息内容 + */ + public static String processTemplate(String template, Map fieldValues, + Object defaultValue) { + if (template == null) return ""; + if (fieldValues == null || fieldValues.isEmpty()) { + return template; + } + + Pattern pattern = Pattern.compile("\\[(.*?)\\]"); + Matcher matcher = pattern.matcher(template); + StringBuffer result = new StringBuffer(); + + while (matcher.find()) { + String fieldName = matcher.group(1); + Object fieldValueObj = fieldValues.get(fieldName); + String fieldValue = convertToString(fieldValueObj); + + // 如果字段值为空,使用默认值或保留原占位符 + if (fieldValue == null || fieldValue.trim().isEmpty()) { + fieldValue = convertToString(defaultValue); + if (fieldValue == null) { + fieldValue = "[" + fieldName + "]"; + } + } + + // 对替换值进行转义,防止正则表达式特殊字符问题 + matcher.appendReplacement(result, Matcher.quoteReplacement(fieldValue)); + } + matcher.appendTail(result); + + return result.toString(); + } + + /** + * 将对象转换为字符串 + * @param obj 要转换的对象 + * @return 字符串表示 + */ + private static String convertToString(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof Number || obj instanceof Boolean) { + return String.valueOf(obj); + } else if (obj instanceof java.util.Date) { + return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.util.Date) obj); + } else { + return obj.toString(); + } + } + + /** + * 验证模板中的字段是否都有对应的值 + * @param template 消息模板 + * @param fieldValues 字段值映射 + * @return 是否所有字段都有值 + */ + public static boolean validateTemplate(String template, Map fieldValues) { + if (template == null || fieldValues == null) { + return false; + } + + Pattern pattern = Pattern.compile("\\[(.*?)\\]"); + Matcher matcher = pattern.matcher(template); + + while (matcher.find()) { + String fieldName = matcher.group(1); + Object fieldValue = fieldValues.get(fieldName); + String strValue = convertToString(fieldValue); + + if (!fieldValues.containsKey(fieldName) || + strValue == null || + strValue.trim().isEmpty()) { + return false; + } + } + return true; + } + + /** + * 获取模板中的所有字段名 + * @param template 消息模板 + * @return 字段名列表 + */ + public static java.util.List getTemplateFields(String template) { + java.util.List fields = new java.util.ArrayList<>(); + if (template == null) { + return fields; + } + + Pattern pattern = Pattern.compile("\\[(.*?)\\]"); + Matcher matcher = pattern.matcher(template); + + while (matcher.find()) { + fields.add(matcher.group(1)); + } + return fields; + } + + /** + * 发送Markdown模板消息 + * @param webhookUrl webhook地址 + * @param template Markdown模板 + * @param fieldValues 字段值映射 + * @return 是否发送成功 + */ + public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template, + Map fieldValues) { + return sendMarkdownTemplateMessage(webhookUrl, template, fieldValues, null); + } + + /** + * 发送Markdown模板消息 + * @param webhookUrl webhook地址 + * @param template Markdown模板 + * @param fieldValues 字段值映射 + * @param defaultValue 默认值 + * @return 是否发送成功 + */ + public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template, + Map fieldValues, + Object defaultValue) { + try { + String actualContent = processTemplate(template, fieldValues, defaultValue); + return sendMarkdownMessage(webhookUrl, actualContent); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 发送文本消息 + */ + public static boolean sendTextMessage(String webhookUrl, String content) { + return sendTextMessage(webhookUrl, content, null, false); + } + + /** + * 发送文本消息(支持@功能) + */ + public static boolean sendTextMessage(String webhookUrl, String content, + String[] mentionedMobiles, boolean mentionedAll) { + try { + Map message = new HashMap<>(); + message.put("msgtype", "text"); + + Map textContent = new HashMap<>(); + textContent.put("content", content); + + if (mentionedAll) { + textContent.put("mentioned_mobile_list", new String[]{"@all"}); + } else if (mentionedMobiles != null && mentionedMobiles.length > 0) { + textContent.put("mentioned_mobile_list", mentionedMobiles); + } + + message.put("text", textContent); + + return sendMessage(webhookUrl, mapper.writeValueAsString(message)); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 发送Markdown消息 + */ + public static boolean sendMarkdownMessage(String webhookUrl, String content) { + try { + Map message = new HashMap<>(); + message.put("msgtype", "markdown"); + + Map markdownContent = new HashMap<>(); + markdownContent.put("content", content); + + message.put("markdown", markdownContent); + + return sendMessage(webhookUrl, mapper.writeValueAsString(message)); + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + private static boolean sendMessage(String webhookUrl, String jsonBody) { + try { + URL url = new URL(webhookUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setDoOutput(true); + connection.setConnectTimeout(5000); + connection.setReadTimeout(10000); + + try (OutputStream os = connection.getOutputStream()) { + byte[] input = jsonBody.getBytes("UTF-8"); + os.write(input, 0, input.length); + } + + int responseCode = connection.getResponseCode(); + return responseCode == 200; + + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-mtragent/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..d45aafd --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/resources/bootstrap.yml @@ -0,0 +1,41 @@ +# Tomcat +server: + port: 9208 + +# Spring +spring: + application: + # 应用名称 + name: ruoyi-mtragent + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8848 +# server-addr: 172.16.15.103:8848 +# username: ${spring.cloud.nacos.config.username} +# password: ${spring.cloud.nacos.config.password} + config: + # 配置中心地址 + server-addr: 127.0.0.1:8848 +# server-addr: 172.16.15.103:8848 +# username: nacos +# password: nacos + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + + redisson: + singleServerConfig: + address: redis://localhost:6379 +logging: + level: + com.ruoyi.app.mapper: DEBUG + + + diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/resources/logback.xml b/ruoyi-modules/ruoyi-mtragent/src/main/resources/logback.xml new file mode 100644 index 0000000..b2f084f --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/resources/logback.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/info.log + + + + ${log.path}/info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + + ${log.path}/error.log + + + + ${log.path}/error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/main/resources/mapper/mtragent/RmAgentManagementMapper.xml b/ruoyi-modules/ruoyi-mtragent/src/main/resources/mapper/mtragent/RmAgentManagementMapper.xml new file mode 100644 index 0000000..7edd267 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/main/resources/mapper/mtragent/RmAgentManagementMapper.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select id, hardware_sn, resource_name, internal_ip, status, agent_version, method, scheduled_update_time, file_url_type, file_url, file_directory, last_update_result, last_update_time, create_time, update_time, create_by, update_by, file_md5, client_id, deploy_device from rm_agent_management + + + + + + + + insert into rm_agent_management + + hardware_sn, + resource_name, + internal_ip, + status, + agent_version, + method, + scheduled_update_time, + file_url_type, + file_url, + file_directory, + last_update_result, + last_update_time, + create_time, + update_time, + create_by, + update_by, + file_md5, + client_id, + deploy_device, + + + #{hardwareSn}, + #{resourceName}, + #{internalIp}, + #{status}, + #{agentVersion}, + #{method}, + #{scheduledUpdateTime}, + #{fileUrlType}, + #{fileUrl}, + #{fileDirectory}, + #{lastUpdateResult}, + #{lastUpdateTime}, + #{createTime}, + #{updateTime}, + #{createBy}, + #{updateBy}, + #{fileMd5}, + #{clientId}, + #{deployDevice}, + + + + + update rm_agent_management + + hardware_sn = #{hardwareSn}, + resource_name = #{resourceName}, + internal_ip = #{internalIp}, + status = #{status}, + agent_version = #{agentVersion}, + method = #{method}, + scheduled_update_time = #{scheduledUpdateTime}, + file_url_type = #{fileUrlType}, + file_url = #{fileUrl}, + file_directory = #{fileDirectory}, + last_update_result = #{lastUpdateResult}, + last_update_time = #{lastUpdateTime}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + file_md5 = #{fileMd5}, + client_id = #{clientId}, + deploy_device = #{deployDevice}, + + + + + and id = #{id} + + + and client_id = #{clientId} + + + and 1=0 + + + + + + + delete from rm_agent_management where id = #{id} + + + + delete from rm_agent_management where id in + + #{id} + + + + update rm_agent_management + + resource_name = #{resourceName}, + internal_ip = #{internalIp}, + status = #{status}, + agent_version = #{agentVersion}, + method = #{method}, + scheduled_update_time = #{scheduledUpdateTime}, + file_url_type = #{fileUrlType}, + file_url = #{fileUrl}, + file_directory = #{fileDirectory}, + last_update_result = #{lastUpdateResult}, + last_update_time = #{lastUpdateTime}, + create_time = #{createTime}, + update_time = #{updateTime}, + create_by = #{createBy}, + update_by = #{updateBy}, + + + + + and id = #{id} + + + and client_id = #{clientId} + + + and hardware_sn = #{hardwareSn} + + + and 1=0 + + + + + \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-mtragent/src/test/java/com/ruoyi/mtragent/AppTest.java b/ruoyi-modules/ruoyi-mtragent/src/test/java/com/ruoyi/mtragent/AppTest.java new file mode 100644 index 0000000..3190886 --- /dev/null +++ b/ruoyi-modules/ruoyi-mtragent/src/test/java/com/ruoyi/mtragent/AppTest.java @@ -0,0 +1,38 @@ +package com.ruoyi.mtragent; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/TableScheduleConfig.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/TableScheduleConfig.java index 452cb56..fdd6386 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/TableScheduleConfig.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/config/TableScheduleConfig.java @@ -1,7 +1,6 @@ package com.ruoyi.system.config; import com.ruoyi.system.domain.*; -import com.ruoyi.system.mapper.RmResourceRegistrationMapper; import com.ruoyi.system.service.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -9,7 +8,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; -import java.math.BigDecimal; import java.time.LocalDate; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -36,17 +34,11 @@ public class TableScheduleConfig { @Autowired private IAllInterfaceNameService allInterfaceNameService; @Autowired - private IEpsServerRevenueConfigService epsServerRevenueConfigService; - @Autowired private IRmEpsTopologyManagementService rmEpsTopologyManagementService; @Autowired private IEpsMethodChangeRecordService epsMethodChangeRecordService; @Autowired private IRmMonitorConfigService rmMonitorConfigService; - @Autowired - private IRmMonitorConfigDetailsService rmMonitorConfigDetailsService; - @Autowired - private RmResourceRegistrationMapper rmResourceRegistrationMapper; // 每月25号创建下月表 @Scheduled(cron = "0 0 0 25 * ?") @@ -54,70 +46,13 @@ public class TableScheduleConfig { public void createNextMonthTables() { epsInitialTrafficDataService.createNextMonthTables(); } + + /** + * 每5分钟计算配置好的总流量 + */ @Scheduled(cron = "0 1/5 * * * ?") - public void sumTrafficMyMonitorConfig() { - // 查询所有配置 - List rmMonitorConfigList = rmMonitorConfigService.selectRmMonitorConfigList(new RmMonitorConfig()); - if (rmMonitorConfigList == null || rmMonitorConfigList.isEmpty()) { - return; - } - for (RmMonitorConfig rmMonitorConfig : rmMonitorConfigList) { - // 判断资源类型 - if("1".equals(rmMonitorConfig.getResourceType()) || "3".equals(rmMonitorConfig.getResourceType())){ - if("3".equals(rmMonitorConfig.getResourceType())){ - if(rmMonitorConfig.getBusinessName() == null){ - log.warn("不存在业务"); - continue; - } - // 根据业务代码查询服务器clientId - RmResourceRegistration queryRegist = new RmResourceRegistration(); - queryRegist.setBusinessName(rmMonitorConfig.getBusinessName()); - List registrationList = rmResourceRegistrationMapper.getRegistrationTableInfoList(queryRegist); - StringBuilder clientIds = new StringBuilder(); - if (registrationList != null && !registrationList.isEmpty()) { - for (RmResourceRegistration registration : registrationList) { - if (registration.getClientId() != null) { - if (clientIds.length() > 0) { - clientIds.append("\n"); - } - clientIds.append(registration.getClientId()); - } - } - } - rmMonitorConfig.setDeployDevice(clientIds.toString()); - } - List serverTrafficList = epsInitialTrafficDataService.getServerTrafficByMonitorView(rmMonitorConfig); - // 计算结果落入临时表 - for (EpsInitialTrafficData epsInitialTrafficData : serverTrafficList) { - RmMonitorConfigDetails configDetails = new RmMonitorConfigDetails(); - configDetails.setMonitorId(rmMonitorConfig.getId()); - configDetails.setCreateTime(epsInitialTrafficData.getCreateTime()); - // 查询该数据是否存在 - List exitsList = rmMonitorConfigDetailsService.selectRmMonitorConfigDetailsList(configDetails); - if(exitsList == null || exitsList.isEmpty()){ - configDetails.setInSpeed(new BigDecimal(epsInitialTrafficData.getInSpeed() == null ? "0" : epsInitialTrafficData.getInSpeed())); - configDetails.setOutSpeed(new BigDecimal(epsInitialTrafficData.getOutSpeed() == null ? "0" : epsInitialTrafficData.getOutSpeed())); - configDetails.setDeployDevice(rmMonitorConfig.getDeployDevice()); - rmMonitorConfigDetailsService.insertRmMonitorConfigDetails(configDetails); - } - } - }else{ - List switchInfoDetailsList = initialSwitchInfoDetailsService.getMonitorViewDetails(rmMonitorConfig); - for (InitialSwitchInfoDetails initialSwitchInfoDetails : switchInfoDetailsList) { - RmMonitorConfigDetails configDetails = new RmMonitorConfigDetails(); - configDetails.setMonitorId(rmMonitorConfig.getId()); - configDetails.setCreateTime(initialSwitchInfoDetails.getCreateTime()); - // 查询该数据是否存在 - List exitsList = rmMonitorConfigDetailsService.selectRmMonitorConfigDetailsList(configDetails); - if(exitsList == null || exitsList.isEmpty()){ - configDetails.setInSpeed(initialSwitchInfoDetails.getInSpeed()); - configDetails.setOutSpeed(initialSwitchInfoDetails.getOutSpeed()); - configDetails.setDeployDevice(rmMonitorConfig.getDeployDevice()); - rmMonitorConfigDetailsService.insertRmMonitorConfigDetails(configDetails); - } - } - } - } + public void sumTrafficMyMonitorConfigScheduled() { + rmMonitorConfigService.sumTrafficMyMonitorConfig(null); } // 每天0点执行 计算95带宽值/日 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/RmMonitorConfigDetailsController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/RmMonitorConfigDetailsController.java index f8efe96..01e9a7c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/RmMonitorConfigDetailsController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/RmMonitorConfigDetailsController.java @@ -1,18 +1,16 @@ package com.ruoyi.system.controller; -import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; -import com.ruoyi.common.core.web.page.TableDataInfo; -import com.ruoyi.common.log.annotation.Log; -import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.system.domain.RmMonitorConfigDetails; import com.ruoyi.system.service.IRmMonitorConfigDetailsService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; @@ -29,73 +27,6 @@ public class RmMonitorConfigDetailsController extends BaseController @Autowired private IRmMonitorConfigDetailsService rmMonitorConfigDetailsService; - /** - * 查询监控看板详情列表 - */ - @RequiresPermissions("system:monitorConfigDetails:list") - @GetMapping("/list") - public TableDataInfo list(RmMonitorConfigDetails rmMonitorConfigDetails) - { - startPage(); - List list = rmMonitorConfigDetailsService.selectRmMonitorConfigDetailsList(rmMonitorConfigDetails); - return getDataTable(list); - } - - /** - * 导出监控看板详情列表 - */ - @RequiresPermissions("system:monitorConfigDetails:export") - @Log(title = "监控看板详情", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, RmMonitorConfigDetails rmMonitorConfigDetails) - { - List list = rmMonitorConfigDetailsService.selectRmMonitorConfigDetailsList(rmMonitorConfigDetails); - ExcelUtil util = new ExcelUtil(RmMonitorConfigDetails.class); - util.exportExcel(response, list, "监控看板详情数据"); - } - - /** - * 获取监控看板详情详细信息 - */ - @RequiresPermissions("system:monitorConfigDetails:query") - @GetMapping(value = "/{id}") - public AjaxResult getInfo(@PathVariable("id") Long id) - { - return success(rmMonitorConfigDetailsService.selectRmMonitorConfigDetailsById(id)); - } - - /** - * 新增监控看板详情 - */ - @RequiresPermissions("system:monitorConfigDetails:add") - @Log(title = "监控看板详情", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody RmMonitorConfigDetails rmMonitorConfigDetails) - { - return toAjax(rmMonitorConfigDetailsService.insertRmMonitorConfigDetails(rmMonitorConfigDetails)); - } - - /** - * 修改监控看板详情 - */ - @RequiresPermissions("system:monitorConfigDetails:edit") - @Log(title = "监控看板详情", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody RmMonitorConfigDetails rmMonitorConfigDetails) - { - return toAjax(rmMonitorConfigDetailsService.updateRmMonitorConfigDetails(rmMonitorConfigDetails)); - } - - /** - * 删除监控看板详情 - */ - @RequiresPermissions("system:monitorConfigDetails:remove") - @Log(title = "监控看板详情", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public AjaxResult remove(@PathVariable Long[] ids) - { - return toAjax(rmMonitorConfigDetailsService.deleteRmMonitorConfigDetailsByIds(ids)); - } /** * 监控看板-详情视图 出入流量 */ @@ -103,7 +34,7 @@ public class RmMonitorConfigDetailsController extends BaseController @PostMapping("/getTrafficByMonitorView") public AjaxResult getTrafficByMonitorView(@RequestBody RmMonitorConfigDetails queryParam) { - Map echartsData = rmMonitorConfigDetailsService.getTrafficByMonitorView(queryParam); + List> echartsData = rmMonitorConfigDetailsService.getTrafficByMonitorView(queryParam); return success(echartsData); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/InitialSwitchInfoDetails.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/InitialSwitchInfoDetails.java index 81a1825..0156e85 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/InitialSwitchInfoDetails.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/InitialSwitchInfoDetails.java @@ -25,8 +25,8 @@ public class InitialSwitchInfoDetails extends BaseEntity @Excel(name = "客户端ID") private String clientId; - /** 网络接口名称(如eth0、ens33等) */ - @Excel(name = "网络接口名称(如eth0、ens33等)") + /** 接口名称 */ + @Excel(name = "接口名称") private String name; /** 接收流量(字节) */ @@ -41,16 +41,16 @@ public class InitialSwitchInfoDetails extends BaseEntity @Excel(name = "接口状态(up/down等)") private String status; - /** 接口类型(ethernet/wireless等) */ - @Excel(name = "接口类型(ethernet/wireless等)") + /** 接口类型*/ + @Excel(name = "接口类型") private String type; - /** 接收流量(bytes/s) */ - @Excel(name = "接收流量", readConverterExp = "b=ytes/s") + /** 接收流量(bits/s) */ + @Excel(name = "接收流量") private BigDecimal inSpeed; - /** 发送流量(bytes/s) */ - @Excel(name = "发送流量", readConverterExp = "b=ytes/s") + /** 发送流量(bits/s) */ + @Excel(name = "发送流量") private BigDecimal outSpeed; /** 发送或接收流量的最大值 */ private BigDecimal maxSpeed; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/RmMonitorConfigDetails.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/RmMonitorConfigDetails.java index ae3fa49..e4f7ede 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/RmMonitorConfigDetails.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/RmMonitorConfigDetails.java @@ -37,11 +37,11 @@ public class RmMonitorConfigDetails extends BaseEntity private BigDecimal outBytes; /** 接收流量(bit/s) */ - @Excel(name = "接收流量", readConverterExp = "b=it/s") + @Excel(name = "接收流量bit/s") private BigDecimal inSpeed; /** 发送流量(bit/s) */ - @Excel(name = "发送流量", readConverterExp = "b=it/s") + @Excel(name = "发送流量bit/s") private BigDecimal outSpeed; /** 开始时间 */ private String startTime; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RmMonitorConfigDetailsMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RmMonitorConfigDetailsMapper.java index 303c1e8..2797a01 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RmMonitorConfigDetailsMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RmMonitorConfigDetailsMapper.java @@ -1,7 +1,9 @@ package com.ruoyi.system.mapper; -import java.util.List; import com.ruoyi.system.domain.RmMonitorConfigDetails; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; /** * 监控看板详情Mapper接口 @@ -51,6 +53,8 @@ public interface RmMonitorConfigDetailsMapper */ public int deleteRmMonitorConfigDetailsById(Long id); + public int deleteRmMonitorConfigDetailsByMonitorIds(Long[] monitorId); + /** * 批量删除监控看板详情 * @@ -58,4 +62,7 @@ public interface RmMonitorConfigDetailsMapper * @return 结果 */ public int deleteRmMonitorConfigDetailsByIds(Long[] ids); + + @Transactional(rollbackFor = Exception.class) + int batchInsertRmMonitorConfigDetails(List batchInsertList); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IInitialSwitchInfoDetailsService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IInitialSwitchInfoDetailsService.java index af4cf6f..9ae7246 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IInitialSwitchInfoDetailsService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IInitialSwitchInfoDetailsService.java @@ -113,7 +113,7 @@ public interface IInitialSwitchInfoDetailsService /** * 监控看板-详情视图 出入流量 - * @param initialSwitchInfoDetails + * @param rmMonitorConfig * @return */ List getMonitorViewDetails(RmMonitorConfig rmMonitorConfig); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigDetailsService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigDetailsService.java index dcc9cb4..b64c929 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigDetailsService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigDetailsService.java @@ -66,5 +66,7 @@ public interface IRmMonitorConfigDetailsService * @param queryParam * @return */ - Map getTrafficByMonitorView(RmMonitorConfigDetails queryParam); + List> getTrafficByMonitorView(RmMonitorConfigDetails queryParam); + + int batchInsertRmMonitorConfigDetails(List batchInsertList); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigService.java index 8a346f2..d0eed35 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/IRmMonitorConfigService.java @@ -1,8 +1,9 @@ package com.ruoyi.system.service; -import java.util.List; import com.ruoyi.system.domain.RmMonitorConfig; +import java.util.List; + /** * 监控配置Service接口 * @@ -58,4 +59,8 @@ public interface IRmMonitorConfigService * @return 结果 */ public int deleteRmMonitorConfigById(Long id); + + public void sumTrafficMyMonitorConfig(Long id); + + void asyncAfterInsert(Long id); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsInitialTrafficDataServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsInitialTrafficDataServiceImpl.java index 4725e4c..dd85b43 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsInitialTrafficDataServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsInitialTrafficDataServiceImpl.java @@ -7,7 +7,6 @@ import com.ruoyi.system.domain.*; import com.ruoyi.system.enums.ReviewEnum; import com.ruoyi.system.mapper.*; import com.ruoyi.system.service.EpsInitialTrafficDataService; -import com.ruoyi.system.service.IRmMonitorConfigService; import com.ruoyi.system.util.CalculateUtil; import com.ruoyi.system.util.DateUtil; import com.ruoyi.system.util.TableRouterUtil; @@ -53,8 +52,6 @@ public class EpsInitialTrafficDataServiceImpl implements EpsInitialTrafficDataSe @Autowired private RmRegistrationMachineMapper rmRegistrationMachineMapper; @Autowired - private IRmMonitorConfigService rmMonitorConfigService; - @Autowired private RmResourceRegistrationMapper rmResourceRegistrationMapper; @Override public void createNextMonthTables() { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsNodeBandwidthServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsNodeBandwidthServiceImpl.java index b62a8d1..851f599 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsNodeBandwidthServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/EpsNodeBandwidthServiceImpl.java @@ -5,7 +5,6 @@ import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.web.page.PageDomain; import com.ruoyi.system.domain.EpsInitialTrafficData; import com.ruoyi.system.domain.EpsNodeBandwidth; -import com.ruoyi.system.domain.RmMonitorConfig; import com.ruoyi.system.domain.RmSwitchManagement; import com.ruoyi.system.mapper.EpsNodeBandwidthMapper; import com.ruoyi.system.mapper.RmSwitchManagementMapper; @@ -334,32 +333,27 @@ public class EpsNodeBandwidthServiceImpl implements IEpsNodeBandwidthService */ @Override public List getListByMonitorView(EpsNodeBandwidth epsNodeBandwidth) { - // 查询概览配置内容 - RmMonitorConfig rmMonitorConfig = rmMonitorConfigService.selectRmMonitorConfigById(epsNodeBandwidth.getMonitorId()); - if(rmMonitorConfig != null){ - // 拿到部署设备 - String deoloyDevice = rmMonitorConfig.getDeployDevice(); - if(deoloyDevice == null){ - return new ArrayList<>(); - } - String clientIds = deoloyDevice.replace("\n",","); - epsNodeBandwidth.setClientIds(clientIds); - if(epsNodeBandwidth.getCalculationMode() == null){ - // 计算方式 默认1000 - epsNodeBandwidth.setCalculationMode("1000"); - } - if(epsNodeBandwidth.getResourceType() == null){ - // 资源类型 默认服务器 - epsNodeBandwidth.setResourceType("1"); - } - if(epsNodeBandwidth.getBandwidthType() == null){ - // 默认日95值 - epsNodeBandwidth.setBandwidthType("1"); - } - List list = epsNodeBandwidthMapper.getListByMonitorView(epsNodeBandwidth); - return list; + // 拿到部署设备 + String deoloyDevice = epsNodeBandwidth.getClientIds(); + if(deoloyDevice == null){ + return new ArrayList<>(); } - return new ArrayList<>(); + String clientIds = deoloyDevice.replace("\n",","); + epsNodeBandwidth.setClientIds(clientIds); + if(epsNodeBandwidth.getCalculationMode() == null){ + // 计算方式 默认1000 + epsNodeBandwidth.setCalculationMode("1000"); + } + if(epsNodeBandwidth.getResourceType() == null){ + // 资源类型 默认服务器 + epsNodeBandwidth.setResourceType("1"); + } + if(epsNodeBandwidth.getBandwidthType() == null){ + // 默认日95值 + epsNodeBandwidth.setBandwidthType("1"); + } + List list = epsNodeBandwidthMapper.getListByMonitorView(epsNodeBandwidth); + return list; } // 动态生成复合键 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/InitialSwitchInfoDetailsServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/InitialSwitchInfoDetailsServiceImpl.java index dcbe579..9499f42 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/InitialSwitchInfoDetailsServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/InitialSwitchInfoDetailsServiceImpl.java @@ -10,7 +10,6 @@ import com.ruoyi.system.domain.*; import com.ruoyi.system.enums.ReviewEnum; import com.ruoyi.system.mapper.*; import com.ruoyi.system.service.IInitialSwitchInfoDetailsService; -import com.ruoyi.system.service.IRmMonitorConfigService; import com.ruoyi.system.util.CalculateUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; @@ -61,7 +60,7 @@ public class InitialSwitchInfoDetailsServiceImpl implements IInitialSwitchInfoDe @Autowired private EpsBusinessDeployMapper epsBusinessDeployMapper; @Autowired - private IRmMonitorConfigService rmMonitorConfigService; + private RmMonitorConfigMapper rmMonitorConfigMapper; private static final String DATE_TIME_FORMATTER = "yyyy-MM-dd HH:mm:ss"; @@ -965,32 +964,27 @@ public class InitialSwitchInfoDetailsServiceImpl implements IInitialSwitchInfoDe */ @Override public List geSwitchListByMonitorView(InitialSwitchInfoDetails initialSwitchInfoDetails) { - // 查询概览配置内容 - RmMonitorConfig rmMonitorConfig = rmMonitorConfigService.selectRmMonitorConfigById(initialSwitchInfoDetails.getMonitorId()); - if(rmMonitorConfig != null){ - // 拿到选中的交换机 - String resources = rmMonitorConfig.getDeployDevice(); - String clientIds = Arrays.stream(resources.split(",")) - .map(msg -> msg.split(";")) - .filter(resource -> resource.length >= 3) - .map(resource -> resource[1]) - .collect(Collectors.joining(",")); - String interfaceNames = Arrays.stream(resources.split(",")) - .map(msg -> msg.split(";")) - .filter(resource -> resource.length >= 3) - .map(resource -> resource[2]) - .collect(Collectors.joining(",")); - // 查询流量信息 - initialSwitchInfoDetails.setClientIds(clientIds); - initialSwitchInfoDetails.setInterfaceNames(interfaceNames); - PageDomain pageDomain = new PageDomain(); - pageDomain.setPageNum(initialSwitchInfoDetails.getPageNum()); - pageDomain.setPageSize(initialSwitchInfoDetails.getPageSize()); - startPage(pageDomain); - List list = initialSwitchInfoDetailsMapper.geSwitchListByMonitorView(initialSwitchInfoDetails); - return list; - } - return new ArrayList<>(); + // 拿到选中的交换机 + String resources = initialSwitchInfoDetails.getClientIds(); + String clientIds = Arrays.stream(resources.split(",")) + .map(msg -> msg.split(";")) + .filter(resource -> resource.length >= 3) + .map(resource -> resource[1]) + .collect(Collectors.joining(",")); + String interfaceNames = Arrays.stream(resources.split(",")) + .map(msg -> msg.split(";")) + .filter(resource -> resource.length >= 3) + .map(resource -> resource[2]) + .collect(Collectors.joining(",")); + // 查询流量信息 + initialSwitchInfoDetails.setClientIds(clientIds); + initialSwitchInfoDetails.setInterfaceNames(interfaceNames); + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(initialSwitchInfoDetails.getPageNum()); + pageDomain.setPageSize(initialSwitchInfoDetails.getPageSize()); + startPage(pageDomain); + List list = initialSwitchInfoDetailsMapper.geSwitchListByMonitorView(initialSwitchInfoDetails); + return list; } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigDetailsServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigDetailsServiceImpl.java index 54f32fe..dc3de48 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigDetailsServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigDetailsServiceImpl.java @@ -8,15 +8,13 @@ import com.ruoyi.system.domain.RmMonitorConfigDetails; import com.ruoyi.system.mapper.RmMonitorConfigDetailsMapper; import com.ruoyi.system.mapper.RmMonitorConfigMapper; import com.ruoyi.system.service.IRmMonitorConfigDetailsService; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Function; /** @@ -113,14 +111,41 @@ public class RmMonitorConfigDetailsServiceImpl implements IRmMonitorConfigDetail * @return */ @Override - public Map getTrafficByMonitorView(RmMonitorConfigDetails queryParam) { + public List> getTrafficByMonitorView(RmMonitorConfigDetails queryParam) { + List> resultMapList = new ArrayList<>(); + if(queryParam.getMonitorId() != null){ + // 根据id查询配置信息 + RmMonitorConfig rmMonitorConfig = rmMonitorConfigMapper.selectRmMonitorConfigById(queryParam.getMonitorId()); + Map map = processViewData(queryParam); + map.put("rmMonitorConfig", rmMonitorConfig); + resultMapList.add(map); + }else{ + // 查询所有配置 + List rmMonitorConfigs = rmMonitorConfigMapper.selectRmMonitorConfigList(new RmMonitorConfig()); + if (rmMonitorConfigs != null && !rmMonitorConfigs.isEmpty()) { + for (RmMonitorConfig rmMonitorConfig : rmMonitorConfigs) { + RmMonitorConfigDetails rmMonitorConfigDetails = new RmMonitorConfigDetails(); + BeanUtils.copyProperties(queryParam, rmMonitorConfigDetails); + rmMonitorConfigDetails.setMonitorId(rmMonitorConfig.getId()); + Map map = processViewData(rmMonitorConfigDetails); + map.put("rmMonitorConfig", rmMonitorConfig); + resultMapList.add(map); + } + } + } + return resultMapList; + } + public Map processViewData(RmMonitorConfigDetails queryParam){ // 查询概览配置内容 RmMonitorConfig rmMonitorConfig = rmMonitorConfigMapper.selectRmMonitorConfigById(queryParam.getMonitorId()); if(rmMonitorConfig != null){ // 拿到开始时间 String startTime = rmMonitorConfig.getMonitorStartTime(); queryParam.setStartTime(startTime); + if(queryParam.getEndTime() == null){ + queryParam.setEndTime(DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:ss")); + } List list = rmMonitorConfigDetailsMapper.selectRmMonitorConfigDetailsList(queryParam); if(list == null){ list = new ArrayList<>(); @@ -141,6 +166,10 @@ public class RmMonitorConfigDetailsServiceImpl implements IRmMonitorConfigDetail info != null && info.getInSpeed() != null ? info.getInSpeed().divide(divisor, 2, RoundingMode.HALF_UP) : 0); + extractors.put("deployDevice", info -> + info != null && info.getDeployDevice() != null ? + info.getDeployDevice() : + null); Map resultMap = EchartsDataUtils.buildEchartsDataAutoPadding( list, RmMonitorConfigDetails::getCreateTime, extractors, queryParam.getStartTime(), queryParam.getEndTime() ); @@ -150,6 +179,11 @@ public class RmMonitorConfigDetailsServiceImpl implements IRmMonitorConfigDetail e.printStackTrace(); } } - return null; + return new HashMap<>(); + } + + @Override + public int batchInsertRmMonitorConfigDetails(List batchInsertList) { + return rmMonitorConfigDetailsMapper.batchInsertRmMonitorConfigDetails(batchInsertList); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigServiceImpl.java index 65af926..06a0d4b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmMonitorConfigServiceImpl.java @@ -1,12 +1,22 @@ package com.ruoyi.system.service.impl; -import java.util.List; import com.ruoyi.common.core.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.*; +import com.ruoyi.system.mapper.RmMonitorConfigDetailsMapper; import com.ruoyi.system.mapper.RmMonitorConfigMapper; -import com.ruoyi.system.domain.RmMonitorConfig; +import com.ruoyi.system.mapper.RmResourceRegistrationMapper; +import com.ruoyi.system.service.EpsInitialTrafficDataService; +import com.ruoyi.system.service.IInitialSwitchInfoDetailsService; import com.ruoyi.system.service.IRmMonitorConfigService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; /** * 监控配置Service业务层处理 @@ -15,10 +25,22 @@ import com.ruoyi.system.service.IRmMonitorConfigService; * @date 2025-11-12 */ @Service +@Slf4j public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService { @Autowired private RmMonitorConfigMapper rmMonitorConfigMapper; + @Autowired + private RmMonitorConfigDetailsMapper rmMonitorConfigDetailsMapper; + @Autowired + private EpsInitialTrafficDataService epsInitialTrafficDataService; + @Autowired + private IInitialSwitchInfoDetailsService initialSwitchInfoDetailsService; + @Autowired + private RmResourceRegistrationMapper rmResourceRegistrationMapper; + @Autowired + @Lazy + private IRmMonitorConfigService self; /** * 查询监控配置 @@ -29,7 +51,8 @@ public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService @Override public RmMonitorConfig selectRmMonitorConfigById(Long id) { - return rmMonitorConfigMapper.selectRmMonitorConfigById(id); + RmMonitorConfig rmMonitorConfig = rmMonitorConfigMapper.selectRmMonitorConfigById(id); + return rmMonitorConfig; } /** @@ -41,7 +64,8 @@ public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService @Override public List selectRmMonitorConfigList(RmMonitorConfig rmMonitorConfig) { - return rmMonitorConfigMapper.selectRmMonitorConfigList(rmMonitorConfig); + List list = rmMonitorConfigMapper.selectRmMonitorConfigList(rmMonitorConfig); + return list; } /** @@ -54,7 +78,21 @@ public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService public int insertRmMonitorConfig(RmMonitorConfig rmMonitorConfig) { rmMonitorConfig.setCreateTime(DateUtils.getNowDate()); - return rmMonitorConfigMapper.insertRmMonitorConfig(rmMonitorConfig); + rmMonitorConfigMapper.insertRmMonitorConfig(rmMonitorConfig); + // 异步触发流量汇总 + self.asyncAfterInsert(rmMonitorConfig.getId()); + return 1; + } + @Async + @Override + public void asyncAfterInsert(Long monitorConfigId) { + try { + log.info("开始异步处理监控配置 {} 的流量汇总", monitorConfigId); + sumTrafficMyMonitorConfig(monitorConfigId); + log.info("监控配置 {} 流量汇总完成", monitorConfigId); + } catch (Exception e) { + log.error("监控配置 {} 流量汇总异常", monitorConfigId, e); + } } /** @@ -79,7 +117,10 @@ public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService @Override public int deleteRmMonitorConfigByIds(Long[] ids) { - return rmMonitorConfigMapper.deleteRmMonitorConfigByIds(ids); + int configRows = rmMonitorConfigMapper.deleteRmMonitorConfigByIds(ids); + // 删除详情 + rmMonitorConfigDetailsMapper.deleteRmMonitorConfigDetailsByMonitorIds(ids); + return configRows; } /** @@ -93,4 +134,106 @@ public class RmMonitorConfigServiceImpl implements IRmMonitorConfigService { return rmMonitorConfigMapper.deleteRmMonitorConfigById(id); } + + /** + * 配置好的数据求和 + */ + @Override + public void sumTrafficMyMonitorConfig(Long id) { + List rmMonitorConfigList = new ArrayList<>(); + if(id != null){ + RmMonitorConfig rmMonitorConfig = rmMonitorConfigMapper.selectRmMonitorConfigById(id); + rmMonitorConfigList.add(rmMonitorConfig); + }else{ + // 查询所有配置 + rmMonitorConfigList = rmMonitorConfigMapper.selectRmMonitorConfigList(new RmMonitorConfig()); + } + if (rmMonitorConfigList == null || rmMonitorConfigList.isEmpty()) { + return; + } + for (RmMonitorConfig rmMonitorConfig : rmMonitorConfigList) { + // 判断资源类型 + if("1".equals(rmMonitorConfig.getResourceType()) || "3".equals(rmMonitorConfig.getResourceType())){ + if("3".equals(rmMonitorConfig.getResourceType())){ + if(rmMonitorConfig.getBusinessName() == null){ + log.warn("不存在业务"); + continue; + } + // 根据业务代码查询服务器clientId + RmResourceRegistration queryRegist = new RmResourceRegistration(); + queryRegist.setBusinessName(rmMonitorConfig.getBusinessName()); + List registrationList = rmResourceRegistrationMapper.getRegistrationTableInfoList(queryRegist); + StringBuilder clientIds = new StringBuilder(); + if (registrationList != null && !registrationList.isEmpty()) { + for (RmResourceRegistration registration : registrationList) { + if (registration.getClientId() != null) { + if (clientIds.length() > 0) { + clientIds.append("\n"); + } + clientIds.append(registration.getClientId()); + } + } + } + rmMonitorConfig.setDeployDevice(clientIds.toString()); + } + List serverTrafficList = epsInitialTrafficDataService.getServerTrafficByMonitorView(rmMonitorConfig); + RmMonitorConfigDetails configDetailsQuery = new RmMonitorConfigDetails(); + configDetailsQuery.setMonitorId(rmMonitorConfig.getId()); + // 查询该数据是否存在 + List exitsList = rmMonitorConfigDetailsMapper.selectRmMonitorConfigDetailsList(configDetailsQuery); + // 将已存在记录的时间转换为Set便于快速查找 + Set existingTimeSet = exitsList.stream() + .map(RmMonitorConfigDetails::getCreateTime) + .collect(Collectors.toSet()); + // 批量准备插入数据 + List batchInsertList = new ArrayList<>(); + // 计算结果落入临时表 + for (EpsInitialTrafficData epsInitialTrafficData : serverTrafficList) { + // 使用Set快速判断是否存在,替代数据库查询 + if (!existingTimeSet.contains(epsInitialTrafficData.getCreateTime())) { + RmMonitorConfigDetails configDetails = new RmMonitorConfigDetails(); + configDetails.setMonitorId(rmMonitorConfig.getId()); + configDetails.setCreateTime(epsInitialTrafficData.getCreateTime()); + configDetails.setInSpeed(new BigDecimal(epsInitialTrafficData.getInSpeed() == null ? "0" : epsInitialTrafficData.getInSpeed())); + configDetails.setOutSpeed(new BigDecimal(epsInitialTrafficData.getOutSpeed() == null ? "0" : epsInitialTrafficData.getOutSpeed())); + configDetails.setDeployDevice(rmMonitorConfig.getDeployDevice()); + batchInsertList.add(configDetails); + } + } + // 批量插入 + if(!batchInsertList.isEmpty()){ + rmMonitorConfigDetailsMapper.batchInsertRmMonitorConfigDetails(batchInsertList); + } + }else{ + List switchInfoDetailsList = initialSwitchInfoDetailsService.getMonitorViewDetails(rmMonitorConfig); + RmMonitorConfigDetails configDetailsQuery = new RmMonitorConfigDetails(); + configDetailsQuery.setMonitorId(rmMonitorConfig.getId()); + // 查询该数据是否存在 + List exitsList = rmMonitorConfigDetailsMapper.selectRmMonitorConfigDetailsList(configDetailsQuery); + // 将已存在记录的时间转换为Set便于快速查找 + Set existingTimeSet = exitsList.stream() + .map(RmMonitorConfigDetails::getCreateTime) + .collect(Collectors.toSet()); + // 批量准备插入数据 + List batchInsertList = new ArrayList<>(); + for (InitialSwitchInfoDetails initialSwitchInfoDetails : switchInfoDetailsList) { + // 使用Set快速判断是否存在,替代数据库查询 + if (!existingTimeSet.contains(initialSwitchInfoDetails.getCreateTime())) { + RmMonitorConfigDetails configDetails = new RmMonitorConfigDetails(); + configDetails.setMonitorId(rmMonitorConfig.getId()); + configDetails.setCreateTime(initialSwitchInfoDetails.getCreateTime()); + configDetails.setInSpeed(initialSwitchInfoDetails.getInSpeed()); + configDetails.setOutSpeed(initialSwitchInfoDetails.getOutSpeed()); + configDetails.setDeployDevice(rmMonitorConfig.getDeployDevice()); + batchInsertList.add(configDetails); + } + // 批量插入 + if(!batchInsertList.isEmpty()){ + rmMonitorConfigDetailsMapper.batchInsertRmMonitorConfigDetails(batchInsertList); + } + } + } + } + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmSwitchManagementServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmSwitchManagementServiceImpl.java index b19dc8e..f5d984f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmSwitchManagementServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RmSwitchManagementServiceImpl.java @@ -176,7 +176,7 @@ public class RmSwitchManagementServiceImpl implements IRmSwitchManagementService interfaceName.getId().toString(), clientId, interfaceName.getInterfaceName(), - switchName + switchName, switchManagement.getId().toString() ); interfaceName.setValue(valueStr); interfaceName.setLabel(interfaceName.getInterfaceName()); diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/RmMonitorConfigDetailsMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/RmMonitorConfigDetailsMapper.xml index 0710f82..b8d97d9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/RmMonitorConfigDetailsMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/RmMonitorConfigDetailsMapper.xml @@ -94,4 +94,29 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{id} + + delete from rm_monitor_config_details where monitor_id in + + #{monitorId} + + + + insert IGNORE into rm_monitor_config_details + (monitor_id, deploy_device, in_bytes, out_bytes, in_speed, out_speed, create_by, update_by, create_time, update_time) + values + + ( + #{item.monitorId}, + #{item.deployDevice}, + #{item.inBytes}, + #{item.outBytes}, + #{item.inSpeed}, + #{item.outSpeed}, + #{item.createBy}, + #{item.updateBy}, + #{item.createTime}, + #{item.updateTime} + ) + + \ No newline at end of file