Spring BootでSSE
Spring BootでSSE(text/event-stream)やりてえ〜。やりてえよね。
ということでおあつらえ向きなSseEmitter
がある。
簡単な使い方
1秒ごとに現在日時を返すやつ。非同期実行自体は https://qiita.com/takkkun/items/1364fdaac8ae2b9fdc01 を参照。
@Service
class SseService {
@Async
fun emitDateTime(emitter: SseEmitter) {
var finished = false
while (!finished) {
TimeUnit.SECONDS.sleep(1)
try {
sse.send(LocalDateTime.now().toString())
}
catch (e: IOException) {
finished = true
}
}
}
}
@Controller
class SseController(private val service: SseService) {
@RequestMapping(/* ... */)
fun sse(): ResponseBodyEmitter {
val emitter = SseEmitter()
service.emitDateTime(emitter)
return emitter
}
}
これで以下のようなレスポンスが返ってくる。
$ curl -i 'http://localhost:8080/sse'
HTTP/1.1 200
Content-Type: text/event-stream;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 20 Jan 2020 07:01:31 GMT
data:2020-01-20T16:01:32.155751
data:2020-01-20T16:01:33.164949
data:2020-01-20T16:01:34.168721
data:2020-01-20T16:01:35.174836
data:2020-01-20T16:01:36.179743
...
タイムアウト
デフォルトのタイムアウトはSpring Bootが定めている。具体的にはspring.mvc.async.request-timeout
というプロパティで。単位はミリ秒。
もしくはSseEmitter
のコンストラクタでも指定できる。この場合、コンストラクタに与えた値が優先される。
無期限にしたい場合は0
を指定。
実際にタイムアウトが起きた場合は、SseEmitter#onTimeout
で指定したコールバックが呼ばれ、AsyncRequestTimeoutException
が投げられる。
クライアントから切断
クライアントから切断された瞬間にそれを検出する術はない、と思う。
ただ、クライアントから切断されている状態でSseEmitter#send
を呼び出すと、IOException
(実際はそのサブクラスのClientAbortException
なはず)が投げられるので、それで検出することは可能。
最終的にSseEmitter#onError
で指定したコールバックが呼ばれるので、それでも良いかな?
ちなみに@Async
の中でハンドルされていない例外が発生すると、非同期処理実行の仕組みの方でログを記録するので、ちゃんとハンドルしてあげた方がベターだと思う(JavaだとIOException
がチェック例外なので強制されると思うけど)。
サーバーから完了
SseEmitter#complete
を呼ぶとレスポンスが完了する。
クライアントから切断することがほとんどだとは思うけど、用途によってはあり得るので一応。
Author And Source
この問題について(Spring BootでSSE), 我々は、より多くの情報をここで見つけました https://qiita.com/takkkun/items/29b1d228fa4f0ba5f4ba著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .