SSE 发射器:管理超时和完成()

adi*_*dar 4 java spring server-sent-events eventemitter

我正在编写一个 Web 应用程序,其中多个侦听器(Evcentsource SSE 客户端 JS)将连接到我的服务器。我想做的是

  1. 为每个连接的侦听器存储 SSE 发射器:可以在内存中或通过为每个客户端分配 id 的任何其他方式来完成到目前为止我能够实现这一目标
  2. 现在的问题; 如何向连接到我的网络应用程序的特定客户端发送响应/事件?在执行此操作时,存储的 SSEEmmiters 要么已完成,要么已超时。我如何防止这种情况?我如何让 sseEmmiter 无限期地打开(直到客户端关闭)并有选择地发送事件。

rwf*_*fbc 6

您需要在 SseEmitter 上设置超时。默认超时时间相当短。

该SseEmitter超时的单位是毫秒。这是会话超时,不受会话活动的影响。

超时需要设置为会话的预期持续时间,以毫秒为单位。所以,86400000(或更多)是完全合适的。


小智 5

如果您希望 sseEmiter 可以无限次打开,您可以简单地将超时设置为 -1L

并有选择地发送事件,将所有 sseEmmiters 放入具有特定键的映射中,以便在您想像我在此代码中所做的那样发送事件时使用它。

@Controller
@RequestMapping(path = "api/person")
public class PersonController {

 @Autowired
 private PersonRepository personRepository;
 private Map<String, SseEmitter> onPersonAddedSseEmitters = new ConcurrentHashMap<>();

 @PostMapping(path = "/add")
 public @ResponseBody
 String addPerson(@RequestBody Person person) {
   person.setId(new Random().nextLong());
   personRepository.save(person);
   onPersonAddedSseEmitters.forEach((key, sseEmitter) -> {
     try {
       if (person.getName().startsWith(key.split("-")[0])) {
         sseEmitter.send(person);
       }
     } catch (Exception ignored) {
       sseEmitter.complete();
       onPersonAddedSseEmitters.remove(key);
     }
   });
   return "Saved";
 }

 @GetMapping(path = "/onPersonAdded/{prefix}")
 public SseEmitter onPersonAdded(@PathVariable String prefix) {
   SseEmitter sseEmitter = new SseEmitter(-1L);
   onPersonAddedSseEmitters.put(prefix + "-" + new Random().nextLong(), sseEmitter);
   return sseEmitter;
 }
}
Run Code Online (Sandbox Code Playgroud)