1前書き

この簡単なチュートリアルでは、Spring MVC 5.x.xでのいくつかの非同期およびストリーミングオブジェクトの使用方法を説明します。

具体的には、3つの重要なクラスについて説明します。


  • ResponseBodyEmitter


  • SseEmitter


  • StreamingResponseBody

また、JavaScriptクライアントを使用してそれらと対話する方法についても説明します。

2.

ResponseBodyEmitter


ResponseBodyEmitter

は非同期応答を処理します。

また、それはいくつかのサブクラスの親を表します。そのうちの1つを以下で詳しく説明します。

2.1. サーバ側


ResponseBodyEmitter

を専用の非同期スレッドと一緒に使用し、

ResponseEntity

(これに直接

emitter

を挿入することができます)でラップしたほうが良いでしょう。

@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);
    }
}

そのため、上記の例では、

CompleteableFutures

** 、より複雑な非同期の約束、または

@ Async

アノテーションの使用を回避する必要があります。

代わりに、非同期エンティティを宣言し、それを

ExecutorServiceによって提供される新しい

Thread__にラップします。

2.2. クライアント側

クライアントサイドでの使用では、単純なXHRメソッドを使用して、通常のAJAX操作のようにAPIエンドポイントを呼び出すことができます。

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){//... });

3.

SseEmitter


  • SseEmitter

    は実際には

    ResponseBodyEmitter

    のサブクラスであり、追加の

    Server-Sent Event

    (SSE)** をすぐに使用できるようにします。

3.1. サーバ側

それでは、この強力な実体を活用したコントローラーの例を簡単に見てみましょう。

@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;
    }
}

かなり標準的な料金ですが、これと通常のRESTコントローラーとの間にはいくつかの違いがあります。

  • 最初に、

    SseEmitter

    を返します

  • また、コアレスポンス情報を独自の

    Thread

    にラップしています。

  • 最後に、


    _ emit.send()を使用してレスポンス情報を送信します

    _

3.2. クライアント側

継続的に接続された

Server-Sent Event

Libraryを利用できるので、今回のクライアントの動作は少し異なります。

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'));
};

4.

StreamingResponseBody

最後に、

__StreamingResponseBodyを使用して、

ResponseEntityを使用してその書き込まれた情報をクライアントに返す前に、

OutputStream

に直接書き込むことができます。

4.1. サーバ側

@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);
    }
}

4.2. クライアント側

前と同じように、上記のコントローラにアクセスするには通常の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){//... });

次に、これらの例のいくつかの成功例を見てみましょう。


5それをすべて一緒にする

サーバーのコンパイルと上記のクライアントの実行(提供された

index.jsp

へのアクセス)に成功すると、ブラウザに次のように表示されます。


image、width = 580、height = 351

そして、私たちの端末では次のようになります。

イメージ:/uploads/Terminal-1024×546-100×53.png%20100w[イメージ]

エンドポイントを直接呼び出して、ストリーミング応答がブラウザに表示されるのを確認することもできます。


6. 結論


Future



CompleteableFuture

は、JavaとSpringへの堅牢な追加を証明しましたが、現在は、並行性の高いWebアプリケーションの非同期およびストリーミングデータをより適切に処理するためのいくつかのリソースを自由に利用できます。

最後に、完全なコード例https://github.com/eugenp/tutorials/tree/master/spring-5-mvc[GitHubについて]をご覧ください。