https://d226lax1qjow5r.cloudfront.net/blog/blogposts/creating-a-websocket-server-with-spring-boot/springboot_websocket.png

Creación de un servidor WebSocket con Spring Boot

Publicado el June 24, 2021

Tiempo de lectura: 3 minutos

WebSocket es un protocolo que permite la comunicación entre el servidor y el navegador. Tiene una ventaja sobre RESTful HTTP porque las comunicaciones son bidireccionales y en tiempo real. Esto permite que el servidor notifique al cliente en cualquier momento, en lugar de que el cliente busque actualizaciones a intervalos regulares.

En esta serie de posts, voy a mostrarte tres formas diferentes de crear un servidor WebSocket en Java utilizando Spring Booty el Spark Frameworky la API de Java para WebSockets.

Requisitos previos

Utilizará Gradle para gestionar tus dependencias y ejecutar tu aplicación.

Además, tendrás que asegurarte de que tienes una copia del JDK instalada. Voy a utilizar JDK 8 en este tutorial.

WebSockets con Spring Boot

Spring Boot le permite crear aplicaciones Spring de producción dentro de un JAR ejecutable.

Crear el proyecto

Puede utilizar Spring Initializr para arrancar su aplicación y seleccionar los paquetes que necesite.

Para este ejemplo, necesitará la Websocket dependencia. También voy a estar usando Gradle, por lo que querrá cambiarlo para generar un proyecto Gradle.

Spring Initializer HomepageSpring Initializer Homepage

Al hacer clic en el botón Generar proyecto se descargará un archivo zip. Descomprímalo en un directorio de su elección.

Crear el manejador WebSocket

Los mensajes WebSocket pueden ser tanto de texto como binarios. Vas a crear un manejador que pueda manejar ambos mensajes.

Crear una nueva clase llamada WebSocketHandler que extienda AbstractWebSocketHandler en el com.example.websocketdemo paquete. AbstractWebSocketHandler requiere que implementes dos métodos handleTextMessage y handleBinaryMessage que son llamados cuando se recibe un nuevo mensaje de texto o binario.

Para fines de demostración, vas a crear un servidor de eco que hará eco del mensaje recibido de vuelta al remitente.

Añade las siguientes implementaciones:

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
    System.out.println("New Text Message Received");
    session.sendMessage(message);
}

@Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws IOException {
    System.out.println("New Binary Message Received");
    session.sendMessage(message);
}

Registrar el WebSocket Handler

Para poder utilizar el WebSocketHandlerdebe estar registrado en el directorio WebSocketHandlerRegistry. Lo siguiente logrará dos cosas:

  1. Registrará el WebSocketHandler en la /socket ruta.

  2. Permitirá a todos los clientes del navegador enviar mensajes al servidor. No será necesario que tengan un origen específico.

Crea una nueva clase llamada WebSocketConfiguration que implemente la interfaz WebSocketConfigurer en el paquete com.example.websocketdemo paquete.

Anote WebSocketConfiguration con las etiquetas @Configuration y @EnableWebSocket anotaciones.

WebSocketConfigurer requiere que implemente un método registerWebSocketHandlers método.

Añada la siguiente implementación al registro WebSocketHandler:

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(new WebSocketHandler(), "/socket").setAllowedOrigins("*");
}

Dado que, además de mensajes de texto, tratará con mensajes binarios, es una buena idea establecer el tamaño máximo de los mensajes binarios. Este es un valor almacenado en el contenedor del servidor. Puedes anular este valor inyectando una nueva fábrica de contenedores de servidor como parte de tu fichero WebSocketConfiguration.

Añade el siguiente código para inyectar un nuevo ServletServerContainerFactoryBean en WebSocketConfiguration por encima del método registerWebSocketHandlers que has añadido anteriormente:

@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxBinaryMessageBufferSize(1024000);
    return container;
}

Esto permitirá cargar una imagen de hasta 1 MB de tamaño.

Cree un cliente para probar su aplicación

