WebSocket es un canal de comunicación full duplex que nos permite una conexión continua y bidireccional entre cliente y servidor.

Creando la aplicación de chat mas simple de lo que soy capaz voy a explicar como utilizar WebSockets en nuestra aplicación Spring Boot.

Cliente

Nuestro cliente, será una simple pagina HTML con un pequeño script JavaScript.
Las librerías JavaScript indispensables son:
JQuery: Librería que facilita el desarrollo JavaScript.
SocketJS-client: Librería que utiliza los socket nativos. En caso de no disponer de los mismos, utilizará una abstracción.
Stomp: Implementación en Javascript del protocolo STOMP. Protocolo muy similar a HTTP en el que los mensajes de texto se envían junto a su correspondiente acción (CONNECT, SEND, ABORT, etc).

Fichero index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Hello WebSocket</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <link href="/main.css" rel="stylesheet">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.3.0/sockjs.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
        <script src="/app.js"></script>
    </head>
    <body>
        <noscript><h2 style="color: #257eff">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
            enabled. Please enable
            Javascript and reload this page!</h2></noscript>
        <div id="main-content" class="container">
            <div class="row justify-content-md-center">
                <div class="col-md-8">
                    <div id="chat"></div>
                    <form class="navbar-form pull-left">
                        <input id="message-input" type="text" class="span2">
                        <button id="send" type="submit" class="btn btn-dark">Send</button>
                    </form>
                </div>
            </div>
        </div>
    </body>
</html>

Script app.js:

"use strict";

$(document).ready(function () {
    var stompClient = null;

    connect();

    $("#send").click(function (e) {
        e.preventDefault();
        stompClient.send("/app/broadcast", {}, 
            JSON.stringify({'text': $("#message-input").val(), 'from': ""}));
        $("#message-input").val("");
    });

    function connect() {
        var socket = new SockJS("/ws");
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/broadcast', function (message) {
                var $chatMessage = $("<div class='chat-message'></div>")
                    .append(JSON.parse(message.body).text + "<br>");
                $("#chat").append($chatMessage);
                if ($(".chat-message").length >= 14) {
                    $("#chat > .chat-message")[0].remove();
                }
            });
        });
    }
});

Como podéis comprobar, básicamente establecemos una conexión, y una vez establecida nos suscribimos a un topic.
En cuanto un cliente envía un mensaje, éste es reenviado al topic al que está suscrito.

Servidor

En el lado servidor especificaremos el endpoint que recibirá los mensajes a traves de WebSocket y el topic al que se suscribirán los clientes.

Dependencias

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

Crearemos nuestra clase para la configuración de los WebSocket:

package com.juanmorschrott.webSockets.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

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

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

}

La anotación @EnableWebSocketMessageBroker habilita la creación y uso de WebSockets.
El método enableSimpleBroker crea un único broker de mensajes al que poder suscribirse.
Por su parte setApplicationDestinationPrefixes configura uno o más prefijos para filtrar los destinos.
Por último addEndpoint declara el endpoint al que lanzarán los mensajes los distintos clientes.

El controlador desde el que gestionaremos los mensajes recibidos por los clientes es:

package com.juanmorschrott.webSockets.controller;

import com.juanmorschrott.webSockets.model.Message;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

@Controller
public class ChatController {

    @MessageMapping("/broadcast")
    @SendTo("/topic/broadcast")
    public Message broadcast(Message message) {
        Message broadcast = new Message();
        broadcast.setText(HtmlUtils.htmlEscape(message.getText()));
        return broadcast;
    }

}

En primer lugar añadimos la anotación @MessageMapping(“/broadcast”) que define que mensajes capturará nuestro endpoint. Mientras que @SendTo(“/topic/broadcast”) nos dice el destino al que enviaremos el valor retornado.

Conclusión

Como podéis ver es realmente simple utilizar WebSockets en SpringBoot. Utilizar el protocolo STOMP nos proporciona una manera de comunicarnos mas formal y estructurada.
Podéis encontrar el ejemplo aquí.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Translate