服務器端實時推送技術之SseEmitter的用法

 這是SpringMVC提供的一種技術,能夠實現服務端向客戶端實時推送數據.用法很是簡單,只須要在Controller提供一個接口,建立並返回SseEmitter對象,發送數據能夠在另外一個接口調用其send方法發送數據.這個SseEmitter對象和DeferredResult有殊途同歸之妙,只是SseEmitter能夠在一次請求中返回多條數據,而DeferredResult只能返回一條.關於DeferredResult的用法請求參考個人另外一篇博客:http://www.javashuo.com/article/p-micvnrhk-et.htmlhtml

 1 import org.slf4j.Logger;
 2 import org.slf4j.LoggerFactory;
 3 import org.springframework.web.bind.annotation.RequestMapping;
 4 import org.springframework.web.bind.annotation.RestController;
 5 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
 6 
 7 import java.io.IOException;
 8 import java.util.Map;
 9 import java.util.concurrent.ConcurrentHashMap;
10 
11 /**
12  * 服務器端實時推送技術之 SseEmitter 的用法測試
13  * <p>
14  * 測試步驟:
15  * 1.請求http://localhost:8888/sse/start?clientId=111接口,瀏覽器會阻塞,等待服務器返回結果;
16  * 2.請求http://localhost:8888/sse/send?clientId=111接口,能夠請求屢次,並觀察第1步的瀏覽器返回結果;
17  * 3.請求http://localhost:8888/sse/end?clientId=111接口結束某個請求,第1步的瀏覽器將結束阻塞;
18  * 其中clientId表明請求的惟一標誌;
19  *
20  * @author syj
21  */
22 @RestController
23 @RequestMapping("/sse")
24 public class SseEmitterController {
25     private static final Logger logger = LoggerFactory.getLogger(SseEmitterController.class);
26 
27     // 用於保存每一個請求對應的 SseEmitter
28     private Map<String, Result> sseEmitterMap = new ConcurrentHashMap<>();
29 
30     /**
31      * 返回SseEmitter對象
32      *
33      * @param clientId
34      * @return
35      */
36     @RequestMapping("/start")
37     public SseEmitter testSseEmitter(String clientId) {
38         // 默認30秒超時,設置爲0L則永不超時
39         SseEmitter sseEmitter = new SseEmitter(0L);
40         sseEmitterMap.put(clientId, new Result(clientId, System.currentTimeMillis(), sseEmitter));
41         return sseEmitter;
42     }
43 
44     /**
45      * 向SseEmitter對象發送數據
46      *
47      * @param clientId
48      * @return
49      */
50     @RequestMapping("/send")
51     public String setSseEmitter(String clientId) {
52         try {
53             Result result = sseEmitterMap.get(clientId);
54             if (result != null && result.sseEmitter != null) {
55                 long timestamp = System.currentTimeMillis();
56                 result.sseEmitter.send(timestamp);
57             }
58         } catch (IOException e) {
59             logger.error("IOException!", e);
60             return "error";
61         }
62 
63         return "Succeed!";
64     }
65 
66     /**
67      * 將SseEmitter對象設置成完成
68      *
69      * @param clientId
70      * @return
71      */
72     @RequestMapping("/end")
73     public String completeSseEmitter(String clientId) {
74         Result result = sseEmitterMap.get(clientId);
75         if (result != null) {
76             sseEmitterMap.remove(clientId);
77             result.sseEmitter.complete();
78         }
79         return "Succeed!";
80     }
81 
82     private class Result {
83         public String clientId;
84         public long timestamp;
85         public SseEmitter sseEmitter;
86 
87         public Result(String clientId, long timestamp, SseEmitter sseEmitter) {
88             this.clientId = clientId;
89             this.timestamp = timestamp;
90             this.sseEmitter = sseEmitter;
91         }
92     }
93 }

 

這個技術有什麼用呢? 就看你的想象力了, 好比能夠用於和進度有關的操做: 安裝進度, 部署進度, 任務執行進度等等.java

相關文章
相關標籤/搜索