feat(streamProxy): 实现camera_code自动生成和查询逻辑

核心变更:
1. 新增 generateCameraCode() 方法:生成格式为 cam_xxxxxxxxxxxx 的唯一编码
2. 修改 add() 方法:
   - 自动生成 camera_code 并设置 app = camera_code
   - 实现重试机制(最多3次)处理唯一键冲突
   - 确保 ZLM URL 路径为纯 ASCII,避免中文编码问题
3. 实现 getStreamProxyByCameraCode() 方法:根据 camera_code 查询代理对象

技术细节:
- 添加 UUID 和 DuplicateKeyException 依赖
- 使用事务确保数据一致性
- 空值检查防止空指针异常

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 11:02:12 +08:00
parent 754677e11d
commit 3792a30616

View File

@@ -29,6 +29,7 @@ import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@@ -41,6 +42,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* 视频代理业务
@@ -73,6 +75,15 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
@Autowired
TransactionDefinition transactionDefinition;
/**
* 生成唯一的 camera_code
* 格式cam_xxxxxxxxxxxx12位随机字符
* @return 唯一的 camera_code
*/
private String generateCameraCode() {
return "cam_" + UUID.randomUUID().toString().replace("-", "").substring(0, 12);
}
/**
* 流到来的处理
*/
@@ -143,14 +154,33 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if (streamProxyInDb != null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "APP+STREAM已经存在");
}
if (streamProxy.getGbDeviceId() != null) {
gbChannelService.add(streamProxy.buildCommonGBChannel());
// 自动生成 camera_code最多重试3次避免冲突
int retryCount = 0;
while (retryCount < 3) {
String cameraCode = generateCameraCode();
streamProxy.setCameraCode(cameraCode);
// 强制设置 app = camera_code确保 ZLM URL 纯 ASCII
streamProxy.setApp(cameraCode);
streamProxy.setCreateTime(DateUtil.getNow());
streamProxy.setUpdateTime(DateUtil.getNow());
try {
if (streamProxy.getGbDeviceId() != null) {
gbChannelService.add(streamProxy.buildCommonGBChannel());
}
streamProxyMapper.add(streamProxy);
streamProxy.setDataType(ChannelDataType.STREAM_PROXY);
streamProxy.setDataDeviceId(streamProxy.getId());
return;
} catch (DuplicateKeyException e) {
retryCount++;
if (retryCount >= 3) {
throw new RuntimeException("生成 camera_code 失败,请重试");
}
}
}
streamProxy.setCreateTime(DateUtil.getNow());
streamProxy.setUpdateTime(DateUtil.getNow());
streamProxyMapper.add(streamProxy);
streamProxy.setDataType(ChannelDataType.STREAM_PROXY);
streamProxy.setDataDeviceId(streamProxy.getId());
}
@Override
@@ -380,4 +410,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
return streamProxyMapper.select(id);
}
@Override
public StreamProxy getStreamProxyByCameraCode(String cameraCode) {
if (ObjectUtils.isEmpty(cameraCode)) {
return null;
}
return streamProxyMapper.selectByCameraCode(cameraCode);
}
}