# WebSocketServerSample ## 概要 ローカルにWebSocketサーバーをたてるサンプルアプリ。 WebSocketで通信を行うファイルを作り、そのファイルをConfigファイルに設定する必要がある。 SpringBootを使っていなければConfigファイル無しでも動いたが、 SpringBootでRestなAPIと併用してWebSocketを使う場合、Configファイルでの設定が必要になると思う。 ## 各ファイルのポイント ### Build.gradle 下の2行を追加する(二行目は追加されてる場合が多いかも) ``` dependencies { //(省略) implementation 'org.springframework.boot:spring-boot-starter-websocket' implementation 'org.springframework.boot:spring-boot-starter-jersey' } ``` ### WebSocketConfig.java Configファイルの作成方法があまり出てこなかった。下の2つの記事を参考に書いたら出来た。 作ったWebSocketコードのファイルは、このConfigファイルで@Beanしないと動かない。 - [Use Java Websocket API in Spring Boot application - stack overflow](https://stackoverflow.com/questions/52185059/use-java-websocket-api-in-spring-boot-application) - [simasch/spring-boot-websocket- GitHub](https://github.com/simasch/spring-boot-websocket) ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { //registry.addHandler(unitWebSocketHandler, "/unit").setAllowedOrigins("*"); } /* ここめっちゃ大事!! ローカルで実行するときは、下3行のBean定義が必要。(入れないとWebSocketのコードが動かなくなる) サーバーで実行するときは、下3行のBean定義が不要。(消さないと全てのコードが動かなくなる) これで2週間くらい躓いた... */ @Bean public WebSocketDemo webSocketDemo() { return new WebSocketDemo(); } @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } ``` ### 通信部分のコード 下の例は、現在の時刻を5秒に1回送信するサンプル。 下の記事を参考にした。 - [Java API for WebSocket - fujitsu.com](https://www.fujitsu.com/jp/documents/products/software/resources/technical/interstage/apserver/guide/WebSocket.pdf) - [WebSocketによるサーバサイドレンダリングなテトリスの作り方(その2) - A Memorandum](https://blog1.mammb.com/entry/2021/05/13/090000#エンドポイントの構成) ``` // ここがURLのエンドポイントになる。 @ServerEndpoint("/WebSocketDemo") public class WebSocketDemo { private static final Queue<Session> sessions = new ConcurrentLinkedQueue<>(); static { ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); service.scheduleWithFixedDelay(WebSocketDemo::broadcast, 5, 5, TimeUnit.SECONDS); } @OnMessage public String onMessage(String message) { System.out.println("WebSocketで受信したメッセージ/ " + message); return "WebSocketでメッセージを正常に受信しました!"; } @OnError public void onError(Throwable th) { System.out.println("WebSocketエラーが発生/ " + th.getMessage()); } @OnOpen public void onOpen(Session session) { System.out.println("WebSocketセッション確立"); sessions.add(session); } @OnClose public void onClose(Session session) { System.out.println("WebSocketセッション終了"); sessions.remove(session); } public static void broadcast() { Date now = new Date(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); sessions.forEach(session -> { session.getAsyncRemote().sendText("Broadcast : " + formatter.format(now)); }); } } ``` もしパラメータを付けたい場合、 URIパス には @ServerEndpoint("/chat/{user}")のようにパスパラメータを定義できる。 これで、@PathParamを通して以下のようにパラメータを取得可能。 ``` @OnOpen public void onOpen(Session session, @PathParam("user") String user) { } ``` ### 参考 WebSocketとJSONを組み合わせる場合、下の記事が参考になった。 - [JavaでWebSocket使い方メモ - Qiita](https://qiita.com/opengl-8080/items/7ca8484c8579d264e239)