blog

Spring BootでWebSocketを使う

WebSocketはサーバーとクライアント間の双方向通信を可能にする長い接続技術です。 サーバーはアプリケーションをビルドするための情報をクライアントに積極的にプッシュすることができます build....

Mar 13, 2019 · 5 min. read
シェア

Spring BootでWebSocketを使う

WebSocketはサーバーとクライアント間の双方向通信を可能にする長い接続技術で、サーバーがクライアントに能動的に情報をプッシュすることができます。

アプリケーションを構築する

依存関係を追加する

  • build.gradle
dependencies {
 compile("org.springframework.boot:spring-boot-starter-websocket")
 compile("org.webjars:webjars-locator-core")
 compile("org.webjars:sockjs-client:1.0.2")
 compile("org.webjars:stomp-websocket:2.3.3")
 compile("org.webjars:bootstrap:3.3.7")
 compile("org.webjars:jquery:3.1.0")

 testCompile("org.springframework.boot:spring-boot-starter-test")
}

構成

  • WebSocketConfig.java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

 @Override
 public void configureMessageBroker(MessageBrokerRegistry registry) {
 registry.enableSimpleBroker("/topic");
 registry.setApplicationDestinationPrefixes("/app");
 }

 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
 registry.addEndpoint("/socket").withSockJS();
 }
}

ここで、/topic はクライアントに送信するメッセージのパス名の接頭辞、/app はサービス・エンドポイントに送信するメッセージのパス名の接頭辞、/socket はクライアントが接続する際に使用するメッセージのパス名の接頭辞です。

グループメッセージング

メッセージを一括送信すると、そのメッセージを購読しているすべてのクライアントにメッセージを送信できます。 SendToまたはorg.springframework.messaging.simp.SimpMessagingTemplate#convertAndSendを使用して送信

サーバー

  • アノテーションを使用して実現
 @MessageMapping("/message/broadcast")
 @SendTo("/response/message")
 public Message broadcastMessage(String title) {
 log.info("Receive new broadcast message from socket, title is :" + title);

 return Message.builder()
 .title(title)
 .content("Socket Broadcast:" + title + " content!")
 .createTime(LocalDateTime.now())
 .build();
 }
  • RESTインターフェイスコールによるメソッド実装
 @Autowired
 private SimpMessagingTemplate simpMessagingTemplate;

 @GetMapping("/message/broadcast")
 @ResponseBody
 public void sendBroadcastMessage(String title) {
 log.info("Receive new broadcast message from REST interface, title is :" + title);

 Message message = Message.builder()
 .title(title)
 .content("REST Broadcast:" + title + " content!")
 .createTime(LocalDateTime.now())
 .build();

 simpMessagingTemplate.convertAndSend("/response/message", message);
 }

クライアント

function a() {
    var bar = new SockJS('/socket');
    stompClient = Stomp.c(bar);
    stompClient.connect({}, function  {
        stompClient.subscribe('/response/message', function  {
            console.log('Receive\x20message\x20from\x20server:' + obj);
        });
    });
}
function b() {
    stompClient.send('/request/message/broadcast', {}, 'Message');
}

テスト

  • アプリケーションを起動し、2つの異なるブラウザで localhost:8080アクセスします。
  • メッセージをブロードキャストして接続を確立し、メッセージを送信すると、両方のブラウザが送信したばかりのメッセージを受信したことがわかります。
  • RESTインターフェイス経由で
curl 'localhost:8080/message/broadcast?title=hello'

指定したクライアントに送信する

メッセージをブロードキャストすると、そのメッセージを購読しているすべてのクライアントにメッセージが送信されます。@SendToUserまたはorg.springframework.messaging.simp.SimpMessagingTemplate#convertAndSend

サーバー

指定のクライアントに送信します。クライアントには指定のユーザー名が必要です。継承により実装されています。

  • CustomPrinciple.java
@AllArgsConstructor
public class CustomPrinciple implements Principal {

 private String name;

 @Override
 public String getName() {
 return これ.name;
 }
}
  • CustomHandshakeHandler.java
@Slf4j
public class CustomHandshakeHandler extends DefaultHandshakeHandler {

 @Override
 protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
 String userId = UUID.randomUUID().toString();
 log.info("Current username is: {}", userId);
 return new CustomPrinciple(userId);
 }
}
 attributes) {
 String userId = UUID.randomUUID().toString();
 log.info(「Current username is: {}」, userId);
 return new CustomPrinciple(userId);


 }
}
  • WebSocketConfig.java
 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
 registry.addEndpoint("/socket")
 .setHandshakeHandler(new CustomHandshakeHandler())
 .withSockJS();

 }
  • アノテーションを使用して実現
 @MessageMapping("/message/specify")
 @SendToUser("/response/message")
 public Message speicifyMessage(String title) {
 log.info("Receive new specify message from socket, title is :" + title);

 return Message.builder()
 .title(title)
 .content("Socket Specify:" + title + " content!")
 .createTime(LocalDateTime.now())
 .build();
 }
  • メソッドを呼び出して実装
 @GetMapping("/message/specify")
 @ResponseBody
 public void sendSpecifyUserMessage(String title, String username) {
 log.info("Receive new specify message from REST interface, title is :" + title);

 Message message = Message.builder()
 .title(title)
 .content("REST Specify:" + title + " content!")
 .createTime(LocalDateTime.now())
 .build();

 simpMessagingTemplate.convertAndSendToUser(username, "/response/message", message);
 }

クライアント

function bar() {
    var b = new SockJS('/socket');
    stompClient = Stomp.a(b);
    stompClient.connect({}, function  {
        stompClient.subscribe('/user/response/message', function  {
            console.log('Receive\x20message\x20from\x20server:' + c);
        });
    });
}
function obj() {
    stompClient.send('/request/message/specify', {}, 'Message');
}

注意すべき点は、指定ユーザーへのメッセージ購読を送信する際に、/user接頭辞を追加する必要があるということです。

テスト

  • アプリケーションを起動し、2つの異なるブラウザで localhost:8080アクセスします。
  • 指定されたメッセージは接続を確立し、メッセージを送信します。このメッセージはメッセージを送信したブラウザのみが受信し、もう一方のブラウザは受信しません。
  • RESTインターフェース経由で接続できます: 接続を確立すると、コンソールに対応するユーザー名が表示されます。
curl 'localhost:8080/message/specify?title=hello&username=test'
Read next

IE11 for Windows 8.1 新機能の概要

Windows 8.1は10月18日に正式にリリースされ、新しいIE11ブラウザも一緒にリリースされます。本日、マイクロソフトは公式ブログを通じて、Windows 8.1に搭載されるIE11の新機能をすべて紹介し、「新しいIEブラウザはユーザーに深い印象を残すと信じています。

Mar 11, 2019 · 2 min read