feat(session): 切换当前活动机构并优化 SSE 连接- 在 LoginController 中添加 switchActiveOrg 方法,用于切换当前活动机构

- 在 SseService 中增加心跳消息发送,保持 SSE 连接活跃
- 修改 OrgBaseEntity 和 OrgCommonEntity,使用 activeOrganizationId 替代 currentOrganizationId- 在 CoalWashingDailyAnalysisController 中设置 SseEmitter 的超时时间为 10 分钟
- 新增 TaskSchedulerConfig 配置类,启用定时任务调度
This commit is contained in:
2025-03-14 22:23:57 +08:00
parent bb95487a69
commit a3ba459172
6 changed files with 51 additions and 10 deletions

View File

@@ -21,7 +21,7 @@ public class OrgBaseEntity extends BaseEntity {
if (StringUtils.isEmpty(organizationId)) {
this.organizationId =
Ctx.isLoggedIn() ? Ctx.currentOrganizationId() : organizationId;
Ctx.isLoggedIn() ? Ctx.activeOrganizationId() : organizationId;
}
super.prePersist();
}

View File

@@ -26,7 +26,7 @@ public class OrgCommonEntity extends CommonEntity {
if (StringUtils.isEmpty(organizationId)) {
this.organizationId =
Ctx.isLoggedIn() ? Ctx.currentOrganizationId() : organizationId;
Ctx.isLoggedIn() ? Ctx.activeOrganizationId() : organizationId;
}
super.prePersist();
}
@@ -36,7 +36,7 @@ public class OrgCommonEntity extends CommonEntity {
if (StringUtils.isEmpty(organizationId)) {
this.organizationId =
Ctx.isLoggedIn() ? Ctx.currentOrganizationId() : organizationId;
Ctx.isLoggedIn() ? Ctx.activeOrganizationId() : organizationId;
}
super.preUpdate();
}

View File

@@ -20,6 +20,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.concurrent.TimeUnit;
@RequestMapping("/coalWashingDailyAnalysis")
@RestController
@SysLog(module = "洗煤报告表")
@@ -109,7 +111,8 @@ public class CoalWashingDailyAnalysisController extends BaseController {
@PostMapping("/sse")
public SseEmitter sse(@RequestBody IdRequest request) {
SseEmitter emitter = new SseEmitter();
SseEmitter emitter = new SseEmitter(TimeUnit.MINUTES.toMillis(10));
// SseEmitter emitter = new SseEmitter(TimeUnit.SECONDS.toMillis(10));
sseService.register("coalWashingDailyAnalysis." + request.getId(), emitter);

View File

@@ -8,6 +8,7 @@ import cn.lihongjie.coal.common.Ctx;
import cn.lihongjie.coal.rabbitmq.RabbitMQService;
import cn.lihongjie.coal.session.dto.CaptchaDto;
import cn.lihongjie.coal.session.dto.LoginDto;
import cn.lihongjie.coal.session.dto.SwitchActiveOrgRequest;
import cn.lihongjie.coal.session.service.SessionService;
import cn.lihongjie.coal.trustDevice.dto.TrustDeviceDto;
import cn.lihongjie.coal.trustDevice.service.TrustDeviceService;
@@ -60,7 +61,14 @@ public class LoginController extends BaseController {
return true;
}
@PostMapping("/switchActiveOrg")
@SysLog(action = "切换机构")
public Boolean switchActiveOrg(@RequestBody SwitchActiveOrgRequest dto) {
service.switchActiveOrg(dto);
return true;
}
@PostMapping("/genCaptcha")

View File

@@ -0,0 +1,8 @@
package cn.lihongjie.coal.spring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class TaskSchedulerConfig {}

View File

@@ -1,7 +1,7 @@
package cn.lihongjie.coal.sse.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -9,10 +9,13 @@ import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
@Service
@Slf4j
@@ -22,8 +25,26 @@ public class SseService {
@Autowired ObjectMapper objectMapper;
@Autowired TaskScheduler taskScheduler;
public void register(String topicId, SseEmitter emitter) {
ScheduledFuture<?> scheduledFuture = taskScheduler.scheduleAtFixedRate(
() -> {
try {
emitter.send(
objectMapper.writeValueAsString(
ImmutableMap.of(
"time",
System.currentTimeMillis(),
"event",
"heartbeat")));
} catch (IOException e) {
throw new RuntimeException(e);
}
},
Duration.ofMinutes(1));
RTopic topic = redissonClient.getTopic(topicId);
int addListener =
topic.addListener(
@@ -41,31 +62,32 @@ public class SseService {
() -> {
topic.removeListener(addListener);
log.info("{} remove listener:{} onCompletion ", topicId, addListener);
scheduledFuture.cancel(true);
});
emitter.onTimeout(
() -> {
topic.removeListener(addListener);
log.info("{} remove listener:{} onTimeout ", topicId, addListener);
scheduledFuture.cancel(true);
});
emitter.onError(
(e) -> {
topic.removeListener(addListener);
log.info("{} remove listener:{} onError ", topicId, addListener, e);
scheduledFuture.cancel(true);
});
}
@SneakyThrows
public void broadcast(String s, Object event) {
RTopic topic = redissonClient.getTopic(s);
topic.publish(event instanceof String ? event : objectMapper.writeValueAsString(event));
}
}