この記事は Holmes Advent Calendar 2020 - Qiita 5 日目の記事です。
こんにちは、Holmesでサーバサイドエンジニアをしているid:c-terashimaです
12月は年末ということもありより忙しい月かと思いますが、いかがお過ごしですか?
私は技術書典10の執筆にPHPカンファレンスの当日スタッフ、子供(二人)の誕生日と慌ただしい日々を送っています。。
今回は spring-boot-starter-websocket
を使ってWebSocket(STOMP)を試してみたいと思います
WebSocketとは
Web上において双方向通信を低コストで行う仕組みのことです
Webアプリケーションサーバから任意のタイミングでクライアントに情報を送信することが可能で、チャットアプリみたいに多数のクライアントにメッセージを通知する場合に双方向通信が必要になります
環境
次の環境で動作を確認しております
- Java11
- Gradle
- SpringBoot 2.4.0
依存関係
build.gradleのdependenciesに spring-boot-starter-web
と spring-boot-starter-websocket
を追加します
それ以外は必要に応じて追加してください
dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-websocket' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.projectreactor:reactor-test' }
WebSocketConfig
アプリケーションでWebSocketを有効にするための構成クラスを追加します
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/websocket") // ① .setAllowedOrigins("chrome-extension://ggnhohnkfcpcanfekomdkjffnfcjnjam") // ③ .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); // ② } }
①で指定している /websocket
はクライアントがコネクションを貼るためのエンドポイントで、②は通知を購読する(subscribe)ためのエンドポイントになります
クライアントは /topic
を購読しておくことで、サーバからの通知を受け取ることが可能になります
今回クライアントはChrome拡張機能のApic - Complete API solution - Chrome ウェブストアを利用します
クロスオリジン対策として拡張機能のホストを③に登録します
メッセージ通知
/hello
APIをコールすると購読しているユーザにメッセージを通知します
@RestController @RequiredArgsConstructor public class Controller { private final SimpMessagingTemplate simpMessagingTemplate; @PutMapping("/hello") public String hello(@RequestBody Parameter parameter) { String message = "hello " + parameter.name; simpMessagingTemplate.convertAndSend("/topic", message); // ① return message; } @Data static class Parameter { private String name; } }
SimpMessagingTemplate#convertAndSendメソッドで /topic
を購読しているユーザにメッセージを送信しています
curlを実行するとMessageがリアルタイムで表示することができました
かんたんに双方向通信を実装することができましたね!