web-dev-qa-db-fra.com

Push Websocket planifié avec Spring Boot

Je suis un peu nouveau pour Spring-Boot et Spring en général. Je me suis retrouvé dans un projet et mon premier "exercice" pour me mouiller les pieds est de créer une fonction de flux d'actualités simple sur le front-end qui se mettra automatiquement à jour via les notifications Push de Websocket.

Les technologies impliquées sont:

  • Angulaire pour l'application frontale générale
  • SockJS pour créer une communication websocket
  • Stomp over webosocket pour recevoir des messages d'un courtier de messages
  • Webbockets Springboot
  • Stomp Message Broker (le Java)

Ce que je veux réaliser à l'avant est:

  1. Créer une connexion Websocket lorsque la vue est chargée
  2. Créer un fournisseur de pédales à l'aide de cette prise Web
  3. Demandez à mon client de s'y abonner
  4. Attraper les messages poussés du serveur et mettre à jour la vue angular

En ce qui concerne le code côté serveur:

  1. Configurer les trucs websocket et gérer la connexion
  2. Demandez au serveur d'envoyer des messages tous les X fois (via un exécuteur ou @Scheduled?).

Je pense avoir tout accompli jusqu'à présent, sauf la dernière partie du code côté serveur. L'exemple que je suivais utilise le websocket en mode duplex intégral et lorsqu'un client envoie quelque chose, le serveur répond immédiatement à la file d'attente de messages et tous les clients abonnés se mettent à jour. Mais ce que je veux, c'est que le serveur lui-même envoie quelque chose sur Stomp SANS attendre que le client fasse des requêtes.

Au début, j'ai créé un ressort @Controller Et y ai ajouté une méthode avec l'annotation @SendTo("/my/subscribed/path"). Cependant, je ne sais pas comment le déclencher. J'ai également essayé d'ajouter @Scheduled Mais cette annotation ne fonctionne que sur les méthodes avec le type de retour void (et je retourne un objet NewsMessage).

Essentiellement, ce dont j'ai besoin, c'est que le client initialise une connexion Websocket et qu'après que le serveur commence à y envoyer des messages à un intervalle défini (ou chaque fois qu'un événement est déclenché, cela n'a pas d'importance pour l'instant). En outre, chaque nouveau client doit écouter la même file d'attente de messages et recevoir les mêmes messages.

33
Konstantine

Tout d'abord, vous devez activer votre websocket au printemps, avant de vous assurer que vous disposez des dépendances correspondantes dans votre pom.xml

Par exemple le plus important:

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

Ensuite, vous devez avoir votre configuration en place. Je vous suggère de commencer avec un simple courtier.

@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");
    }

}

Votre contrôleur devrait alors ressembler à ceci. Quand votre application AngularJs ouvrira une connexion sur '/ portfolio' et enverra un abonnement à cette chaîne /topic/greeeting vous le recevrez dans le contrôleur et répondrez à tous les utilisateurs abonnés.

@Controller
public class GreetingController {

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

Concernant votre question de planificateur, vous devez l'activer via la configuration:

@Configuration
@EnableScheduling
public class SchedulerConfig{}

Et puis planifiez-le:

@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());
    }
}

J'espère que ce concept et les étapes clarifiées doivent être pris pour que les choses fonctionnent pour vous.

// Remarque: vous avez modifié @Scheduler en @Scheduled

38
RMachnik

Tout d'abord, vous ne pouvez pas envoyer de messages (Push) aux clients sans leurs abonnements.

Deuxièmement, pour envoyer des messages à tous les abonnés, vous devriez jeter un œil au côté abstraction topic.

C'est l'un des principes fondamentaux de STOMP.

Je pense que tu vas bien avec @Scheduled, mais il vous suffit d'injecter SimpMessagingTemplate pour envoyer des messages au courtier STOMP pour pousser ensuite.

Voir aussi la configuration XML de Spring WebSockets ne fournit pas brokerMessagingTemplate

7
Artem Bilan