Spring Boot Streaming and SSE异步处理

3,306 阅读2分钟

文章目录

Spring Boot Streaming and SSE异步处理

  • ResponseBodyEmitter
  • SseEmitter
  • StreamingResponseBody

ResponseBodyEmitter

ResponseBodyEmitter 处理异步响应。

而且,它代表了许多子类的父类-我们将在下面仔细研究其中的一个。

服务器端

最好将 ResponseBodyEmitter与它自己的专用异步线程一起使用,并用ResponseEntity包装 (我们可以将其直接注入发射器):

@Controller
public class ResponseBodyEmitterController {
 
    private ExecutorService executor 
      = Executors.newCachedThreadPool();

    @GetMapping("/rbe")
    public ResponseEntity<ResponseBodyEmitter> handleRbe() {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        executor(() -> {
            try {
                emitter.send(
                  "/rbe" + " @ " + new Date(), MediaType.TEXT_PLAIN);
                emitter.complete();
            } catch (Exception ex) {
                emitter.completeWithError(ex);
            }
        });
        return new ResponseEntity(emitter, HttpStatus.OK);
    }
}

客户端

对于客户端使用,我们可以使用简单的XHR方法并调用API端点,就像通常的AJAX操作一样:

var xhr = function(url) {
    return new Promise(function(resolve, reject) {
        var xmhr = new XMLHttpRequest();
        //...
        xmhr.open("GET", url, true);
        xmhr.send();
       //...
    });
};

xhr('http://localhost:8080/javamvcasync/rbe')
  .then(function(success){ //... });

SseEmitter

SseEmitter实际上是ResponseBodyEmitter的子类,并提供开箱即用的 其他 服务器发送事件(SSE)支持。

服务器端

因此,让我们快速看一下利用此强大实体的示例控制器:

@Controller
public class SseEmitterController {
    private ExecutorService nonBlockingService = Executors
      .newCachedThreadPool();
    
    @GetMapping("/sse")
    public SseEmitter handleSse() {
         SseEmitter emitter = new SseEmitter();
         nonBlockingService.execute(() -> {
             try {
                 emitter.send("/sse" + " @ " + new Date());
                 // we could send more events
                 emitter.complete();
             } catch (Exception ex) {
                 emitter.completeWithError(ex);
             }
         });
         return emitter;
    }   
}

客户端

这次,我们的客户端工作有所不同,因为我们可以利用持续连接的服务器发送的事件库:

var sse = new EventSource('http://localhost:8080/javamvcasync/sse');
sse.onmessage = function (evt) {
    var el = document.getElementById('sse');
    el.appendChild(document.createTextNode(evt.data));
    el.appendChild(document.createElement('br'));
};

StreamingResponseBody

最后,我们可以使用 StreamingResponseBody直接 将其写入OutputStream,然后再使用ResponseEntity将已写入的信息传递回客户端 。

服务器端

@Controller
public class StreamingResponseBodyController {
 
    @GetMapping("/srb")
    public ResponseEntity<StreamingResponseBody> handleRbe() {
        StreamingResponseBody stream = out -> {
            String msg = "/srb" + " @ " + new Date();
            out.write(msg.getBytes());
        };
        return new ResponseEntity(stream, HttpStatus.OK);
    }
}

客户端

像以前一样,我们将使用常规的XHR方法访问上面的控制器:

var xhr = function(url) {
    return new Promise(function(resolve, reject) {
        var xmhr = new XMLHttpRequest();
        //...
        xmhr.open("GET", url, true);
        xmhr.send();
        //...
    });
};

xhr('http://localhost:8080/javamvcasync/srb')
  .then(function(success){ //... });

🍎QQ群【837324215】
🍎关注我的公众号【Java大厂面试官】,一起学习呗🍎🍎🍎