21
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SpringBoot+WebSocketで特定のユーザーに情報を送る

21
Posted at

SpringBoot+WebSocketで特定のユーザーに情報を送る

SpringBootでWebSocketを使ってWebRTCのシグナリングサーバーを作ろうとしたらSpringのWebSocketに関する情報が今一つなくて苦労したので備忘も兼ねて。

ちなみに、STOMPの利用が前提。

やりたかったこと

  • WebSocketを使って、特定のユーザーにのみ情報を送る
  • ユーザーはSpringSecurityで管理されているものとする
  • 基本1対1通信

SpringBootでWebSocketを使うための準備

依存ライブラリの追加

EclipseのSTSを利用する場合

利用するものにメッセージング>WebSocketを追加

maven

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>

gradle


compile("org.springframework.boot:spring-boot-starter-websocket")
```

## Configの追加
以下のようなクラスをComponentScanのかかるところに置いておく

``` java
@Configuration
@EnableWebSocketMessageBroker //STOMPを用いたブローカーベースのWebSocketを有効化する 
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer //古い資料だとAbstractWebSocketMessageBrokerConfigurerを使えと書いてあるが、今はこちら。
{
	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		config.enableSimpleBroker("/queue", "/user");//サーバーサイドから送り返す先のprefix
		config.setApplicationDestinationPrefixes("/app");//MessageMappingのprefix
	}

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/ws").withSockJS();//ブローカーに管理させるエンドポイント。クライアントサイドでSockJsを利用する場合。
	}
}


```

## Controllerの実装

``` java
@Controller
public class WebSocketController {

	@Autowired//SpringBttoがよろしく作ってくれるので自分でConfigを書く必要はない
	private SimpMessagingTemplate simpMessagingTemplate;

	@MessageMapping("/test")//setApplicationDestinationPrefixesで指定した値を付け加えた、app/testに送信した値がここに来る
	public void sendMessage(Principal principal,//PrincipalはSpringSecurityと同様。ユーザー情報の取得に用いる
                            @Payload String message//クライアントサイドから送られたメッセージ
        ) {
           //何らかのロジックで送り先のユーザーID=toUserId(Principal.getUserName()で取れるもの)を取得する
           simpMessagingTemplate.convertAndSendToUser(toUserId, "/queue/test", sendMessage);//toUserIdが/user/queue/testをsubscribeしているところにsendMessageを送る
           //convertAndSendToUserは内部でよろしく特定のユーザー向けに宛先を調整してくれるので、
           //ここの開発者が細かい制御をする必要はない
	}
}
```

## Clientサイドの実装
前提として、

* stomp.js,sock.jsは読み込まれている
* SpringSecurityでのログインは済んでいる

ものとします。

```js
const socket = new SockJS('/ws'); //WebSocketConfig.registerStompEndpointsで指定したもの
const stompClient = Stomp.over(socket);
stompClient.connect({},function(frame){
    //接続成功時のコールバック関数
    stompClient.subscribe('/user/queue/test',function(result){//subscribe対象の指定
    //convertAndSendToUserの引数とsubscribeの引数が異なるので注意。userによる変換がかかるのでこちらはuserを指定。
        const sendMessage = result.body;//送信されたものはbodyで取り出す
    });
});

//何か送るとき
stompClient.send('/app/test',{},message);//WebSocketConfigで指定したapp + Controllerで指定したtest
//今回空で渡している第二引数はheaderを入れる部分

```

## その他注意点

### nginxを挟む時は注意
proxy内に以下を追記しないと400エラーが発生して接続できない

```conf
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
```
21
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?