springboot使用SSE
SSE(server send event)服务端主动推送技术。html5新标准,用来从服务端实时推送数据到浏览器
直接建立在当前http连接上,本质上是保持一个http长连接,轻量简单的服务器数据推送场景,可以使用SSE,SSE技术是基于单工通信模式
服务端
@RequestMapping("sse")
@RestController
@Slf4j
public class SseController {
//缓存连接
private static final Map<String, SseEmitter> MAP = new ConcurrentHashMap<>();
/**
* 建立连接
* @param id
* @return
*/
@SneakyThrows
@GetMapping("subscribe/{id}")
public SseEmitter subscribe(@PathVariable String id){
log.info("subscribe {}",id);
SseEmitter sseEmitter = new SseEmitter(30000L);
MAP.put(id,sseEmitter);
sseEmitter.onCompletion(()->{
log.info("{}完成",id);
MAP.remove(id);
});
sseEmitter.onTimeout(()->{
log.info("{}超时",id);
MAP.remove(id);
});
//响应前端,并设置重试时间为1秒
sseEmitter.send(SseEmitter.event().reconnectTime(1000).data("连接成功"));
return sseEmitter;
}
/**
* 发送消息
* @param id
* @param msg
* @return
*/
@SneakyThrows
@GetMapping("push/{id}/{msg}")
public String push(@PathVariable String id,@PathVariable String msg){
log.info("push {} {}",id,msg);
SseEmitter sseEmitter = MAP.get(id);
if (sseEmitter!=null){
sseEmitter.send(SseEmitter.event().name("msg").data(msg));
}
return "ok";
}
/**
* 断开连接
* @param id
* @return
*/
@GetMapping("over/{id}")
public String over(@PathVariable String id){
SseEmitter sseEmitter = MAP.get(id);
if (sseEmitter!=null){
sseEmitter.complete();
MAP.remove(id);
}
return "ok";
}
}
浏览器
- 访问
sse/subscribe/{id}
建立连接,并监听 - 访问
sse/push/{id}/{msg}
发送消息 - 访问
sse/over/{id}
断开连接