修改部分循环引用

This commit is contained in:
longguancheng 2026-01-26 14:12:22 +08:00
parent dd67784d85
commit ed6b18574f
9 changed files with 163 additions and 53 deletions

View File

@ -1,15 +1,8 @@
package com.zhangy.skyeye.jm.service; package com.zhangy.skyeye.jm.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zhangy.skyeye.jm.consts.JmJobModeEnum;
import com.zhangy.skyeye.jm.dto.JmJobDTO; import com.zhangy.skyeye.jm.dto.JmJobDTO;
import com.zhangy.skyeye.jm.dto.JmJobKtyDTO;
import com.zhangy.skyeye.jm.dto.JmJobPageDTO;
import com.zhangy.skyeye.jm.dto.JmJobQueryDTO; import com.zhangy.skyeye.jm.dto.JmJobQueryDTO;
import com.zhangy.skyeye.jm.entity.JmJob;
import com.zhangy.skyeye.jm.entity.JmJobExec; import com.zhangy.skyeye.jm.entity.JmJobExec;
import com.zhangy.skyeye.jm.entity.JmJobPayload;
import com.zhangy.skyeye.jm.entity.JmJobUav;
import java.util.List; import java.util.List;

View File

@ -1,7 +1,6 @@
package com.zhangy.skyeye.jm.service; package com.zhangy.skyeye.jm.service;
import com.zhangy.skyeye.jm.entity.JmJobPayload; import com.zhangy.skyeye.jm.entity.JmJobPayload;
import com.zhangy.skyeye.jm.entity.JmJobUav;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@ -2,13 +2,10 @@ package com.zhangy.skyeye.jm.service.impl;
import com.zhangy.skyeye.common.extend.exception.ServiceException; import com.zhangy.skyeye.common.extend.exception.ServiceException;
import com.zhangy.skyeye.common.extend.util.ObjectUtil; import com.zhangy.skyeye.common.extend.util.ObjectUtil;
import com.zhangy.skyeye.jm.dto.JmJobDTO;
import com.zhangy.skyeye.jm.entity.JmAirline; import com.zhangy.skyeye.jm.entity.JmAirline;
import com.zhangy.skyeye.jm.entity.JmAirlineExec; import com.zhangy.skyeye.jm.entity.JmAirlineExec;
import com.zhangy.skyeye.jm.mapper.JmAirlineExecMapper; import com.zhangy.skyeye.jm.mapper.JmAirlineExecMapper;
import com.zhangy.skyeye.jm.mapper.JmAirlineMapper;
import com.zhangy.skyeye.jm.service.JmAirlineExecService; import com.zhangy.skyeye.jm.service.JmAirlineExecService;
import com.zhangy.skyeye.jm.service.JmAirlineService;
import com.zhangy.skyeye.publics.consts.ExecStatusEnum; import com.zhangy.skyeye.publics.consts.ExecStatusEnum;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -22,8 +19,6 @@ public class JmAirlineExecServiceImpl implements JmAirlineExecService {
@Autowired @Autowired
private JmAirlineExecMapper airlineExecMapper; private JmAirlineExecMapper airlineExecMapper;
@Autowired
private JmAirlineMapper jmAirlineMapper;
@Override @Override
public List<JmAirline> selectByJobExec(Long... jobId) { public List<JmAirline> selectByJobExec(Long... jobId) {

View File

@ -13,6 +13,7 @@ import com.zhangy.skyeye.jm.entity.JmImage;
import com.zhangy.skyeye.jm.entity.JmImageItem; import com.zhangy.skyeye.jm.entity.JmImageItem;
import com.zhangy.skyeye.jm.entity.JmJobPayload; import com.zhangy.skyeye.jm.entity.JmJobPayload;
import com.zhangy.skyeye.jm.mapper.JmImageMapper; import com.zhangy.skyeye.jm.mapper.JmImageMapper;
import com.zhangy.skyeye.jm.mapper.JmJobPayloadMapper;
import com.zhangy.skyeye.jm.service.*; import com.zhangy.skyeye.jm.service.*;
import com.zhangy.skyeye.publics.consts.FileStoreTypeEnum; import com.zhangy.skyeye.publics.consts.FileStoreTypeEnum;
import com.zhangy.skyeye.publics.consts.FileTypeEnum; import com.zhangy.skyeye.publics.consts.FileTypeEnum;
@ -49,7 +50,7 @@ public class JmImageServiceImpl implements JmImageService {
private IPyImageService detectService; private IPyImageService detectService;
@Autowired @Autowired
private JmJobPayloadService jobPayloadService; private JmJobPayloadMapper jobPayloadMapper;
@Autowired @Autowired
private ISysFileService fileService; private ISysFileService fileService;
@ -223,7 +224,7 @@ public class JmImageServiceImpl implements JmImageService {
jobExecId = jobExecDTO.getExecId(); jobExecId = jobExecDTO.getExecId();
fileType = FileTypeEnum.SAR_IMAGE_HIGH; fileType = FileTypeEnum.SAR_IMAGE_HIGH;
srcFileType = FileTypeEnum.SAR_IMAGE_HIGH_SRC; srcFileType = FileTypeEnum.SAR_IMAGE_HIGH_SRC;
JmJobPayload sar = jobPayloadService.selectSar(jobId, uavId); JmJobPayload sar = jobPayloadMapper.selectSar(jobId, uavId);
if (sar == null) { if (sar == null) {
throw ServiceException.noLog("找不到该任务的SAR载荷"); throw ServiceException.noLog("找不到该任务的SAR载荷");
} }

View File

@ -2,9 +2,7 @@ package com.zhangy.skyeye.jm.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.zhangy.skyeye.common.extend.exception.ServiceException; import com.zhangy.skyeye.common.extend.exception.ServiceException;
import com.zhangy.skyeye.common.extend.util.FileUtil;
import com.zhangy.skyeye.common.extend.util.ObjectUtil; import com.zhangy.skyeye.common.extend.util.ObjectUtil;
import com.zhangy.skyeye.device.service.IPayloadService;
import com.zhangy.skyeye.jm.dto.JmJobDTO; import com.zhangy.skyeye.jm.dto.JmJobDTO;
import com.zhangy.skyeye.jm.dto.JmJobQueryDTO; import com.zhangy.skyeye.jm.dto.JmJobQueryDTO;
import com.zhangy.skyeye.jm.entity.JmAirlineExec; import com.zhangy.skyeye.jm.entity.JmAirlineExec;
@ -13,10 +11,11 @@ import com.zhangy.skyeye.jm.entity.JmJobPoint;
import com.zhangy.skyeye.jm.entity.JmJobUav; import com.zhangy.skyeye.jm.entity.JmJobUav;
import com.zhangy.skyeye.jm.event.JmJobStatusInitEvent; import com.zhangy.skyeye.jm.event.JmJobStatusInitEvent;
import com.zhangy.skyeye.jm.mapper.JmJobExecMapper; import com.zhangy.skyeye.jm.mapper.JmJobExecMapper;
import com.zhangy.skyeye.jm.service.*; import com.zhangy.skyeye.jm.service.JmAirlineExecService;
import com.zhangy.skyeye.jm.service.JmJobExecService;
import com.zhangy.skyeye.jm.service.JmJobPointService;
import com.zhangy.skyeye.jm.service.JmJobUavService;
import com.zhangy.skyeye.publics.consts.ExecStatusEnum; import com.zhangy.skyeye.publics.consts.ExecStatusEnum;
import com.zhangy.skyeye.publics.consts.FileTypeEnum;
import com.zhangy.skyeye.publics.service.SysFileTypeService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
@ -32,8 +31,6 @@ import java.util.stream.Collectors;
@Service @Service
public class JmJobExecServiceImpl implements JmJobExecService { public class JmJobExecServiceImpl implements JmJobExecService {
@Autowired
private JmJobStatusService jobStatusService;
@Autowired @Autowired
private JmJobExecMapper jobExecMapper; private JmJobExecMapper jobExecMapper;
@Autowired @Autowired
@ -42,16 +39,9 @@ public class JmJobExecServiceImpl implements JmJobExecService {
private JmJobPointService jobPointService; private JmJobPointService jobPointService;
@Autowired @Autowired
private JmJobUavService jobUavService; private JmJobUavService jobUavService;
@Autowired
private IPayloadService payloadService;
@Autowired @Autowired
private ApplicationEventPublisher eventPublisher; private ApplicationEventPublisher eventPublisher;
@Autowired
private SysFileTypeService fileTypeService;
@Override @Override
public void initExecutingJobs() { public void initExecutingJobs() {
List<JmJobDTO> executingJobs = this.selectWorking(); List<JmJobDTO> executingJobs = this.selectWorking();
@ -183,7 +173,6 @@ public class JmJobExecServiceImpl implements JmJobExecService {
@Transactional @Transactional
@Override @Override
public void deleteByJobConf(Long... jobConfId) { public void deleteByJobConf(Long... jobConfId) {
Long[] jobExecIds = jobExecMapper.selectByConf(jobConfId).stream().map(e -> e.getId()).toArray(Long[]::new);
jmAirlineExecService.deleteByJob(jobConfId); jmAirlineExecService.deleteByJob(jobConfId);
jobExecMapper.deleteByConf(jobConfId); jobExecMapper.deleteByConf(jobConfId);
} }

View File

@ -38,9 +38,9 @@ public class JmJobPayloadServiceImpl implements JmJobPayloadService {
if (ObjectUtil.isEmpty(jobExecList)) { if (ObjectUtil.isEmpty(jobExecList)) {
return list; return list;
} }
Long[] jobExecIds = jobExecList.stream().map(j -> j.getExecId()).distinct().toArray(Long[]::new); Long[] jobExecIds = jobExecList.stream().map(JmJobDTO::getExecId).distinct().toArray(Long[]::new);
// jobExecList 按照时间倒序排列若有一个任务配置对应多个任务执行时取第一个元素为最新的执行数据 // jobExecList 按照时间倒序排列若有一个任务配置对应多个任务执行时取第一个元素为最新的执行数据
Map<Long, Long> jobConfExecIdMap = jobExecList.stream().collect(Collectors.toMap(j -> j.getConfId(), j -> j.getExecId(), (a, b) -> a)); Map<Long, Long> jobConfExecIdMap = jobExecList.stream().collect(Collectors.toMap(JmJobDTO::getConfId, JmJobDTO::getExecId, (a, b) -> a));
// 图片jobId不应该用confId // 图片jobId不应该用confId
Map<Long, Map<Long, List<JmImage>>> imageGroup = sarImageService.selectByJob(FileTypeEnum.SAR_IMAGE_LOW, jobExecIds) Map<Long, Map<Long, List<JmImage>>> imageGroup = sarImageService.selectByJob(FileTypeEnum.SAR_IMAGE_LOW, jobExecIds)
.stream() .stream()
@ -86,15 +86,16 @@ public class JmJobPayloadServiceImpl implements JmJobPayloadService {
@Override @Override
public List<JmJobPayload> selectByUav(Long jobId, Long uavId) { public List<JmJobPayload> selectByUav(Long jobId, Long uavId) {
Map<Long, List<JmImage>> imageGroup = sarImageService.selectByUav(FileTypeEnum.SAR_IMAGE_LOW, jobId, uavId) // 没用到
.stream() // Map<Long, List<JmImage>> imageGroup = sarImageService.selectByUav(FileTypeEnum.SAR_IMAGE_LOW, jobId, uavId)
.collect(Collectors.groupingBy(JmImage::getPayloadId)); // .stream()
List<JmJobPayload> list = jobPayloadMapper.selectByUav(jobId, uavId); // .collect(Collectors.groupingBy(JmImage::getPayloadId));
list.forEach(e -> { // List<JmJobPayload> list = jobPayloadMapper.selectByUav(jobId, uavId);
Long payloadId = e.getPayloadId(); // list.forEach(e -> {
e.setImageList(imageGroup.containsKey(payloadId) ? imageGroup.get(payloadId) : Collections.EMPTY_LIST); // Long payloadId = e.getPayloadId();
}); // e.setImageList(imageGroup.containsKey(payloadId) ? imageGroup.get(payloadId) : Collections.EMPTY_LIST);
return list; // });
return jobPayloadMapper.selectByUav(jobId, uavId);
} }
@Override @Override

View File

@ -0,0 +1,34 @@
package com.zhangy.skyeye.sar.context;
import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO;
import com.zhangy.skyeye.jm.dto.JmUavStatusDTO;
/**
* @PROJECT_NAME: skyeyesystem
* @DESCRIPTION: SAR 回传相关任务上下文提供者 用于打破 SarBackWsServiceImpl JmJobStatusService 的直接依赖
* @AUTHOR: GuanCheng Long
* @DATE: 2026/1/21 1:10
*/
public interface SarTaskContextProvider {
/**
* 根据载荷 IP 获取当前无人机状态
*/
JmUavStatusDTO getCurrentUav(String payloadIp);
/**
* 根据载荷 IP 获取当前航线状态
*/
JmAirlineStatusDTO getCurrentAirline(String payloadIp);
/**
* 获取当前任务执行 ID
*/
Long getCurrentJobExecId(String payloadIp);
/**
* 获取当前任务配置 ID
*/
Long getCurrentJobId(String payloadIp);
}

View File

@ -0,0 +1,104 @@
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
*
*/
/**
* @PROJECT_NAME: skyeyesystem
* @DESCRIPTION: SAR 任务上下文提供者实现基于 Redis 缓存避免循环依赖
* - JmJobStatusServiceImpl 在更新状态时主动把 JmUavStatusDTO 推送到 Redis
* - 此类只从 Redis 读取不注入 JmJobStatusService
* @AUTHOR: GuanCheng Long
* @DATE: 2026/1/21 1:10
*/
@Slf4j
@Component
public class SarTaskContextProviderImpl implements SarTaskContextProvider {
@Autowired
private RedisUtil redisUtil;
// Redis 键前缀
private static final String UAV_STATUS_KEY_PREFIX = "sar:context:uav:";
// 缓存过期时间
private static final long CACHE_EXPIRE_SECONDS = 600; // 10 分钟
@Override
public JmUavStatusDTO getCurrentUav(String payloadIp) {
if (payloadIp == null || payloadIp.trim().isEmpty()) {
log.warn("获取 uav 状态失败payloadIp 为空");
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;
}
@Override
public JmAirlineStatusDTO getCurrentAirline(String payloadIp) {
JmUavStatusDTO uav = getCurrentUav(payloadIp);
if (uav == null) {
return null;
}
return uav.getCurrAirline();
}
@Override
public Long getCurrentJobExecId(String payloadIp) {
JmUavStatusDTO uav = getCurrentUav(payloadIp);
return uav != null ? uav.getJobExecId() : null;
}
@Override
public Long getCurrentJobId(String payloadIp) {
JmAirlineStatusDTO airline = getCurrentAirline(payloadIp);
return airline != null ? airline.getJobId() : null;
}
/**
* 更新/刷新缓存 JmJobStatusServiceImpl 调用
* 在状态更新成功后调用此方法
*/
public void updateUavStatus(String payloadIp, JmUavStatusDTO uavStatus) {
if (payloadIp == null || uavStatus == null) {
log.warn("更新 uav 状态失败参数为空ip={}, status={}", payloadIp, uavStatus);
return;
}
String key = UAV_STATUS_KEY_PREFIX + payloadIp;
try {
// 设置值 + 过期时间
redisUtil.set(key, uavStatus, CACHE_EXPIRE_SECONDS);
log.debug("已更新 Redis 缓存key={}, jobExecId={}", key, uavStatus.getJobExecId());
} catch (Exception e) {
log.error("更新 SAR uav 状态缓存失败ip={}", payloadIp, e);
}
}
/**
* 清理某个 IP 的缓存任务结束或异常时调用
*/
public void clearUavStatus(String payloadIp) {
if (payloadIp == null) {
return;
}
String key = UAV_STATUS_KEY_PREFIX + payloadIp;
redisUtil.del(key);
log.debug("SAR uav 缓存已标记清理(或自然过期):{}", key);
}
}

View File

@ -3,13 +3,11 @@ package com.zhangy.skyeye.sar.service.impl;
import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO; import com.zhangy.skyeye.jm.dto.JmAirlineStatusDTO;
import com.zhangy.skyeye.jm.dto.JmUavStatusDTO; import com.zhangy.skyeye.jm.dto.JmUavStatusDTO;
import com.zhangy.skyeye.jm.entity.JmImage; import com.zhangy.skyeye.jm.entity.JmImage;
import com.zhangy.skyeye.jm.service.JmJobStatusService;
import com.zhangy.skyeye.publics.consts.WebSocketKey; import com.zhangy.skyeye.publics.consts.WebSocketKey;
import com.zhangy.skyeye.publics.service.SysFileTypeService; import com.zhangy.skyeye.sar.context.SarTaskContextProvider;
import com.zhangy.skyeye.sar.dto.JmSarWaveWsDTO; import com.zhangy.skyeye.sar.dto.JmSarWaveWsDTO;
import com.zhangy.skyeye.sar.dto.SarBackWaveFrameDTO; import com.zhangy.skyeye.sar.dto.SarBackWaveFrameDTO;
import com.zhangy.skyeye.sar.service.ISarBackWsService; import com.zhangy.skyeye.sar.service.ISarBackWsService;
import com.zhangy.skyeye.sar.service.SarWsAsyncService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.SimpMessagingTemplate;
@ -33,13 +31,7 @@ public class SarBackWsServiceImpl implements ISarBackWsService {
private SimpMessagingTemplate simpMessageingTemplate; private SimpMessagingTemplate simpMessageingTemplate;
@Autowired @Autowired
private SysFileTypeService sysFileTypeService; private SarTaskContextProvider taskContextProvider;
@Autowired
private JmJobStatusService jobStatusService;
@Autowired
private SarWsAsyncService sarWsAsyncService;
@Override @Override
public void sendWave(String payloadIp, SarBackWaveFrameDTO frame, byte[] frameData) { public void sendWave(String payloadIp, SarBackWaveFrameDTO frame, byte[] frameData) {
@ -63,12 +55,14 @@ public class SarBackWsServiceImpl implements ISarBackWsService {
* @return * @return
*/ */
private JmSarWaveWsDTO loadJobDetail(String payloadIp, JmSarWaveWsDTO ws, byte[] frameData) { private JmSarWaveWsDTO loadJobDetail(String payloadIp, JmSarWaveWsDTO ws, byte[] frameData) {
JmUavStatusDTO uav = jobStatusService.getCurrUav(payloadIp); JmUavStatusDTO uav = taskContextProvider.getCurrentUav(payloadIp);
if (uav == null) { // 如果没有执行中的任务则忽略 if (uav == null) { // 如果没有执行中的任务则忽略
log.debug("IP={} 无正在执行的任务,忽略波形推送", payloadIp);
return null; return null;
} }
JmAirlineStatusDTO airlineStatusVo = uav.getCurrAirline(); JmAirlineStatusDTO airlineStatusVo = uav.getCurrAirline();
if (airlineStatusVo == null) { if (airlineStatusVo == null) {
log.debug("IP={} 无当前航线,忽略波形推送", payloadIp);
return null; return null;
} }
long jobConfId = airlineStatusVo.getJobId(); long jobConfId = airlineStatusVo.getJobId();