Necesitarás crear un cliente para probar tu servidor WebSocket. Usted querrá probar el envío de mensajes de texto y binarios. Esto se puede lograr con JavaScript.

Añade lo siguiente a index.html dentro de la carpeta src/main/resources/static carpeta:

<html>
<head>
    <style>
        #messages {
            text-align: left;
            width: 50%;
            padding: 1em;
            border: 1px solid black;
        }
    </style>
    <title>Sample WebSocket Client</title>
</head>
<body>
<div class="container">
    <div id="messages" class="messages"></div>
    <div class="input-fields">
        <p>Type a message and hit send:</p>
        <input id="message"/>
        <button id="send">Send</button>

        <p>Select an image and hit send:</p>
        <input type="file" id="file" accept="image/*"/>

        <button id="sendImage">Send Image</button>
    </div>
</div>
</body>
<script>
    const messageWindow = document.getElementById("messages");

    const sendButton = document.getElementById("send");
    const messageInput = document.getElementById("message");

    const fileInput = document.getElementById("file");
    const sendImageButton = document.getElementById("sendImage");

    const socket = new WebSocket("ws://localhost:8080/socket");
    socket.binaryType = "arraybuffer";

    socket.onopen = function (event) {
        addMessageToWindow("Connected");
    };

    socket.onmessage = function (event) {
        if (event.data instanceof ArrayBuffer) {
            addMessageToWindow('Got Image:');
            addImageToWindow(event.data);
        } else {
            addMessageToWindow(`Got Message: ${event.data}`);
        }
    };

    sendButton.onclick = function (event) {
        sendMessage(messageInput.value);
        messageInput.value = "";
    };

    sendImageButton.onclick = function (event) {
        let file = fileInput.files[0];
        sendMessage(file);
        fileInput.value = null;
    };

    function sendMessage(message) {
        socket.send(message);
        addMessageToWindow("Sent Message: " + message);
    }

    function addMessageToWindow(message) {
        messageWindow.innerHTML += `<div>${message}</div>`
    }

    function addImageToWindow(image) {
        let url = URL.createObjectURL(new Blob([image]));
        messageWindow.innerHTML += `<img src="${url}"/>`
    }
</script>
</html>

Iniciar la aplicación

Su servidor WebSocket está ahora completo. Inicie su aplicación utilizando el comando gradle bootRun dentro del directorio de la aplicación.

Puede acceder a su solicitud en http://localhost:8080 donde aparecerá la siguiente página:

Sample JavaScript-enabled client for testing the WebSocket serverSample JavaScript-enabled client for testing the WebSocket server

El mensaje "conectado" indica que el cliente JavaScript ha podido establecer una conexión.

Intenta enviar un mensaje de texto escribiendo en el campo de entrada y pulsando el botón enviar. Prueba también a subir una imagen. En ambos casos, debería recibir el mismo mensaje y la misma imagen.

Sample JavaScript-enabled client showing a text and binary message echoed backSample JavaScript-enabled client showing a text and binary message echoed back

Conclusión

En este tutorial has aprendido a crear un servidor WebSocket usando Spring Boot que puede recibir tanto mensajes binarios como de texto. El código terminado para este tutorial se puede encontrar en la página web nexmo-community/websocket-spring-boot repositorio.

¿Has probado Spark Framework? Quizás quieras ver cómo Crear un servidor WebSocket utilizando el Spark Framework.

¿Sabía que puede utilizar WebSocket como endpoint en un Objeto de control de llamada? Vea este ejemplo en Transmisión de llamadas a un navegador con WebSockets de Voice.

Compartir:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Steve CrowAntiguos alumnos de Vonage

Steve se autoproclama matemático y rey de la sátira. También le gustan los galgos, los rompecabezas enrevesados y los juegos de mesa europeos. Cuando no está hablando de matemáticas con gente que no es matemática o de Java con gente que no es de Java, se le puede encontrar tomando café y hackeando código.