SSE

JavaScript 接收方

var evtSource = new EventSource("SSEServlet"); // 跨域加上  { withCredentials: true } 

// 接收消息( 消息如果已经被EventListener处理后不会到这里)
evtSource.onmessage = function(e) {
  console.log("message: ", e);
}

// 接受指定消息
evtSource.addEventListener("ping", function(e) {
  console.log("ping at: ", e);
}, false);

java发送方

  • servlet中需要设置的头
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Character-Encoding: utf-8
  • servlet
protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/event-stream");
  response.setCharacterEncoding("utf-8");

  for (int i = 0; i < 5; i++) {
    // 指定事件标识
    response.getWriter().write("event:me\n");
    // 格式: data: + 数据 + 2个回车
    response.getWriter().write("data:" + i + "\n\n");
    response.getWriter().flush();
  }
}
  • 返回 Flux<ServerSentEvent<T>>
@RestController
@RequestMapping("/sse")
public class SseController {

    @GetMapping("/randomNumbers")
    public Flux<ServerSentEvent<Integer>> randomNumbers() {
        return Flux.interval(Duration.ofSeconds(1))
                .map(seq -> Tuples.of(seq, ThreadLocalRandom.current().nextInt()))
                .map(data -> ServerSentEvent.<Integer>builder()
                        .event("random")
                        .id(Long.toString(data.getT1()))
                        .data(data.getT2())
                        .build());
    }
}
  • 或者指定produces为 MediaType.TEXT_EVENT_STREAM_VALUE
@GetMapping(value = "/flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)