web-dev-qa-db-ja.com

Spring Bootによるスケジュールされたwebsocketプッシュ

私は、スプリングブーツとスプリングの一般的な初心者です。私はプロジェクトに投入されましたが、足を濡らすための最初の「運動」は、websocket Push通知を介して自動的に更新されるシンプルなニュースフィード機能をフロントエンドに作成することです。

関連する技術は次のとおりです。

  • 一般的なフロントエンドアプリケーション向けのAngular
  • Websocket通信を作成するためのSockJS
  • メッセージブローカーからメッセージを受信するためのwebosocketのストンプ
  • Springboot Websockets
  • Stomp Message Broker(Java関連フレームワーク)

フロントエンドで達成したいことは:

  1. ビューが読み込まれたときにWebsocket接続を作成する
  2. そのWebSocketを使用してストンププロバイダーを作成する
  3. クライアントにサブスクライブしてもらう
  4. サーバーがプッシュしたメッセージをキャッチし、angularビューを更新します

サーバー側のコードに関して:

  1. WebSocketスタッフを設定し、接続を管理します
  2. サーバーにX時間ごとにメッセージをプッシュさせる(エグゼキューターまたは_@Scheduled_?を使用)。

サーバー側コードの最後の部分を除いて、これまでのところすべてを達成していると思います。私がフォローしていた例では、websocketを全二重モードで使用し、クライアントが何かを送信すると、サーバーはメッセージキューに即座に応答し、サブスクライブされたすべてのクライアントが更新されます。しかし、私が望むのは、サーバー自体がStompを介して何かを送信し、クライアントが要求を出すのを待つことではないということです。

最初に、スプリング_@Controller_を作成し、@SendTo("/my/subscribed/path")アノテーションを使用してメソッドを追加しました。しかし、私はそれをトリガーする方法がわかりません。また、_@Scheduled_を追加しようとしましたが、この注釈はvoid戻り値型のメソッドでのみ機能します(そしてNewsMessageオブジェクトを返しています)。

基本的に私が必要とするのは、クライアントにwebsocket接続を初期化させ、サーバーが設定された間隔で(またはイベントがトリガーされるたびに問題にならないように)メッセージをプッシュし始めることです。また、すべての新しいクライアントは同じメッセージキューをリッスンし、同じメッセージを受信する必要があります。

33
Konstantine

まず、websocketを春に有効にする必要があります。それから、pom.xml

例えば、最も重要なもの:

         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

次に、設定を行う必要があります。シンプルなブローカーから始めることをお勧めします。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

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

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

}

コントローラーは次のようになります。 AngularJsアプリが '/ portfolio'で接続を開き、このチャンネルにサブスクリプションを送信すると/topic/greeetingこれをコントローラーで受け取り、購読しているすべてのユーザーに応答します。

@Controller
public class GreetingController {

    @MessageMapping("/greeting")
    public String handle(String greeting) {
        return "[" + getTimestamp() + ": " + greeting;
    }
}

スケジューラの質問に関しては、設定で有効にする必要があります。

@Configuration
@EnableScheduling
public class SchedulerConfig{}

そして、それをスケジュールします。

@Component
public class ScheduledUpdatesOnTopic{

    @Autowired
    private SimpMessagingTemplate template;
    @Autowired
    private final MessagesSupplier messagesSupplier;

    @Scheduled(fixedDelay=300)
    public void publishUpdates(){
        template.convertAndSend("/topic/greetings", messagesSupplier.get());
    }
}

これが何らかの形で明確化された概念とステップがあなたのために物事を機能させるために取られる必要があることを願っています。

//注:@Schedulerを@Scheduledに変更しました

38
RMachnik

まず、サブスクリプションなしでクライアントにメッセージを送信(プッシュ)することはできません。

次に、すべてのサブスクライバーにメッセージを送信するには、topic抽象化側を確認する必要があります。

それがSTOMPの基本です。

私はあなたが@Scheduledが、その後プッシュするためにSTOMPブローカーにメッセージを送信するためにSimpMessagingTemplateを挿入する必要があります。

brokerMessagingTemplateを提供しないSpring WebSockets XML構成 も参照してください。

7
Artem Bilan