服務端推送技術之SSE(基於SpringMVC)

服務端推送技術之SSE(基於SpringMVC)

今天主要介紹如何在springmvc中實現SSE消息推送。

SpringMVC本身已經對SSE的實現做了封裝,名字叫做SseEmitter,詳情可參考官網API:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/SseEmitter.html。網上搜到的很多示例都是不能達到推送效果的,所以我這裡的示例專門加了一個發送消息的接口,和推送接口配合演示。

控制器代碼示例

package com.keyan.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.function.Consumer;
@Controller
public class Demo {
//初始化一個sseEmitter對象,定義在這裡是方便不同的請求都可以使用這一個對象
//timeout設置為0表示不超時
final SseEmitter emitter = new SseEmitter(0L);
//用來返回測試頁面的方法
@RequestMapping("/index")
public String index(){
return "/sse.html";
}
/**
* sse連接請求,也是初始化連接用的,供web端js調用
* @return
*/
@RequestMapping(value="/push",produces="text/event-stream")
public SseEmitter push(){

System.out.println("waitting");
//指定結束連接時的回調
emitter.onCompletion(()->{
System.out.println("emitter over........................");
});
//指定出錯誤時的回調
emitter.onError(new Consumer() {
@Override
public void accept(Throwable throwable) {
System.err.println(throwable.getCause());
System.err.println(throwable.getMessage());
}
});
//指定超時回調
emitter.onTimeout(()->{
System.out.println("emiter timeout........................");
});
//也可以把sseEmitter交給另外一個線程,然後又線程推送數據
/* mvcTaskExecutor.execute(() -> {
try {
for(int i=0;i<100;i++){
emitter.send("hello"+i);
System.out.println("hello"+i);
Thread.sleep(2000*1);
}
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
});*/
System.out.println("return");
return emitter;
}
/**
* 另外一個方法,模擬要發送消息的角色
* @param text
* @return
*/
@RequestMapping(value = "send")
public @ResponseBody String text(String text){
System.out.println("receive text:"+text);
try {
//使用已初始化好的sseEmitter對象發送消息

emitter.send(text);
//自己加的一個機制,如果消息為exit,則主動結束連接
if("exit".equals(text)){
emitter.complete();
}
} catch (IOException e) {
e.printStackTrace();
}
return "ok";
}
}

頁面演示示例




SSE Demo


sse




效果演示

服務端推送技術之SSE(基於SpringMVC)

改進升級

1、 消息的推送者可以改為線程,在線程裡處理業務,然後調用sseEmitter對象send消息

2、 sse不是萬能的,僅以本示例為主的話,每個連接都需要一個線程,如果是大量的客戶連接,線程會比較多,可能會造成問題

3、 這種推送是單向的,是服務端向客戶端推送的,而websocket是雙向的,根據需要選擇

4、 SseEmitter在運行比較耗時的任務時非常好用,比如實時查看部署進度,比如查看定時任務的實時輸出、查看實時數據統計等


分享到:


相關文章: