使用SseEmitter不斷向網(wǎng)頁(yè)輸出結(jié)果

之前寫過(guò)一篇文章:springmvc不斷輸出文本到網(wǎng)頁(yè),采用的是對(duì)response不斷進(jìn)行write和flush實(shí)現(xiàn)的。在spring 4.2版本的時(shí)候提供了一個(gè)SseEmitter可以直接用來(lái)實(shí)現(xiàn)這個(gè)功能。

實(shí)例

@Controller
@RequestMapping("/sse")
public class SseEmitterController {

    private static final Logger LOGGER = LoggerFactory.getLogger(SseEmitterController.class);

    @Autowired
    @Qualifier("mvcTaskExecutor")
    ThreadPoolTaskExecutor mvcTaskExecutor;

    @GetMapping("")
    public SseEmitter sseDemo() throws InterruptedException {
        final SseEmitter emitter = new SseEmitter(0L); //timeout設(shè)置為0表示不超時(shí)
        mvcTaskExecutor.execute(() -> {
            try {
                for(int i=0;i<100;i++){
                    emitter.send("hello"+i);
                    LOGGER.info("emit:{}","hello"+i);
                    Thread.sleep(1000*1);
                }
                emitter.complete();
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });
        return emitter;
    }
}

輸出實(shí)例

data:"hello0"

data:"hello1"

data:"hello2"

data:"hello3"

data:"hello4"

data:"hello5"

//......

注意事項(xiàng)

  • 這里的SseEmitter的send不能阻塞mvc線程,必須提前返回,然后把send放到異步里頭

除了使用上述的放入線程池的方式,也可以直接調(diào)用標(biāo)記有async的方法

  • 這里SseEmitter的timeout設(shè)置為0,表示不超時(shí).
    如果不設(shè)置為0,那么如果SseEmitter在指定的時(shí)間(AsyncSupportConfigurer設(shè)置的timeout,默認(rèn)為30秒)未完成會(huì)拋出異常
org.springframework.web.context.request.async.AsyncRequestTimeoutException: null
    at org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor.handleTimeout(TimeoutDeferredResultProcessingInterceptor.java:42) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterTimeout(DeferredResultInterceptorChain.java:75) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.context.request.async.WebAsyncManager$5.run(WebAsyncManager.java:392) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:143) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:134) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:153) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:224) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_71]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_71]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_71]

小結(jié)

SseEmitter在運(yùn)行比較耗時(shí)的任務(wù)時(shí)非常好用,比如實(shí)時(shí)查看部署進(jìn)度,比如查看定時(shí)任務(wù)的實(shí)時(shí)輸出等。

doc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容