diff --git a/src/main/java/com/platform/config/CorsConfig.java b/src/main/java/com/platform/config/CorsConfig.java index d327719..9b0c84f 100644 --- a/src/main/java/com/platform/config/CorsConfig.java +++ b/src/main/java/com/platform/config/CorsConfig.java @@ -36,6 +36,4 @@ public class CorsConfig extends WebMvcConfigurerAdapter { return new CorsFilter(urlBasedCorsConfigurationSource); } - - } diff --git a/src/main/java/com/platform/config/MybatisPlusConfig.java b/src/main/java/com/platform/config/MybatisPlusConfig.java index 8a37a9e..0a724fd 100644 --- a/src/main/java/com/platform/config/MybatisPlusConfig.java +++ b/src/main/java/com/platform/config/MybatisPlusConfig.java @@ -69,6 +69,10 @@ public class MybatisPlusConfig implements ApplicationRunner { return new LongValue(tenantId.toString()); } } catch (Exception e) {//处理定时任务 + // 如果是定时任务,手动设置租户 ID + if (isScheduledTaskContext()) { // <-- 自定义判断逻辑 + return new LongValue(1L); // <-- 返回系统默认租户 ID + } logger.warn("未登录获取不到 SecurityManager {}", e.getMessage()); } return null; @@ -116,4 +120,13 @@ public class MybatisPlusConfig implements ApplicationRunner { List tableNames = sysSchemaService.queryTableNames(properties.getColumnName()); tables.addAll(tableNames); } + + /** + * 判断当前是否在定时任务上下文中 + */ + private boolean isScheduledTaskContext() { + // 通过线程名称或自定义标记判断(根据实际任务线程池配置调整) + return Thread.currentThread().getName().startsWith("pool-") + || Thread.currentThread().getName().contains("scheduler"); + } } diff --git a/src/main/java/com/platform/config/ShiroConfig.java b/src/main/java/com/platform/config/ShiroConfig.java index 004e263..e958cb6 100644 --- a/src/main/java/com/platform/config/ShiroConfig.java +++ b/src/main/java/com/platform/config/ShiroConfig.java @@ -103,6 +103,11 @@ public class ShiroConfig { filterMap.put("/trtc/**", "anon"); filterMap.put("/websocket/**", "anon"); filterMap.put("/**", "oauth2"); + + //APP详细 + filterMap.put("/live/merge/detail/", "anon"); + + shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; diff --git a/src/main/java/com/platform/modules/foreign/dto/AppSearchDto.java b/src/main/java/com/platform/modules/foreign/dto/AppSearchDto.java index 9068f64..11d78bb 100644 --- a/src/main/java/com/platform/modules/foreign/dto/AppSearchDto.java +++ b/src/main/java/com/platform/modules/foreign/dto/AppSearchDto.java @@ -11,13 +11,13 @@ import java.util.List; @Data public class AppSearchDto { private String liveDesc; + private Integer timeState; private Date startTime; private Date endTime; private String channelName; private List channelNameList; private Integer page; private Integer size; - public List getChannelNameList() { if(StringUtils.isBlank(channelName)) { return Collections.emptyList(); diff --git a/src/main/java/com/platform/modules/job/config/ScheduleConfig.java b/src/main/java/com/platform/modules/job/config/ScheduleConfig.java index 6d85321..2160abe 100644 --- a/src/main/java/com/platform/modules/job/config/ScheduleConfig.java +++ b/src/main/java/com/platform/modules/job/config/ScheduleConfig.java @@ -33,7 +33,7 @@ public class ScheduleConfig { prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); - prop.put("org.quartz.jobStore.misfireThreshold", "12000"); + prop.put("org.quartz.jobStore.misfireThreshold", "60000"); prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); factory.setQuartzProperties(prop); diff --git a/src/main/java/com/platform/modules/live/controller/ClipController.java b/src/main/java/com/platform/modules/live/controller/ClipController.java new file mode 100644 index 0000000..f13e822 --- /dev/null +++ b/src/main/java/com/platform/modules/live/controller/ClipController.java @@ -0,0 +1,71 @@ +package com.platform.modules.live.controller; + +import io.swagger.models.auth.In; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +// ① 控制器类 +@Slf4j +@RestController +public class ClipController { + private final Map emitters = new ConcurrentHashMap<>(); + + + @GetMapping(value = "/status-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) + public SseEmitter streamTranscodingStatus(@RequestParam String sceneId) { + SseEmitter emitter = new SseEmitter(3L * 60 * 60 * 1000); + + // 直接发送单次事件(关键修改点) + try { + emitter.send( + SseEmitter.event() + // .id("CONNECT_EVENT") // 可选:给事件添加ID + // 事件名称 + .name("Connect") + // 核心数据(会按SSE规范自动包装) + .data("建立连接成功!") + ); + } catch (IOException e) { + emitter.completeWithError(e); + } + + // 维护连接池(根据业务需求调整) + emitters.put(sceneId, emitter); + + // 清理逻辑 + emitter.onCompletion(() -> emitters.remove(sceneId, emitter)); + emitter.onTimeout(() -> { + emitters.remove(sceneId, emitter); + emitter.complete(); + }); + + return emitter; + } + + // ④ 推送剪辑完成事件(在其他服务中调用) + public void sendClipFinishedEvent(Integer videoId) { + emitters.forEach((clientId, emitter) -> { + try { + // 直接构建 String 消息(示例使用 JSON 格式) + String message = String.format("{\"videoId\":\"%s\"} \"message\":\"已经完成剪辑\"", videoId); + + emitter.send(SseEmitter.event() + .name("clip_finished") // 事件名称 + .data(message) // 直接发送 String + ); + } catch (IOException e) { + log.error("剪辑回调失败"); + } + }); + } +} diff --git a/src/main/java/com/platform/modules/live/controller/LiveChannelController.java b/src/main/java/com/platform/modules/live/controller/LiveChannelController.java index 1494cb2..517702d 100644 --- a/src/main/java/com/platform/modules/live/controller/LiveChannelController.java +++ b/src/main/java/com/platform/modules/live/controller/LiveChannelController.java @@ -1,10 +1,8 @@ package com.platform.modules.live.controller; import java.util.Date; -import java.util.HashMap; import java.util.Map; -import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.platform.modules.live.entity.LiveChannelComponentEntity; import com.platform.modules.live.service.LiveChannelTenantService; import com.platform.modules.live.service.impl.LiveChannelComponentServiceImpl; @@ -192,11 +190,12 @@ public class LiveChannelController extends AbstractController{ /** * 查询现场大屏和栏目封装 + * * @return 集合 */ @PostMapping("/appView") - public HashMap appView() { - return liveChannelService.appView(); + public R appView() { + return R.ok().put("appView",liveChannelService.appView()); } /** diff --git a/src/main/java/com/platform/modules/live/controller/LiveMultimediaController.java b/src/main/java/com/platform/modules/live/controller/LiveMultimediaController.java index 82c6039..d006a29 100644 --- a/src/main/java/com/platform/modules/live/controller/LiveMultimediaController.java +++ b/src/main/java/com/platform/modules/live/controller/LiveMultimediaController.java @@ -36,9 +36,9 @@ import springfox.documentation.annotations.ApiIgnore; /** * 素材信息 - * + * * @author weiyan - * @email + * @email * @date 2019-03-12 10:09:03 */ @RestController @@ -68,7 +68,7 @@ public class LiveMultimediaController extends AbstractController{ PageUtils page = liveMultimediaService.queryPageByParams(params); return R.ok().put("page", page); } - + /** * 列表 */ @@ -87,7 +87,7 @@ public class LiveMultimediaController extends AbstractController{ PageUtils page = liveMultimediaService.queryPageByParams(params); return R.ok().put("page", page); } - + @GetMapping("/common/saveToLocal") @ApiOperation(value = "保存到本地") public R saveToLocal(String videoUrl,String title, HttpServletResponse response) { @@ -97,7 +97,7 @@ public class LiveMultimediaController extends AbstractController{ liveMultimediaService.saveToLocal(videoUrl,title,response); return R.ok(); } - + /** * 信息 */ @@ -107,7 +107,7 @@ public class LiveMultimediaController extends AbstractController{ public R info(@RequestParam("id") Integer id){ return R.ok().put("info", liveMultimediaService.info(id)); } - + /** * 根据mediaId查询素材信息 */ @@ -117,7 +117,7 @@ public class LiveMultimediaController extends AbstractController{ public R getInfoByMediaId(@RequestParam("mediaId") String mediaId){ return R.ok().put("info", liveMultimediaService.getInfoByMediaId(mediaId)); } - + /** * 保存 */ @@ -125,8 +125,12 @@ public class LiveMultimediaController extends AbstractController{ @PostMapping("/save") @RequiresPermissions("live:multimedia:save") @ApiOperation("保存素材") - public R save(@ModelAttribute LiveMultimediaEntity liveMultimedia, MultipartFile mediaFile){ - return R.ok().put("info", liveMultimediaService.save(liveMultimedia, mediaFile, getUserId())); + public R save(@ModelAttribute LiveMultimediaEntity liveMultimedia, MultipartFile mediaFile,@RequestParam(value = "limitSize", required = false, defaultValue = "500")Long limitSize){ + + if(limitSize * 1024 <= mediaFile.getSize()){ + return R.error("图片大小必须控制在" + limitSize + "之内!"); + } + return R.ok().put("info", liveMultimediaService.save(liveMultimedia, mediaFile, getUserId())); } /** @@ -148,7 +152,7 @@ public class LiveMultimediaController extends AbstractController{ // 线程处理 liveMultimediaSyncService.uploadMediaSync(identifier, filepath, (Integer) data.get("id")); return R.ok().put("info", data); - + } /** @@ -162,7 +166,7 @@ public class LiveMultimediaController extends AbstractController{ liveMultimediaService.update(liveMultimedia, getUserId()); return R.ok(); } - + /** * 删除 */ diff --git a/src/main/java/com/platform/modules/live/controller/MediaUploadController.java b/src/main/java/com/platform/modules/live/controller/MediaUploadController.java index 68143de..84dc0aa 100644 --- a/src/main/java/com/platform/modules/live/controller/MediaUploadController.java +++ b/src/main/java/com/platform/modules/live/controller/MediaUploadController.java @@ -114,7 +114,7 @@ public class MediaUploadController { @PostMapping("/common/upload_media/chunk") @RequiresPermissions(value = {"live:multimedia:save", "live:multimedia:update"}, logical = Logical.OR) - public R uploadChunk(PlmChunkEntity chunk,@RequestParam(value = "limitSize", required = false, defaultValue = "500")Long limitSize) { + public R uploadChunk(PlmChunkEntity chunk,@RequestParam(value = "limitSize", required = true)Long limitSize) { if (null == chunk || null == chunk.getFile() || StringUtils.isBlank(chunk.getIdentifier()) || null == chunk.getChunkNumber()) { return R.error("缺少必要参数"); diff --git a/src/main/java/com/platform/modules/live/dto/ChannelDTO.java b/src/main/java/com/platform/modules/live/dto/ChannelDTO.java index 92b31b9..a08fbad 100644 --- a/src/main/java/com/platform/modules/live/dto/ChannelDTO.java +++ b/src/main/java/com/platform/modules/live/dto/ChannelDTO.java @@ -1,5 +1,6 @@ package com.platform.modules.live.dto; +import com.platform.modules.live.entity.LiveSceneEntity; import lombok.Data; import java.util.List; @@ -10,6 +11,10 @@ public class ChannelDTO { private String componentType; // 组件类型 private Integer componentCount; // 组件数量 private String titleSetting; + private Integer priority; + private Integer isDisplay; + private String componentLayout; + private String identify; private List liveScenes; } diff --git a/src/main/java/com/platform/modules/live/service/impl/LiveChannelServiceImpl.java b/src/main/java/com/platform/modules/live/service/impl/LiveChannelServiceImpl.java index bf84265..8fcffa0 100644 --- a/src/main/java/com/platform/modules/live/service/impl/LiveChannelServiceImpl.java +++ b/src/main/java/com/platform/modules/live/service/impl/LiveChannelServiceImpl.java @@ -4,6 +4,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import com.baomidou.mybatisplus.mapper.Wrapper; import com.platform.modules.live.constants.SceneConstants; import com.platform.modules.live.dto.ChannelDTO; import com.platform.modules.live.dto.LiveSceneDTO; @@ -11,6 +12,8 @@ import com.platform.modules.live.entity.LiveChannelComponentEntity; import com.platform.modules.live.entity.LiveSceneChannelEntity; import com.platform.modules.live.entity.LiveSceneEntity; import com.platform.modules.live.service.LiveSceneService; +import com.platform.modules.live.utils.ForeignProperties; +import com.platform.modules.plm.util.MaterialUtils; import com.platform.modules.sys.dao.SysConfigDao; import com.platform.modules.sys.entity.SysConfigEntity; import com.platform.modules.sys.service.impl.SysConfigServiceImpl; @@ -20,6 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanInfoFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.mapper.EntityWrapper; @@ -55,6 +59,9 @@ public class LiveChannelServiceImpl extends ServiceImpl params){ @@ -365,6 +372,8 @@ private LiveChannelDao liveChannelDao; @Override public HashMap appView() { + + HashMap map = new HashMap<>(); //1.查询轮播大图 @@ -384,7 +393,13 @@ private LiveChannelDao liveChannelDao; map.put("carouselScene", liveScenes); // 2.按照栏目封装现场 - List channelEntities = liveChannelService.selectList(null); + Wrapper wrapper = new EntityWrapper() + .eq("is_delete", 0) + .eq("is_display", 1) + .orderBy("priority", false); + + + List channelEntities = liveChannelService.selectList(wrapper); List collect = channelEntities.stream().map(this::convertToB).collect(Collectors.toList()); // 为每个 ChannelDTO 获取 liveScenes if(CollectionUtils.isNotEmpty(collect)){ @@ -421,6 +436,7 @@ private LiveChannelDao liveChannelDao; //2.将所有查询到的现场的channel_display字段设置为true liveSceneEntities.forEach(liveSceneEntity -> { liveChannelDao.updateChannelDisplay(liveSceneEntity.getId()); + liveSceneEntity.setTitleImage( MaterialUtils.getMaterialUrl(liveSceneEntity.getTitleImage(), foreignProperties.getMediaurl())); }); } @@ -490,6 +506,10 @@ private LiveChannelDao liveChannelDao; channelDTO.setComponentCount(a.getComponentCount()); channelDTO.setComponentType(a.getComponentType()); channelDTO.setTitleSetting(a.getTitleSetting()); + channelDTO.setPriority(a.getPriority()); + channelDTO.setIsDisplay(a.getIsDisplay()); + channelDTO.setComponentLayout(a.getComponentLayout()); + channelDTO.setIdentify(a.getIdentify()); return channelDTO; } } diff --git a/src/main/java/com/platform/modules/live/service/impl/LiveMultimediaServiceImpl.java b/src/main/java/com/platform/modules/live/service/impl/LiveMultimediaServiceImpl.java index e5ef194..1f04590 100644 --- a/src/main/java/com/platform/modules/live/service/impl/LiveMultimediaServiceImpl.java +++ b/src/main/java/com/platform/modules/live/service/impl/LiveMultimediaServiceImpl.java @@ -15,6 +15,7 @@ import java.util.*; import javax.servlet.http.HttpServletResponse; import com.aliyuncs.vod.model.v20170321.*; +import com.platform.modules.live.controller.ClipController; import com.platform.plugs.live.handlers.IVideoClipsHandler; import io.swagger.models.auth.In; import org.apache.commons.lang3.StringUtils; @@ -105,6 +106,9 @@ public class LiveMultimediaServiceImpl extends ServiceImpl page = this.selectPage( new Query(params).getPage(), wrapper diff --git a/src/main/java/com/platform/modules/live/service/impl/LiveSceneServiceImpl.java b/src/main/java/com/platform/modules/live/service/impl/LiveSceneServiceImpl.java index 44de03b..cb46e1a 100644 --- a/src/main/java/com/platform/modules/live/service/impl/LiveSceneServiceImpl.java +++ b/src/main/java/com/platform/modules/live/service/impl/LiveSceneServiceImpl.java @@ -2446,7 +2446,8 @@ public class LiveSceneServiceImpl extends ServiceImpl entityList = liveSceneChannelService.selectList( - new EntityWrapper().eq("channel_id", cid).in("scene_id", sceneIds) + new EntityWrapper() + .in("scene_id", sceneIds) ); if (null == entityList || entityList.size() == 0) @@ -2767,14 +2768,17 @@ public class LiveSceneServiceImpl extends ServiceImpl wrapper = new EntityWrapper<>(); + wrapper.eq("is_auto_live", SceneConstants.IsAutoLive.OPEN) + .eq("delete_flag", SceneConstants.IsDelete.NOTISDELETE) + .eq("scene_state", SceneConstants.SCENE_PROD) + .andNew("(live_state = {0} AND live_start <= {1}) OR (live_state = {2} AND live_end <= {3})", + SceneConstants.LIVE_STATE_NOTICE, new Date(), + SceneConstants.LIVE_STATE_DIRECT, new Date() + ); //改为数据库查询 - List liveSceneEntityList = this.baseMapper.selectList(new EntityWrapper() - .eq("is_auto_live", SceneConstants.IsAutoLive.OPEN) - .eq("delete_flag",SceneConstants.IsDelete.NOTISDELETE).eq("scene_state", SceneConstants.SCENE_PROD) - .eq("live_state", SceneConstants.LIVE_STATE_NOTICE).le("live_start", localDateTimePlusOne) - .or().eq("is_auto_live", SceneConstants.IsAutoLive.OPEN) - .eq("delete_flag",SceneConstants.IsDelete.NOTISDELETE).eq("scene_state", SceneConstants.SCENE_PROD) - .eq("live_state", SceneConstants.LIVE_STATE_DIRECT).le("live_end", localDateTime)); + List liveSceneEntityList = this.baseMapper.selectList(wrapper); List result = new ArrayList<>(); if (CollectionUtil.isNotEmpty(liveSceneEntityList)) { @@ -2933,6 +2937,16 @@ public class LiveSceneServiceImpl extends ServiceImpl appSearch(AppSearchDto appSearchDto) { Page page = new Page<>(appSearchDto.getPage(), appSearchDto.getSize()); + + // 筛选一天(例如,获取昨天的日期) + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + + if(appSearchDto.getTimeState() ==1 || appSearchDto.getTimeState() ==7 || appSearchDto.getTimeState() ==30) { + calendar.add(Calendar.DAY_OF_MONTH, -1 * appSearchDto.getTimeState()); + appSearchDto.setStartTime(calendar.getTime()); + } + if(appSearchDto.getStartTime() != null && appSearchDto.getEndTime() == null) { appSearchDto.setEndTime(new Date()); } diff --git a/src/main/java/com/platform/modules/live/task/AutoLiveTask.java b/src/main/java/com/platform/modules/live/task/AutoLiveTask.java index 9216b3f..628d32a 100644 --- a/src/main/java/com/platform/modules/live/task/AutoLiveTask.java +++ b/src/main/java/com/platform/modules/live/task/AutoLiveTask.java @@ -5,6 +5,8 @@ import com.platform.common.utils.RedisUtils; import com.platform.modules.live.constants.SceneConstants; import com.platform.modules.live.entity.LiveSceneEntity; import com.platform.modules.live.service.LiveSceneService; +import org.apache.shiro.SecurityUtils; +import org.quartz.DisallowConcurrentExecution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +19,7 @@ import java.util.List; * @author Matt * 2021/4/19 11:30 */ +@DisallowConcurrentExecution @Component("autoLiveTask") public class AutoLiveTask { @@ -28,17 +31,19 @@ public class AutoLiveTask { @Autowired private RedisUtils redisUtils; - public void AutoLiveTask(){ + public void AutoLiveTask() { + synchronized (this.getClass()) { - logger.info("现场自动开关播定时刷新任务,刷新时间为:" + DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN)); + logger.info("现场自动开关播定时刷新任务,刷新时间为:" + DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN)); - List dataList = liveSceneService.freshLiveStateByAutoLive(); + List dataList = liveSceneService.freshLiveStateByAutoLive(); - if (dataList != null && dataList.size() > 0) { - dataList.forEach(e -> { - liveSceneService.createSceneIndex(e, null, null, null, null, null); - redisUtils.delete(SceneConstants.SCENE_REDIS_PREFIX + e.getId()); - }); + if (dataList != null && dataList.size() > 0) { + dataList.forEach(e -> { + liveSceneService.createSceneIndex(e, null, null, null, null, null); + redisUtils.delete(SceneConstants.SCENE_REDIS_PREFIX + e.getId()); + }); + } } } } diff --git a/src/main/java/com/platform/modules/live/task/LikeSyncTask.java b/src/main/java/com/platform/modules/live/task/LikeSyncTask.java index 9924e96..bd3d63a 100644 --- a/src/main/java/com/platform/modules/live/task/LikeSyncTask.java +++ b/src/main/java/com/platform/modules/live/task/LikeSyncTask.java @@ -2,7 +2,9 @@ package com.platform.modules.live.task; import com.platform.modules.live.service.LiveReportService; import com.platform.modules.live.service.impl.LiveSceneCountServiceImpl; +import org.quartz.DisallowConcurrentExecution; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ScanOptions; @@ -16,6 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component +@DisallowConcurrentExecution public class LikeSyncTask { private static final Logger logger = LoggerFactory.getLogger(LikeSyncTask.class); @@ -29,58 +32,66 @@ public class LikeSyncTask { private LiveReportService liveReportService; public void syncLikesToDatabase() { - ScanOptions options = ScanOptions.scanOptions().match("scene:liveCount:*").build(); - Cursor cursor = redisTemplate.getConnectionFactory() - .getConnection() - .scan(options); + RedisConnection connection = null; + try { + connection = redisTemplate.getConnectionFactory().getConnection(); + ScanOptions options = ScanOptions.scanOptions().match("scene:liveCount:*").build(); + Cursor cursor = connection.scan(options); - RedisSerializer serializer = new StringRedisSerializer(); + RedisSerializer serializer = new StringRedisSerializer(); - while (cursor.hasNext()) { - byte[] keyBytes = cursor.next(); - String key = serializer.deserialize(keyBytes); + while (cursor.hasNext()) { + byte[] keyBytes = cursor.next(); + String key = serializer.deserialize(keyBytes); - if (key != null) { - Integer sceneId = Integer.valueOf(key.split(":")[2]); - Object liveCount = redisTemplate.opsForValue().get(key); - if (liveCount != null) { - long totalLikes = Long.parseLong(liveCount.toString()); - try { - liveSceneCountService.addLiveCountToDb(sceneId, totalLikes); - redisTemplate.delete(key); - } catch (Exception e) { - logger.error("Failed to sync likes for key: {}", key, e); + if (key != null) { + Integer sceneId = Integer.valueOf(key.split(":")[2]); + Object liveCount = redisTemplate.opsForValue().get(key); + if (liveCount != null) { + long totalLikes = Long.parseLong(liveCount.toString()); + try { + liveSceneCountService.addLiveCountToDb(sceneId, totalLikes); + redisTemplate.delete(key); + } catch (Exception e) { + logger.error("Failed to sync likes for key: {}", key, e); + } } } } + }finally { + if (connection != null) connection.close(); } } public void syncReportLikesToDatabase() { - ScanOptions options = ScanOptions.scanOptions().match("report:liveCount:*").build(); - Cursor cursor = redisTemplate.getConnectionFactory() - .getConnection() - .scan(options); + RedisConnection connection = null; + try { + connection = redisTemplate.getConnectionFactory().getConnection(); + ScanOptions options = ScanOptions.scanOptions().match("scene:liveCount:*").build(); + Cursor cursor = connection.scan(options); - RedisSerializer serializer = new StringRedisSerializer(); + RedisSerializer serializer = new StringRedisSerializer(); - while (cursor.hasNext()) { - byte[] keyBytes = cursor.next(); - String key = serializer.deserialize(keyBytes); + while (cursor.hasNext()) { + byte[] keyBytes = cursor.next(); + String key = serializer.deserialize(keyBytes); - if (key != null) { - Integer reportId = Integer.valueOf(key.split(":")[2]); - Object liveCount = redisTemplate.opsForValue().get(key); - if (liveCount != null) { - long totalLikes = Long.parseLong(liveCount.toString()); - try { - liveReportService.addLiveCountToDb(reportId,totalLikes); - redisTemplate.delete(key); - } catch (Exception e) { - logger.error("Failed to sync likes for key: {}", key, e); + if (key != null) { + Integer reportId = Integer.valueOf(key.split(":")[2]); + Object liveCount = redisTemplate.opsForValue().get(key); + if (liveCount != null) { + long totalLikes = Long.parseLong(liveCount.toString()); + try { + liveReportService.addLiveCountToDb(reportId, totalLikes); + redisTemplate.delete(key); + } catch (Exception e) { + logger.error("Failed to sync likes for key: {}", key, e); + } } } } + }finally { + if (connection != null) connection.close(); // 归还连接 } } diff --git a/src/main/java/com/platform/modules/sys/service/impl/SysConfigServiceImpl.java b/src/main/java/com/platform/modules/sys/service/impl/SysConfigServiceImpl.java index a3f9747..140e716 100644 --- a/src/main/java/com/platform/modules/sys/service/impl/SysConfigServiceImpl.java +++ b/src/main/java/com/platform/modules/sys/service/impl/SysConfigServiceImpl.java @@ -13,6 +13,7 @@ import com.platform.modules.sys.redis.SysConfigRedis; import com.platform.modules.sys.service.SysConfigService; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -52,13 +53,25 @@ public class SysConfigServiceImpl extends ServiceImpl + + + + SSE 测试页面 + + + +
+

SSE 连接测试

+
+ + + +
+
状态: 未连接
+
+
+ + + + \ No newline at end of file