gpt4 book ai didi

java - Spring Server Sent Events - ResponseBodyEmitter 已经设置完成

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:35:49 24 4
gpt4 key购买 nike

我正在使用 spring 4.3.7.RELEASE 来设置服务器发送的事件。并使用 @scheduled 注释每 2 秒发送一次消息。这是 Controller 。

@Controller
public class MySSEController {
private final SseEmitter sseEmitter = new SseEmitter();
private int counter = 0;

@RequestMapping("/ssestream")
public SseEmitter getRealTimeMessageAction() throws IOException {

sseEmitter.send("MessageCounter : " + counter);
return sseEmitter;
}

@Scheduled(fixedDelay = 2*1000)
public void scheduledMsgEmitter() throws IOException
{
if(null != sseEmitter) {
sseEmitter.send("MessageCounter : " + ++counter);
}
}

}

我直接从 eclipse 在 Tomcat 9 上运行它。应用程序每 2 秒启动一次并向浏览器发送消息。但一段时间后它停止发送消息,我在 eclipse 控制台中看到以下异常。

Mar 16, 2017 6:57:34 PM org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver handleAsyncRequestTimeoutException
SEVERE: Async timeout for GET [/streaming-web/stream/ssestream]
Mar 16, 2017 6:57:35 PM org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler handleError
SEVERE: Unexpected error occurred in scheduled task.
java.lang.IllegalStateException: ResponseBodyEmitter is already set complete
at org.springframework.util.Assert.state(Assert.java:70)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.send(ResponseBodyEmitter.java:158)
at org.springframework.web.servlet.mvc.method.annotation.SseEmitter.send(SseEmitter.java:126)
at org.springframework.web.servlet.mvc.method.annotation.SseEmitter.send(SseEmitter.java:107)
at org.springframework.web.servlet.mvc.method.annotation.SseEmitter.send(SseEmitter.java:89)
at com.mycomp.test.controllers.MySSEController.scheduledMsgEmitter(MySSEController.java:25)
at sun.reflect.GeneratedMethodAccessor31.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

我错过了什么吗?请帮我解决这个问题。

最佳答案

我不确定这是否是正确的解决方案。

我稍微修改了实现以适用于所有连接的客户端 Earlier I was unable to deliver the same message to different clients connected to this stream此实现不会抛出 IllegalStateException

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

@Controller
public class MySSEController_Working {

private Set<SseEmitter> sseEmitters = new HashSet<SseEmitter>();
private int messageCount = 0;

@RequestMapping("/ssestream")
public SseEmitter getRealTimeMessageAction(HttpServletRequest request, HttpServletResponse response) throws IOException {

final SseEmitter sseEmitter = new SseEmitter();

sseEmitter.onCompletion(() -> {
synchronized (this.sseEmitters) {
this.sseEmitters.remove(sseEmitter);
}
});

sseEmitter.onTimeout(()-> {
sseEmitter.complete();
});

// Put context in a map
sseEmitters.add(sseEmitter);

return sseEmitter;
}

@Scheduled(fixedDelay = 2*1000)
public void scheduledMsgEmitter() throws IOException
{
if(!sseEmitters.isEmpty())
++messageCount;
else
System.out.println("No active Emitters ");

System.out.println("Sent Messages : " + messageCount);

sseEmitters.forEach(emitter -> {
if (null != emitter)
try {
System.out.println("Timeout : "+ emitter.getTimeout());
emitter.send("MessageCounter : " + messageCount);
emitter.complete();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}

关于java - Spring Server Sent Events - ResponseBodyEmitter 已经设置完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42835888/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com