From e82b63c8a83ba7cb399230389f999a6118e7669d Mon Sep 17 00:00:00 2001 From: longguancheng Date: Mon, 2 Feb 2026 16:18:42 +0800 Subject: [PATCH] Replace all Redis entries with Caffeine. --- .../service/impl/PayloadServiceImpl.java | 110 ++++++++++------ .../jm/controller/JmImageController.java | 44 ++----- .../service/impl/JmJobStatusServiceImpl.java | 3 - .../skyeye/jm/task/JmTaskScheduler.java | 66 +++++----- .../context/SarTaskContextProviderImpl.java | 57 ++++---- .../control/SarControlConnectStrategy.java | 36 ++++-- .../skyeye/sar/control/SarControlContext.java | 35 ++--- .../control/SarControlDisconnectStrategy.java | 31 +++-- .../skyeye/sar/listen/SarStatusListener.java | 28 ++-- .../service/impl/SarControlServiceImpl.java | 24 ++-- .../sar/service/impl/SarImageServiceImpl.java | 122 +++++++----------- .../src/main/resources/application-dev.yml | 10 +- 12 files changed, 298 insertions(+), 268 deletions(-) diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/device/service/impl/PayloadServiceImpl.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/device/service/impl/PayloadServiceImpl.java index 0cc6bd4..f5f0e86 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/device/service/impl/PayloadServiceImpl.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/device/service/impl/PayloadServiceImpl.java @@ -17,26 +17,26 @@ import com.zhangy.skyeye.jm.dto.JmUavStatusDTO; import com.zhangy.skyeye.jm.service.JmJobStatusService; import com.zhangy.skyeye.publics.consts.CacheKey; import com.zhangy.skyeye.publics.consts.ExecStatusEnum; -import com.zhangy.skyeye.redis.utils.RedisUtil; +import com.zhangy.skyeye.publics.utils.CacheUtil; import com.zhangy.skyeye.sar.service.ISarControlService; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +@Slf4j @Service public class PayloadServiceImpl implements IPayloadService { @Autowired - private RedisTemplate redisTemplate; + private CacheManager cacheManager; @Autowired private PayloadMapper payloadMapper; @@ -47,36 +47,70 @@ public class PayloadServiceImpl implements IPayloadService { @Autowired private ISarControlService sarControlService; + private Cache sarPermanentCache; // SAR 专用永久缓存 + private Cache sarShortCache; // 短时状态 + + @PostConstruct + public void initAndCacheAllSar() { + // 1. 初始化缓存实例(获取“盒子”) + sarPermanentCache = cacheManager.getCache("device-permanent"); + sarShortCache = cacheManager.getCache("sar-short-lived"); + // 2. 防护检查(不抛异常,而是日志 + 降级) + if (sarPermanentCache == null) { + log.error("device-permanent 缓存未找到!请检查 CacheConfig 是否正确注册"); + throw new IllegalStateException("device-permanent 缓存未找到"); + } + if (sarShortCache == null) { + log.error("sar-short-lived 缓存未找到!请检查 CacheConfig"); + throw new IllegalStateException("sar-short-lived 缓存未找到"); + } + + // 3. 开始缓存所有 SAR(如果 permanentCache 为 null,这里会安全跳过) + PayloadQueryDTO payloadQueryDTO = new PayloadQueryDTO(); + payloadQueryDTO.setType(PayloadTypeEnum.SAR.getCode()); + List sarList = selectList(payloadQueryDTO); + + if (sarPermanentCache != null) { + sarList.forEach(this::cacheSar); + log.info("SAR 载荷缓存完成,共 {} 条", sarList.size()); + } else { + log.warn("永久缓存不可用,跳过 SAR 预加载"); + } + } + @Override public IPage selectPage(PageDTO param) { return payloadMapper.selectPage(param); } - @PostConstruct - public void cacheAllSar() { - PayloadQueryDTO payloadQueryDTO = new PayloadQueryDTO(); - payloadQueryDTO.setType(PayloadTypeEnum.SAR.getCode()); - List sarList = selectList(payloadQueryDTO); - sarList.forEach(this::cacheSar); - } - private void cacheSar(SkyeyePayload e) { - redisTemplate.opsForHash().put(CacheKey.DEVICE_SAR, e.getId().toString(), e); + if (sarPermanentCache != null) { + sarPermanentCache.put(e.getId().toString(), e); + } } @Override public List getSar(Long... sarId) { if (ObjectUtil.isNotEmpty(sarId)) { - return redisTemplate.opsForHash().multiGet(CacheKey.DEVICE_SAR, Arrays.asList(sarId)); + return Arrays.stream(sarId) + .map(id -> CacheUtil.get(sarPermanentCache, id.toString(), SkyeyePayload.class)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } - return redisTemplate.opsForHash().values(CacheKey.DEVICE_SAR); + + // 获取所有 SAR(全量从缓存读取) + com.github.benmanes.caffeine.cache.Cache nativeCache = + (com.github.benmanes.caffeine.cache.Cache) sarPermanentCache.getNativeCache(); + + return nativeCache.asMap().values().stream() + .filter(v -> v instanceof SkyeyePayload) + .map(v -> (SkyeyePayload) v) + .collect(Collectors.toList()); } @Override public SkyeyePayload getOne(Long payloadId) { - SkyeyePayload p = (SkyeyePayload) redisTemplate.opsForHash().get(CacheKey.DEVICE_SAR, payloadId.toString()); - // 若有其它种类载荷,则判空,继续查询 - return p; + return CacheUtil.get(sarPermanentCache, payloadId.toString(), SkyeyePayload.class); } @Override @@ -84,10 +118,6 @@ public class PayloadServiceImpl implements IPayloadService { return payloadMapper.selectList(param); } - - @Autowired - private RedisUtil redisUtil; - @Override public List getEnableList() { // 从缓存查询所有sar @@ -98,13 +128,16 @@ public class PayloadServiceImpl implements IPayloadService { // 从内存查询所有任务中的雷达 Collection statusVos = sarJobStatusService.getAll(); Set jobSarSet = statusVos.stream() - .flatMap(job -> job.getUavMap().values().stream().filter(uav -> uav.getSarStatus() != ExecStatusEnum.OVER)) - .map(JmUavStatusDTO::getSarId) + .flatMap(job -> job.getUavMap().values().stream() + .filter(uav -> uav.getSarStatus() != ExecStatusEnum.OVER)) + .map(JmUavStatusDTO::getSarId) // 正确取 SAR ID .collect(Collectors.toSet()); // 筛选出未在任务中且已连接的雷达 - return sarList.stream() - .filter(sar -> !jobSarSet.contains(sar.getId()) && redisUtil.hasKey(CacheKey.getSarConnect(sar.getIp()))) + List payloadList = sarList.stream() + .filter(sar -> !jobSarSet.contains(sar.getId()) + && CacheUtil.get(sarShortCache, CacheKey.getSarConnect(sar.getIp()), JmSarStatusDTO.class) != null) .collect(Collectors.toList()); + return payloadList; } @Override @@ -171,38 +204,43 @@ public class PayloadServiceImpl implements IPayloadService { @Transactional @Override public void delete(Long... id) { - // 查询任务中的sar List inJobSarIds = sarJobStatusService.getAll() .stream() .flatMap(vo -> vo.getUavMap().values().stream()) .filter(vo -> vo.getSarStatus() != ExecStatusEnum.OVER) .map(JmUavStatusDTO::getSarId) .collect(Collectors.toList()); - // 任务中的不可删除 + for (Long sarId : id) { if (inJobSarIds.contains(sarId)) { - throw ServiceException.noLog("[" + getSar(sarId).get(0).getName() + "]在执行任务,不可删除"); + List sar = getSar(sarId); + if (!sar.isEmpty()) { + throw ServiceException.noLog("[" + sar.get(0).getName() + "]在执行任务,不可删除"); + } } } + payloadMapper.deleteLogic(id); - redisTemplate.opsForHash().delete(CacheKey.DEVICE_SAR, id); + Arrays.stream(id).forEach(i -> sarPermanentCache.evict(i.toString())); } @Override public JmSarStatusDTO getLastStatus(String payloadIp) { String statusKey = CacheKey.getSarConnect(payloadIp); - if (!redisUtil.hasKey(statusKey)) { + JmSarStatusDTO status = CacheUtil.get(sarShortCache, statusKey, JmSarStatusDTO.class); + if (status == null) { try { sarControlService.connect(payloadIp); TimeUnit.SECONDS.sleep(1); + status = CacheUtil.get(sarShortCache, statusKey, JmSarStatusDTO.class); } catch (InterruptedException ex) { throw new ServiceException("获取雷达状态失败:" + ex.getMessage()); } - if (!redisUtil.hasKey(statusKey)) { + if (status == null) { throw ServiceException.noLog("无法连接到SAR载荷[" + payloadIp + "]!"); } } - return (JmSarStatusDTO) redisUtil.get(statusKey); + return status; } @Override diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/controller/JmImageController.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/controller/JmImageController.java index e4c5a05..ff35e4a 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/controller/JmImageController.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/controller/JmImageController.java @@ -10,18 +10,14 @@ import com.zhangy.skyeye.jm.dto.JmJobImageDTO; import com.zhangy.skyeye.jm.entity.JmImage; import com.zhangy.skyeye.jm.service.JmImageService; import com.zhangy.skyeye.publics.consts.FileTypeEnum; +import com.zhangy.skyeye.publics.utils.LocalLockUtil; import org.opencv.core.Core; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.net.ConnectException; -import java.util.Collections; -import java.util.UUID; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static com.zhangy.skyeye.publics.consts.CacheKey.SAR_IMAGE_UPLOAD_LOCK; @@ -30,12 +26,12 @@ import static com.zhangy.skyeye.publics.consts.CacheKey.SAR_IMAGE_UPLOAD_LOCK; @RestController @RequestMapping("/sar/image") public class JmImageController { - + @Autowired private JmImageService sarImageService; @Autowired - private RedisTemplate redisTemplate; + private LocalLockUtil localLockUtil; /** * 分页查询 @@ -44,16 +40,16 @@ public class JmImageController { public Object selectPage(@Valid @RequestBody JmImagePageDTO param) { return sarImageService.selectPage(param); } - - /** + + /** * 按任务查询低精度图像 */ @GetMapping("/queryByJob") public Object selectList(@RequestParam Long jobId) { return sarImageService.selectByJob(FileTypeEnum.SAR_IMAGE_LOW, jobId); } - - /** + + /** * 查询详情 */ @GetMapping("/detail") @@ -77,29 +73,14 @@ public class JmImageController { @PostMapping("/addHigh") public Object addHighImage(@Valid @RequestBody JmJobImageDTO dto) { String lockKey = SAR_IMAGE_UPLOAD_LOCK; - String requestId = UUID.randomUUID().toString(); // 唯一标识当前请求 + boolean locked = localLockUtil.tryLock(lockKey, 60); // 尝试 60 秒获取锁(比原来 1 分钟更灵活) + if (!locked) { + throw ServiceException.noLog("正在上传其它图像,请稍后重试!"); + } try { - // 原子操作获取锁(设置过期时间30秒) - Boolean locked = redisTemplate.opsForValue().setIfAbsent( - lockKey, - requestId, - 1, - TimeUnit.MINUTES - ); - if (Boolean.FALSE.equals(locked)) { - throw ServiceException.noLog("正在上传其它图像,请稍后重试!"); - } sarImageService.addHighImage(dto); } finally { - // 仅删除自己的锁(Lua脚本保证原子性) - String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " - + "return redis.call('del', KEYS[1]) " - + "else return 0 end"; - redisTemplate.execute( - new DefaultRedisScript<>(luaScript, Long.class), - Collections.singletonList(lockKey), - requestId - ); + localLockUtil.unlock(lockKey); // 释放锁 } return "操作完成"; } @@ -135,6 +116,7 @@ public class JmImageController { .map(e -> BeanUtil.copyProperties(e, JmImageKtyDTO.class)) .collect(Collectors.toList()); } + static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/service/impl/JmJobStatusServiceImpl.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/service/impl/JmJobStatusServiceImpl.java index dfa974d..bca64d8 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/service/impl/JmJobStatusServiceImpl.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/service/impl/JmJobStatusServiceImpl.java @@ -42,9 +42,6 @@ public class JmJobStatusServiceImpl implements JmJobStatusService { @Autowired private SarImageUdpProcessor imageProcessService; -// @Autowired -// private ISmpSubscriptService subscriptService; - /** * 缓存所有执行中的任务的状态 key 任务配置ID,value 任务状态 */ diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/task/JmTaskScheduler.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/task/JmTaskScheduler.java index 04b0997..8056d04 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/task/JmTaskScheduler.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/jm/task/JmTaskScheduler.java @@ -1,26 +1,24 @@ package com.zhangy.skyeye.jm.task; -import com.zhangy.skyeye.redis.utils.RedisUtil; import com.zhangy.skyeye.device.entity.SkyeyePayload; import com.zhangy.skyeye.device.service.IPayloadService; -import com.zhangy.skyeye.jm.dto.JmJobStatusDTO; +import com.zhangy.skyeye.jm.dto.JmSarStatusDTO; import com.zhangy.skyeye.publics.consts.CacheKey; import com.zhangy.skyeye.publics.service.ISysLoginService; +import com.zhangy.skyeye.publics.utils.CacheUtil; import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; -import com.zhangy.skyeye.jm.service.JmJobStatusService; import com.zhangy.skyeye.sar.exception.SarConnectException; import com.zhangy.skyeye.sar.service.ISarControlService; -// import com.zhangy.skyeye.smp.dto.SmpUavStatusWsDTO; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; -import java.util.Collection; +import javax.annotation.PostConstruct; import java.util.List; /** @@ -34,18 +32,6 @@ public class JmTaskScheduler { @Setter private boolean isDebug; - @Autowired - private RedisUtil redisUtil; - - @Autowired - private JmJobStatusService jobStatusService; - - @Autowired - private SimpMessagingTemplate simpMessagingTemplate; - - @Autowired - RedisTemplate redisTemplate; - @Autowired private ISysLoginService loginService; @@ -56,7 +42,16 @@ public class JmTaskScheduler { private IPayloadService payloadService; @Autowired - private ISarControlService sarControlService; + private CacheManager cacheManager; + + private Cache sarPermanentCache; + private Cache sarShortCache; + + @PostConstruct + public void initCaches() { + sarPermanentCache = cacheManager.getCache("sar-payload-permanent"); + sarShortCache = cacheManager.getCache("sar-short-lived"); + } /** * 每1秒向前端推送雷达状态信息,断开连接则所有数据置0返回 @@ -108,28 +103,31 @@ public class JmTaskScheduler { /** * 每10秒进行载荷连接判断: * 1. 如果有用户登录: - * 1)未执行连接指令,进行连接 - * 2)已经执行连接指令,但没有获取到sar状态信息,进行重连 + * 1)未执行连接指令,进行连接 + * 2)已经执行连接指令,但没有获取到sar状态信息,进行重连 * 2. 没有用户在线: - * 无。因为断开连接会先结束任务,不能断开连接。等硬件断电 + * 无。因为断开连接会先结束任务,不能断开连接。等硬件断电 */ @Scheduled(fixedRate = 10000) public void connectSar() { - if (!loginService.hasLogged() || isDebug) { // 断开 - /*Map map = redisUtil.hmget(CacheKey.SAR_CONNECTED); - if (map != null && map.size() > 0) { - map.keySet().forEach(ip -> controlInfoService.sendUdp((String) ip, SarControlTypeEnum.DISCONNECT)); - }*/ - } else { // 连接 + if (!loginService.hasLogged() || isDebug) { + // 断开逻辑:如果需要,可遍历 permanentCache 或其他方式获取 ip 列表 + // 但当前注释掉了,保持原样或删除 + } else { List sarList = payloadService.getSar(null); sarList.forEach(sar -> { - if (!redisUtil.hHasKey(CacheKey.SAR_CONNECTED, sar.getIp()) || - !redisUtil.hasKey(CacheKey.getSarConnect(sar.getIp()))) { + String ip = sar.getIp(); + // 判断是否已连接:看 shortCache 里是否有该 ip 的状态(最近有状态包) + boolean hasStatus = CacheUtil.get(sarShortCache, CacheKey.getSarConnect(ip), JmSarStatusDTO.class) != null; + // 判断是否已执行连接指令:看 permanentCache 里是否有该 ip 的连接标志 + boolean hasConnectedFlag = sarPermanentCache.get(ip) != null; + // 如果缺少状态 或 缺少连接标志,则尝试连接 + if (!hasConnectedFlag || !hasStatus) { try { - controlInfoService.sendUdp(sar.getIp(), SarControlTypeEnum.CONNECT); + controlInfoService.sendUdp(ip, SarControlTypeEnum.CONNECT); + log.info("尝试连接 SAR IP: {}", ip); } catch (SarConnectException ex) { - // sar可能没通电,连接失败不做处理 - log.warn("连接雷达[" + sar.getIp() + "]失败:" + ex.getMessage()); + log.warn("连接雷达[{}]失败:{}", ip, ex.getMessage()); } } }); diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/context/SarTaskContextProviderImpl.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/context/SarTaskContextProviderImpl.java index ac7516c..e300706 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/context/SarTaskContextProviderImpl.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/context/SarTaskContextProviderImpl.java @@ -2,19 +2,19 @@ package com.zhangy.skyeye.sar.context; import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO; import com.zhangy.skyeye.jm.dto.JmUavStatusDTO; -import com.zhangy.skyeye.redis.utils.RedisUtil; +import com.zhangy.skyeye.publics.utils.CacheUtil; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Component; -/** - * - */ +import javax.annotation.PostConstruct; + /** * @PROJECT_NAME: skyeyesystem * @DESCRIPTION: SAR 任务上下文提供者实现(基于 Redis 缓存,避免循环依赖) - * - JmJobStatusServiceImpl 在更新状态时,主动把 JmUavStatusDTO 推送到 Redis - * - 此类只从 Redis 读取,不注入 JmJobStatusService + * - JmJobStatusServiceImpl 在更新状态时,主动把 JmUavStatusDTO 推送到 Redis + * - 此类只从 Redis 读取,不注入 JmJobStatusService * @AUTHOR: GuanCheng Long * @DATE: 2026/1/21 1:10 */ @@ -22,14 +22,21 @@ import org.springframework.stereotype.Component; @Component public class SarTaskContextProviderImpl implements SarTaskContextProvider { - @Autowired - private RedisUtil redisUtil; + private final CacheManager cacheManager; - // Redis 键前缀 - private static final String UAV_STATUS_KEY_PREFIX = "sar:context:uav:"; + private Cache uavStatusCache; - // 缓存过期时间(秒) - private static final long CACHE_EXPIRE_SECONDS = 600; // 10 分钟 + public SarTaskContextProviderImpl(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + @PostConstruct + public void initCache() { + this.uavStatusCache = cacheManager.getCache("uav-status"); + if (this.uavStatusCache == null) { + log.error("缓存 uav-status 未找到,请检查 CacheConfig 配置"); + } + } @Override public JmUavStatusDTO getCurrentUav(String payloadIp) { @@ -38,15 +45,8 @@ public class SarTaskContextProviderImpl implements SarTaskContextProvider { return null; } - String key = UAV_STATUS_KEY_PREFIX + payloadIp; - Object obj = redisUtil.get(key); - - if (obj instanceof JmUavStatusDTO) { - return (JmUavStatusDTO) obj; - } - - log.debug("Redis 中未找到 IP={} 的 uav 状态", payloadIp); - return null; + String key = "sar:context:uav:" + payloadIp; // 保持原 key 格式 + return CacheUtil.get(uavStatusCache, key, JmUavStatusDTO.class); } @Override @@ -80,11 +80,10 @@ public class SarTaskContextProviderImpl implements SarTaskContextProvider { return; } - String key = UAV_STATUS_KEY_PREFIX + payloadIp; + String key = "sar:context:uav:" + payloadIp; try { - // 设置值 + 过期时间 - redisUtil.set(key, uavStatus, CACHE_EXPIRE_SECONDS); - log.debug("已更新 Redis 缓存:key={}, jobExecId={}", key, uavStatus.getJobExecId()); + uavStatusCache.put(key, uavStatus); // 自动过期 10 分钟 + log.debug("已更新缓存:key={}, jobExecId={}", key, uavStatus.getJobExecId()); } catch (Exception e) { log.error("更新 SAR uav 状态缓存失败,ip={}", payloadIp, e); } @@ -97,8 +96,8 @@ public class SarTaskContextProviderImpl implements SarTaskContextProvider { if (payloadIp == null) { return; } - String key = UAV_STATUS_KEY_PREFIX + payloadIp; - redisUtil.del(key); - log.debug("SAR uav 缓存已标记清理(或自然过期):{}", key); + String key = "sar:context:uav:" + payloadIp; + uavStatusCache.evict(key); + log.debug("SAR uav 缓存已清理:{}", key); } } \ No newline at end of file diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlConnectStrategy.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlConnectStrategy.java index 20ad395..83a632b 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlConnectStrategy.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlConnectStrategy.java @@ -1,21 +1,23 @@ package com.zhangy.skyeye.sar.control; -import com.zhangy.skyeye.redis.utils.RedisUtil; -import com.zhangy.skyeye.publics.consts.CacheKey; -import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; import com.zhangy.skyeye.sar.dto.SarControlDTO; import com.zhangy.skyeye.sar.dto.SarControlParamDTO; +import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.util.Collections; import java.util.Date; import java.util.List; /** - * 控制:连接 + * 控制:建立连接 + * 连接成功后,在回传状态时会将状态信息放入缓存,这里只记录连接标志 */ @Slf4j @Order(1) @@ -23,7 +25,18 @@ import java.util.List; @RequiredArgsConstructor public class SarControlConnectStrategy implements ISarControlStrategy { - private final RedisUtil redisUtil; + private final CacheManager cacheManager; + + // 不加 final,因为在 PostConstruct 中初始化 + private Cache permanentCache; + + @PostConstruct + public void initCache() { + this.permanentCache = cacheManager.getCache("sar-payload-permanent"); + if (this.permanentCache == null) { + log.error("永久缓存 sar-payload-permanent 未找到,请检查 CacheConfig 配置"); + } + } @Override public boolean supports(SarControlParamDTO param) { @@ -40,15 +53,16 @@ public class SarControlConnectStrategy implements ISarControlStrategy { @Override public void sendPost(SarControlDTO sar) { - // 建立连接后,回传状态时会将状态信息放入缓存 - redisUtil.hset(CacheKey.SAR_CONNECTED, sar.getIp(), new Date()); + // 建立连接后,记录连接标志(value 可以是 Date、字符串 "connected" 或 boolean true,随你业务) + if (permanentCache != null) { + permanentCache.put(sar.getIp(), new Date()); + } else { + log.warn("无法记录连接标志,永久缓存未初始化"); + } } @Override public int retryType() { return 0; } -} - - - +} \ No newline at end of file diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlContext.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlContext.java index 926e7e4..6f3a528 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlContext.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlContext.java @@ -2,8 +2,8 @@ package com.zhangy.skyeye.sar.control; import com.zhangy.skyeye.common.extend.exception.ServiceException; import com.zhangy.skyeye.common.extend.util.ObjectUtil; -import com.zhangy.skyeye.redis.utils.RedisUtil; import com.zhangy.skyeye.publics.consts.CacheKey; +import com.zhangy.skyeye.publics.utils.CacheUtil; import com.zhangy.skyeye.sar.dto.SarControlDTO; import com.zhangy.skyeye.sar.dto.SarControlPackDTO; import com.zhangy.skyeye.sar.dto.SarControlParamDTO; @@ -14,7 +14,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.RedisConnectionFailureException; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @@ -59,7 +60,7 @@ public class SarControlContext { private final int POLLING_INTERVAL = 100; @Autowired - private RedisUtil redisUtil; + private CacheManager cacheManager; /** * 应答超时 @@ -74,6 +75,7 @@ public class SarControlContext { /** * 执行 + * * @param param */ public void execute(SarControlParamDTO param) { @@ -89,12 +91,12 @@ public class SarControlContext { /** * 执行发送:失败则递归重试 * - * @param param 控制参数 + * @param param 控制参数 * @param matchedStrategy 控制策略 */ private void sendControl(SarControlParamDTO param, ISarControlStrategy matchedStrategy) { List controls = matchedStrategy.handle(param); - for(SarControlDTO control: controls) { + for (SarControlDTO control : controls) { control.setIp(param.getIp()); sendUdp(control); matchedStrategy.sendPost(control); @@ -103,30 +105,30 @@ public class SarControlContext { /** * 发送,未收到回执则重发 + * * @param control */ private void sendUdp(SarControlDTO control) { SarControlTypeEnum controlType = control.getControlType(); String ip = control.getIp(); - log.debug("开始发送雷达控制指令[" + controlType + "]----------------------"); - //System.out.println(control); + log.debug("开始发送雷达控制指令[{}]", controlType); try (DatagramSocket socket = new DatagramSocket()) { byte[] content = pack(control); socket.connect(new InetSocketAddress(ip, PORT)); DatagramPacket packet = new DatagramPacket(content, content.length); - int failCount = 0; SarErrorDTO info = null; - while (info == null && failCount < RETRY_MAX) { // 失败重试 + String cacheKey = CacheKey.getSarControlBack(ip); // skyeye:sar:control + ip + while (info == null && failCount < RETRY_MAX) { socket.send(packet); // 每0.1秒取回执,1秒后超时 long startTime = System.currentTimeMillis(); - String cacheKey = CacheKey.getSarControlBack(ip); - while (System.currentTimeMillis() - startTime < ANSWER_TIMEOUT) { - if (redisUtil.hasKey(cacheKey)) { - info = (SarErrorDTO) redisUtil.get(cacheKey); - redisUtil.del(cacheKey); + // 从 Caffeine 获取 + Cache shortCache = cacheManager.getCache("sar-short-lived"); + info = CacheUtil.get(shortCache, cacheKey, SarErrorDTO.class); + if (info != null) { + shortCache.evict(cacheKey); // 相当于 del,读取后删除 break; } else { try { @@ -146,10 +148,8 @@ public class SarControlContext { if (info == null) { throw new SarConnectException("控制指令[" + controlType + "]发送失败,雷达[" + ip + "]无应答,请重试"); } else { - log.info("雷达控制指令[" + controlType + "]发送完毕----------------------"); + log.info("雷达控制指令[{}]发送完毕----------------------", controlType); } - } catch (RedisConnectionFailureException ex) { - throw ServiceException.errorLog("无法连接到Redis服务!"); } catch (IOException ex) { throw ServiceException.errorLog("控制指令[" + controlType + "]发送失败 " + ex.getMessage()); } @@ -157,6 +157,7 @@ public class SarControlContext { /** * 封包 + * * @param sarControl * @return */ diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlDisconnectStrategy.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlDisconnectStrategy.java index 4e36b15..be5be3a 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlDisconnectStrategy.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/control/SarControlDisconnectStrategy.java @@ -1,15 +1,17 @@ package com.zhangy.skyeye.sar.control; -import com.zhangy.skyeye.redis.utils.RedisUtil; -import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; -import com.zhangy.skyeye.sar.dto.SarControlDTO; import com.zhangy.skyeye.publics.consts.CacheKey; +import com.zhangy.skyeye.sar.dto.SarControlDTO; import com.zhangy.skyeye.sar.dto.SarControlParamDTO; +import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.util.Collections; import java.util.List; @@ -22,7 +24,16 @@ import java.util.List; @RequiredArgsConstructor public class SarControlDisconnectStrategy implements ISarControlStrategy { - private final RedisUtil redisUtil; + private final CacheManager cacheManager; + + private Cache shortCache; + private Cache permanentCache; + + @PostConstruct + public void init() { + this.shortCache = cacheManager.getCache("sar-short-lived"); + this.permanentCache = cacheManager.getCache("sar-payload-permanent"); + } @Override public boolean supports(SarControlParamDTO param) { @@ -37,15 +48,15 @@ public class SarControlDisconnectStrategy implements ISarControlStrategy { return Collections.singletonList(connect); } - /** - * 删除缓存键 - * @param sar - */ @Override public void sendPost(SarControlDTO sar) { String connectKey = CacheKey.getSarConnect(sar.getIp()); - redisUtil.del(connectKey); - redisUtil.hdel(CacheKey.SAR_CONNECTED, sar.getIp()); + if (shortCache != null) { + shortCache.evict(connectKey); + } + if (permanentCache != null) { + permanentCache.evict(sar.getIp()); + } } @Override diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/listen/SarStatusListener.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/listen/SarStatusListener.java index 0eb61f6..2981c15 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/listen/SarStatusListener.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/listen/SarStatusListener.java @@ -1,6 +1,5 @@ package com.zhangy.skyeye.sar.listen; -import com.zhangy.skyeye.redis.utils.RedisUtil; import com.zhangy.skyeye.jm.dto.JmSarStatusDTO; import com.zhangy.skyeye.jm.service.JmJobStatusService; import com.zhangy.skyeye.publics.consts.CacheKey; @@ -13,6 +12,8 @@ import com.zhangy.skyeye.sar.task.PriorityThreadFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Component; import java.io.IOException; @@ -50,7 +51,7 @@ public class SarStatusListener extends SarAbstractListener { private int connectTimeout; @Autowired - private RedisUtil redisUtil; + private CacheManager cacheManager; @Autowired private JmJobStatusService sarJobStatusService; @@ -70,37 +71,40 @@ public class SarStatusListener extends SarAbstractListener { @Override protected void processData(DatagramPacket packet) throws IOException { socket.receive(packet); - // 过滤无效数据包 if (packet.getLength() != 100) { return; } log.debug("接收到状态包----------------------"); String ip = packet.getAddress().getHostAddress(); - // 处理接收到的数据 SarStatusPackDTO packDTO = SarStatusPackDTO.parse(ip, packet.getData()); if (packDTO == null) { if (running) - log.warn("[" + packDTO.getPayloadIp() + "]状态包校验失败,已丢弃。错误包=" + - packDTO.getErrorPacketStatus() + ",状态包=" + packDTO.getDevicePacketStatus()); + log.warn("状态包校验失败,已丢弃。"); return; } - // 错误包,结果放入缓存,超时1秒 + Cache sarShortCache = cacheManager.getCache("sar-short-lived"); + if (sarShortCache == null) { + log.error("sar-short-lived 缓存未找到!请检查 CacheConfig"); + throw new IllegalStateException("sar-short-lived 缓存未找到"); + } + // 错误包 → 回执 int errorStatus = packDTO.getErrorPacketStatus(); if (errorStatus == 1) { SarErrorDTO info = packDTO.getDeviceErrorInfo(); if (info.getErrorPacketType() == SarErrorTypeEnum.RESULT) { - log.debug("收到回执包:" + ip); - redisUtil.set(CacheKey.getSarControlBack(ip), info, answerTimeout, TimeUnit.SECONDS); + log.debug("收到回执包:{}", ip); + String controlBackKey = CacheKey.getSarControlBack(ip); + sarShortCache.put(controlBackKey, info); // 写入,自动 2s 过期 } } // 状态包 int deviceStatus = packDTO.getDevicePacketStatus(); if (deviceStatus == 1) { JmSarStatusDTO info = packDTO.getDeviceStatusInfo(); - log.debug("sar开机状态:" + info.getIsBoot()); + log.debug("sar开机状态:{}", info.getIsBoot()); sarJobStatusService.update(ip, info); - redisUtil.set(CacheKey.getSarConnect(ip), info, answerTimeout, TimeUnit.SECONDS); - //System.out.println(info); + String connectKey = CacheKey.getSarConnect(ip); + sarShortCache.put(connectKey, info); // 写入,自动过期 } log.debug("----------------------状态包解析完毕"); } diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarControlServiceImpl.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarControlServiceImpl.java index d0d9a44..2f207df 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarControlServiceImpl.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarControlServiceImpl.java @@ -4,18 +4,19 @@ import com.zhangy.skyeye.common.extend.util.JsonUtil; import com.zhangy.skyeye.jm.dto.JmJobDTO; import com.zhangy.skyeye.jm.dto.JmSarStatusDTO; import com.zhangy.skyeye.jm.entity.JmJobPayload; -import com.zhangy.skyeye.jm.entity.JmJobUav; import com.zhangy.skyeye.publics.consts.CacheKey; -import com.zhangy.skyeye.redis.utils.RedisUtil; +import com.zhangy.skyeye.publics.utils.CacheUtil; import com.zhangy.skyeye.sar.control.SarControlContext; import com.zhangy.skyeye.sar.dto.SarControlParamDTO; import com.zhangy.skyeye.sar.enums.SarControlTypeEnum; import com.zhangy.skyeye.sar.service.ISarControlService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.util.Optional; /** @@ -28,8 +29,17 @@ public class SarControlServiceImpl implements ISarControlService { private final SarControlContext udpSendContext; - @Autowired - private RedisUtil redisUtil; + private final CacheManager cacheManager; // final 字段 + + private Cache shortCache; + + @PostConstruct + public void init() { + this.shortCache = cacheManager.getCache("sar-short-lived"); + if (shortCache == null) { + log.error("sar-short-lived cache 未找到!"); + } + } @Override public void sendUdp(JmJobDTO job) { @@ -60,7 +70,6 @@ public class SarControlServiceImpl implements ISarControlService { }); } - @Override public void sendUdp(SarControlParamDTO param) { udpSendContext.execute(param); @@ -87,7 +96,6 @@ public class SarControlServiceImpl implements ISarControlService { @Override public JmSarStatusDTO getLatestStatus(String ip) { String connectKey = CacheKey.getSarConnect(ip); - // 从缓存取载荷状态信息 - return (JmSarStatusDTO) redisUtil.get(connectKey); + return CacheUtil.get(shortCache, connectKey, JmSarStatusDTO.class); } } diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarImageServiceImpl.java b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarImageServiceImpl.java index 62f4eb2..228160e 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarImageServiceImpl.java +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/java/com/zhangy/skyeye/sar/service/impl/SarImageServiceImpl.java @@ -1,9 +1,8 @@ package com.zhangy.skyeye.sar.service.impl; import com.zhangy.skyeye.common.extend.util.MathUtil; -import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO; import com.zhangy.skyeye.common.extend.util.ObjectUtil; -import com.zhangy.skyeye.redis.utils.RedisUtil; +import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO; import com.zhangy.skyeye.jm.dto.JmImageRotateDTO; import com.zhangy.skyeye.jm.dto.JmUavStatusDTO; import com.zhangy.skyeye.jm.entity.JmImage; @@ -11,6 +10,7 @@ import com.zhangy.skyeye.jm.service.JmImageService; import com.zhangy.skyeye.jm.service.JmJobStatusService; import com.zhangy.skyeye.publics.consts.FileTypeEnum; import com.zhangy.skyeye.publics.service.SysFileTypeService; +import com.zhangy.skyeye.publics.utils.CacheUtil; import com.zhangy.skyeye.publics.utils.ImageUtil; import com.zhangy.skyeye.publics.utils.OpenCVUtil; import com.zhangy.skyeye.sar.dto.SarBackImageFrameDTO; @@ -22,8 +22,11 @@ import lombok.extern.slf4j.Slf4j; import org.opencv.core.Mat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.io.File; import java.util.Date; import java.util.List; @@ -45,7 +48,7 @@ public class SarImageServiceImpl implements ISarImageService { private SarWsAsyncService sarWsAsyncService; @Autowired - private RedisUtil redisUtil; + private CacheManager cacheManager; // 图片最大宽度,前端说和电脑有关,4096保险点,一般是4096 8192 16384 @Value("${skyeye.sar.image.max:4096}") @@ -55,43 +58,53 @@ public class SarImageServiceImpl implements ISarImageService { private final String CACHE_FIELD_START_FRAME_NO = "startFrameNo"; // 当前帧号 private final String CACHE_FIELD_CURR_FRAME_NO = "currFrameNo"; - // 缓存超时(秒) - private final long CACHE_EXPIRE_SECOND = 24 * 3600; + + private Cache joinStateCache; + + @PostConstruct + public void initCache() { + joinStateCache = cacheManager.getCache("image-join-state"); + if (joinStateCache == null) { + log.error("缓存 image-join-state 未找到,请检查 CacheConfig"); + } + } /** * 获取基准图像信息 * - * @param airlineId 航线执行ID + * @param airlineId 航线执行ID * @param singleWidth 单条图片宽度 - * @param frameNo 当前帧号 + * @param frameNo 当前帧号 * @return 返回非空的图像信息,其字段 imageNo 一定有值 */ - private JmImage getBaseImage(Long airlineId, int singleWidth, int frameNo) {IMG_MAX_WITH=1; + private JmImage getBaseImage(Long airlineId, int singleWidth, int frameNo) { List imageList = imageService.selectLowByAirline(airlineId); - String cacheKey = "jmImgJoin-" + airlineId; - JmImage base = null; + String cachePrefix = "jmImgJoin-" + airlineId; + JmImage base; // 情况1:航线第一张图 if (ObjectUtil.isEmpty(imageList)) { base = new JmImage(); base.setImageNo(1); - redisUtil.hset(cacheKey, CACHE_FIELD_START_FRAME_NO, frameNo, CACHE_EXPIRE_SECOND); + // 存起始帧号 + joinStateCache.put(cachePrefix + ":" + CACHE_FIELD_START_FRAME_NO, frameNo); return base; } // 情况2:如果最后一张还能拼图,则直接返回继续拼 JmImage last = imageList.get(imageList.size() - 1); - Integer startFrameNo = (Integer) redisUtil.hget(cacheKey, CACHE_FIELD_START_FRAME_NO); - int currWidth = startFrameNo == null ? 0 : singleWidth * (frameNo - startFrameNo + 1); // 图宽(当前图+基准图) + Integer startFrameNo = CacheUtil.get(joinStateCache, cachePrefix + ":" + CACHE_FIELD_START_FRAME_NO, Integer.class); + int currWidth = startFrameNo == null ? 0 : singleWidth * (frameNo - startFrameNo + 1); int surplusNum = (IMG_MAX_WITH - currWidth) / singleWidth; // 还可以拼图片数 - Integer baseNo = (Integer) redisUtil.hget("jmImgJoin-" + airlineId, CACHE_FIELD_CURR_FRAME_NO); + Integer baseNo = CacheUtil.get(joinStateCache, cachePrefix + ":" + CACHE_FIELD_CURR_FRAME_NO, Integer.class); + if (startFrameNo == null || currWidth < IMG_MAX_WITH || - baseNo == null || (frameNo - baseNo + 1 <= surplusNum)) { // 当前图+填充 不能超过允许拼接数 - log.info("当前宽度:" + currWidth + " < " + IMG_MAX_WITH + " 可以继续拼接"); + baseNo == null || (frameNo - baseNo + 1 <= surplusNum)) { + log.info("当前宽度:{} < {} 可以继续拼接", currWidth, IMG_MAX_WITH); return last; } // 情况3:已经拼接到最大数量,或者当前图+填充数量超过允许拼接数量,创建新图像文件 - log.info("当前宽度:" + currWidth + " > " + IMG_MAX_WITH + " 重新拼接,当前帧号" + frameNo + "作为首帧"); + log.info("当前宽度:{} > {} 重新拼接,当前帧号{}作为首帧", currWidth, IMG_MAX_WITH, frameNo); base = new JmImage(); - redisUtil.hset(cacheKey, CACHE_FIELD_START_FRAME_NO, frameNo, CACHE_EXPIRE_SECOND); + joinStateCache.put(cachePrefix + ":" + CACHE_FIELD_START_FRAME_NO, frameNo); base.setImageNo(last.getImageNo() + 1); return base; } @@ -106,47 +119,12 @@ public class SarImageServiceImpl implements ISarImageService { } // 使用前一张图的右侧坐标作为后一张图的左侧,前提是没丢图 if (!isFirst && !lostImage) { - /*imageFrame.setLon1(before[0]); - imageFrame.setLat1(before[1]); - imageFrame.setLon4(before[2]); - imageFrame.setLat4(before[3]);*/ + // 注释部分保持原样 } before[0] = imageFrame.getLon5(); before[1] = imageFrame.getLat5(); before[2] = imageFrame.getLon8(); before[3] = imageFrame.getLat8(); - /*switch (rotateDTO.getType()) { - case 0: - case 1: - // 使用前一张图的右侧坐标作为后一张图的左侧,前提是没丢图 - if (!isFirst && !lostImage) { - imageFrame.setLon1(before[0]); - imageFrame.setLat1(before[1]); - imageFrame.setLon4(before[2]); - imageFrame.setLat4(before[3]); - } else if (before == null) { - before = new Double[4]; - currAirline.setBeforeRight(before); - } - before[0] = imageFrame.getLon5(); - before[1] = imageFrame.getLat5(); - before[2] = imageFrame.getLon8(); - before[3] = imageFrame.getLat8(); - break; - case 2: - case 3: - if (!isFirst && !lostImage) { - imageFrame.setLon5(before[0]); - imageFrame.setLat5(before[1]); - imageFrame.setLon8(before[2]); - imageFrame.setLat8(before[3]); - } - before[0] = imageFrame.getLon1(); - before[1] = imageFrame.getLat1(); - before[2] = imageFrame.getLon4(); - before[3] = imageFrame.getLat4(); - break; - } */ } /** @@ -154,8 +132,8 @@ public class SarImageServiceImpl implements ISarImageService { * * @param sourceIp * @param airlineExecId - * @param frameData 图像帧数据 - * @param imageFrame 图像帧 + * @param frameData 图像帧数据 + * @param imageFrame 图像帧 */ @Override public JmImage parseImage(String sourceIp, Long airlineExecId, byte[] frameData, SarBackImageFrameDTO imageFrame) { @@ -186,28 +164,28 @@ public class SarImageServiceImpl implements ISarImageService { } // 3.保存图像png,用航线ID+序号命名 - JmImage base = getBaseImage(airlineExecId, currImage.width(), imageFrame.getFrameNo()); - String imageName = airlineExecId + "-" + base.getImageNo() +".png"; + JmImage base = getBaseImage(airlineExecId, currImage.width(), frameNo); + String imageName = airlineExecId + "-" + base.getImageNo() + ".png"; String[] imagePath = sysFileTypeService.getFilePath(FileTypeEnum.SAR_IMAGE_LOW, jobExecId, imageName); String currPath = imagePath[0]; System.out.println("帧:" + frameNo); // 4.保存基准图(同步),用于下次拼接 - Integer baseNo = (Integer) redisUtil.hget("jmImgJoin-" + airlineExecId, CACHE_FIELD_CURR_FRAME_NO); + Integer baseNo = CacheUtil.get(joinStateCache, "jmImgJoin-" + airlineExecId + ":" + CACHE_FIELD_CURR_FRAME_NO, Integer.class); boolean lostImage = baseNo != null && (frameNo - baseNo > 1); // 判断是否丢图 String basePath = sysFileTypeService.getAbsolutePath(FileTypeEnum.SAR_IMAGE_LOW, jobExecId, - airlineExecId + "-" + base.getImageNo() +"-base.png"); + airlineExecId + "-" + base.getImageNo() + "-base.png"); Mat baseMat = generateBaseMat(base, currImage, frameNo, imageFrame.getMax(), basePath, baseNo); if (baseMat == null) { // 拼接失败 或 基准图生成失败则跳过,按丢图处理 return null; } if (lostImage) { - log.warn("丢图"+(frameNo - baseNo)+"张!当前帧" + frameNo + ",前帧" + baseNo); + log.warn("丢图{}张!当前帧{},前帧{}", (frameNo - baseNo), frameNo, baseNo); } //modCoord(imageFrame, lostImage, currAirline); - redisUtil.hset("jmImgJoin-" + airlineExecId, CACHE_FIELD_CURR_FRAME_NO, frameNo, CACHE_EXPIRE_SECOND);// 更新帧号 + joinStateCache.put("jmImgJoin-" + airlineExecId + ":" + CACHE_FIELD_CURR_FRAME_NO, frameNo); // ### 亮度调整,用于可靠udp版本图像,固定使用系数0.5 // 拆分多张图片,去掉自适应调整 if (IMG_MAX_WITH > 20000) { @@ -220,15 +198,15 @@ public class SarImageServiceImpl implements ISarImageService { // 6.更新基准图坐标和帧号 JmImage imageInfo = saveImage(uav, airlineExecId, base, imagePath, imageFrame, frameNo, lostImage); long end = System.currentTimeMillis(); - log.info("生成" + imageFrame.getImageBitDeep()+"位雷达回传图像:帧序号" + frameNo + "," + - imageInfo.getRelativePath() + ",耗时" + (end - start)/1000 + "秒"); + log.info("生成{}位雷达回传图像:帧序号{},{},耗时{}秒", + imageFrame.getImageBitDeep(), frameNo, imageInfo.getRelativePath(), (end - start) / 1000); return imageInfo; } /** * 加载回传图像,先转置再转为Mat * - * @param frameData 图像帧数据,包含参数信息和未转置的8位灰度图像数据 + * @param frameData 图像帧数据,包含参数信息和未转置的8位灰度图像数据 * @param imageFrame 图像帧对象 * @return 转置后的4通道图像Mat */ @@ -261,10 +239,10 @@ public class SarImageServiceImpl implements ISarImageService { /** * 生成基准图,将原有基准图与新图拼接 * - * @param base 基准图信息 + * @param base 基准图信息 * @param currImage 当前图 - * @param currNo 当前图的帧号 - * @param currMax 当前图最大值 + * @param currNo 当前图的帧号 + * @param currMax 当前图最大值 * @param imagePath 基准图路径 * @return */ @@ -277,7 +255,7 @@ public class SarImageServiceImpl implements ISarImageService { if (baseMax < currMax) { OpenCVUtil.multiply(baseImage, baseMax / currMax); } else if (baseMax > currMax) { - OpenCVUtil.multiply(currImage , currMax / baseMax); + OpenCVUtil.multiply(currImage, currMax / baseMax); } } Mat baseMat = ImageUtil.join(baseImage, baseNo, currImage, currNo); // 会释放 currImage baseImage 资源 @@ -291,9 +269,9 @@ public class SarImageServiceImpl implements ISarImageService { * 生成后处理图,将拼接好的基准图转置并调整对比度 * * @param currAirline 当前航线信息 - * @param baseMat 原基准图,处理后释放资源 - * @param imagePath 后处理图路径,每条航线对应一张图,每次生成会覆盖 - * @param imageLight 图像亮度倍数,0是不调整 + * @param baseMat 原基准图,处理后释放资源 + * @param imagePath 后处理图路径,每条航线对应一张图,每次生成会覆盖 + * @param imageLight 图像亮度倍数,0是不调整 */ private void generateAfterMat(JmAirlineStatusDTO currAirline, Mat baseMat, String imagePath, int imageLight) { // 后处理参数 diff --git a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/resources/application-dev.yml b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/resources/application-dev.yml index 583287c..5456dbe 100644 --- a/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/resources/application-dev.yml +++ b/backend/Skyeye-sys-dev/skyeye-service-manager/src/main/resources/application-dev.yml @@ -46,11 +46,11 @@ spring: date-format: yyyy-MM-dd'T'HH:mm:ss'Z' #redis 配置 - redis: - database: 0 - host: 127.0.0.1 - port: 6379 - password: 'P@ssw0rd' + #redis: + #database: 0 + #host: 127.0.0.1 + #port: 6379 + #password: 'P@ssw0rd' mybatis-plus: mapper-locations: classpath*:mapping/**/*Mapping.xml