package com.ruoyi.system.service.impl; import java.net.InetAddress; import java.util.Date; import java.util.List; import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.TCollector; import com.ruoyi.system.mapper.TCollectorMapper; import com.ruoyi.system.service.ITCollectorService; /** * 采集器 Service 实现。 * * @author ruoyi */ @Service public class TCollectorServiceImpl implements ITCollectorService { private static final String ENABLED = "0"; private static final String DISABLED = "1"; private static final String OFFLINE = "0"; private static final String IDLE = "0"; private static final String TESTING = "1"; private static final Pattern IPV4_PATTERN = Pattern.compile( "^(25[0-5]|2[0-4]\\d|1?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|1?\\d?\\d)){3}$"); private static final Pattern MAC_PATTERN = Pattern.compile("^[0-9A-F]{2}(:[0-9A-F]{2}){5}$"); @Autowired private TCollectorMapper collectorMapper; /** * 查询未删除采集器,不存在时抛出业务异常。 */ @Override public TCollector selectCollectorById(Long collectorId) { if (collectorId == null) { throw new ServiceException("采集器ID不能为空"); } TCollector collector = collectorMapper.selectCollectorById(collectorId); if (collector == null) { throw new ServiceException("采集器不存在"); } return collector; } /** * 按设备、创建时间区间和状态查询采集器列表。 */ @Override public List selectCollectorList(TCollector collector) { if (collector == null) { collector = new TCollector(); } collector.setDevice(trimToNull(collector.getDevice())); collector.setBeginCreateTime(trimToNull(collector.getBeginCreateTime())); collector.setEndCreateTime(trimToNull(collector.getEndCreateTime())); validateOptionalStatus(collector.getOnlineStatus(), "在线状态"); validateOptionalStatus(collector.getTestStatus(), "测试状态"); validateOptionalStatus(collector.getStatus(), "状态"); return collectorMapper.selectCollectorList(collector); } /** * 新增采集器并初始化运行状态。 */ @Override public int insertCollector(TCollector collector) { validateCollector(collector, false); collector.setOnlineStatus(OFFLINE); collector.setTestStatus(IDLE); collector.setCurrentTest(null); collector.setCurrentSampleName(null); if (StringUtils.isEmpty(collector.getStatus())) { collector.setStatus(ENABLED); } else { validateStatus(collector.getStatus(), "状态"); } collector.setDelFlag("0"); collector.setCreateTime(new Date()); return collectorMapper.insertCollector(collector); } /** * 编辑采集器基础资料和启禁用状态,不覆盖设备运行状态。 */ @Override public int updateCollector(TCollector collector) { validateCollector(collector, true); validateStatus(collector.getStatus(), "状态"); if (DISABLED.equals(collector.getStatus())) { validateCollectorNotTesting(selectCollectorById(collector.getCollectorId()), "禁用"); } collector.setUpdateTime(new Date()); return collectorMapper.updateCollector(collector); } /** * 启用或禁用采集器;测试中的采集器禁止禁用。 */ @Override public int updateCollectorStatus(TCollector collector) { if (collector == null || collector.getCollectorId() == null) { throw new ServiceException("采集器ID不能为空"); } validateStatus(collector.getStatus(), "状态"); TCollector current = selectCollectorById(collector.getCollectorId()); if (DISABLED.equals(collector.getStatus())) { validateCollectorNotTesting(current, "禁用"); } if (collector.getStatus().equals(current.getStatus())) { return 1; } collector.setUpdateTime(new Date()); return collectorMapper.updateCollectorStatus(collector); } /** * 先校验全部记录,再在同一事务中执行批量逻辑删除。 */ @Override @Transactional(rollbackFor = Exception.class) public int deleteCollectorByIds(Long[] collectorIds, String updateBy) { if (collectorIds == null || collectorIds.length == 0) { throw new ServiceException("请选择要删除的采集器"); } for (Long collectorId : collectorIds) { validateCollectorNotTesting(selectCollectorById(collectorId), "删除"); } int rows = 0; for (Long collectorId : collectorIds) { rows += collectorMapper.deleteCollectorById(collectorId, updateBy); } return rows; } /** * 校验并规范化采集器基础资料,同时检查唯一性。 */ private void validateCollector(TCollector collector, boolean update) { if (collector == null) { throw new ServiceException("采集器信息不能为空"); } if (update) { selectCollectorById(collector.getCollectorId()); } collector.setCollectorCode(trimToNull(collector.getCollectorCode())); collector.setIpAddress(trimToNull(collector.getIpAddress())); collector.setMacAddress(normalizeMacAddress(collector.getMacAddress())); collector.setCollectorName(trimToNull(collector.getCollectorName())); collector.setManufacturer(trimToNull(collector.getManufacturer())); collector.setModel(trimToNull(collector.getModel())); collector.setRemark(trimToNull(collector.getRemark())); if (StringUtils.isEmpty(collector.getCollectorCode())) { throw new ServiceException("设备编码不能为空"); } if (StringUtils.isEmpty(collector.getCollectorName())) { throw new ServiceException("采集器名称不能为空"); } validateIpAddress(collector.getIpAddress()); if (collector.getChannelCount() == null || collector.getChannelCount() < 1 || collector.getChannelCount() > 10000) { throw new ServiceException("通道数必须在1到10000之间"); } validateUnique(collector); } /** * 校验设备编码和 MAC 地址在未删除数据中唯一。 */ private void validateUnique(TCollector collector) { TCollector sameCode = collectorMapper.selectCollectorByCode(collector.getCollectorCode()); if (isDifferentCollector(sameCode, collector.getCollectorId())) { throw new ServiceException("设备编码已存在"); } TCollector sameMac = collectorMapper.selectCollectorByMacAddress(collector.getMacAddress()); if (isDifferentCollector(sameMac, collector.getCollectorId())) { throw new ServiceException("MAC地址已存在"); } } /** * 判断唯一性查询结果是否属于其他采集器。 */ private boolean isDifferentCollector(TCollector existing, Long collectorId) { return existing != null && (collectorId == null || !collectorId.equals(existing.getCollectorId())); } /** * 规范化并校验 MAC 地址。 */ private String normalizeMacAddress(String macAddress) { String normalized = trimToNull(macAddress); if (normalized == null) { throw new ServiceException("MAC地址不能为空"); } normalized = normalized.replace('-', ':').toUpperCase(); if (!MAC_PATTERN.matcher(normalized).matches()) { throw new ServiceException("MAC地址格式不正确"); } return normalized; } /** * 校验 IPv4 或 IPv6 地址,不接受主机名。 */ private void validateIpAddress(String ipAddress) { if (StringUtils.isEmpty(ipAddress)) { throw new ServiceException("IP地址不能为空"); } if (IPV4_PATTERN.matcher(ipAddress).matches()) { return; } if (!ipAddress.contains(":")) { throw new ServiceException("IP地址格式不正确"); } try { InetAddress address = InetAddress.getByName(ipAddress); if (address.getAddress().length != 16) { throw new ServiceException("IP地址格式不正确"); } } catch (Exception exception) { throw new ServiceException("IP地址格式不正确"); } } /** * 校验可选的二值状态查询条件。 */ private void validateOptionalStatus(String status, String name) { if (StringUtils.isNotEmpty(status)) { validateStatus(status, name); } } /** * 校验状态值只能为 0 或 1。 */ private void validateStatus(String status, String name) { if (!ENABLED.equals(status) && !DISABLED.equals(status)) { throw new ServiceException(name + "只能为0或1"); } } /** * 删除或禁用前校验采集器不处于测试中。 */ private void validateCollectorNotTesting(TCollector collector, String operation) { if (TESTING.equals(collector.getTestStatus())) { throw new ServiceException("采集器正在测试,不能" + operation); } } /** * 去除字符串首尾空白,并将空字符串转换为 null。 */ private String trimToNull(String value) { return StringUtils.isEmpty(StringUtils.trim(value)) ? null : StringUtils.trim(value); } }