Newer
Older
WebSocketServerSample / README.md
# 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)