https://a.storyblok.com/f/270183/1368x665/fba399d139/java-websockets_24.png

Cómo crear un servidor WebSocket con la API Java para WebSockets

Publicado el July 5, 2021

Tiempo de lectura: 7 minutos

Este artículo se actualizó en agosto de 2025

WebSocket es un protocolo que permite que un servidor y un cliente (como un navegador o una aplicación móvil) se comuniquen en tiempo real. A diferencia de RESTful HTTP, en el que el cliente tiene que estar pendiente de las actualizaciones (un proceso llamado sondeo), WebSocket mantiene abierta una conexión bidireccional constante. Esto significa que el servidor puede enviar actualizaciones al cliente siempre que algo cambie, por lo que no es necesario esperar a que el cliente pregunte.

En este tutorial, le mostraremos cómo implementar un servidor WebSocket en Java utilizando la API Jakarta WebSocket (JSR 356).

Requisitos previos

API Java para WebSockets

Introducida en Java EE 7, la API de Java para WebSocketso JSR 356, es una especificación que los desarrolladores de Java pueden utilizar para integrar WebSockets en sus aplicaciones.

Permite a los desarrolladores escribir sus aplicaciones basadas en WebSocket de forma completamente independiente de la implementación de su contenedor. Para esta guía, se utilizará Tomcat. Sin embargo, debido a que usarás JSR 356, cualquier otro contenedor web que soporte Jakarta EE 9 o posterior debería funcionar.

Crear el proyecto

Utilizarás Gradle para inicializar una nueva aplicación Java. Puedes usar el siguiente comando para crear un directorio para tu proyecto, navegar a ese directorio e inicializar la aplicación:

mkdir websocket-java-api cd websocket-java-api

Crea un nuevo proyecto Gradle:

  1. Ejecute gradle init --type=java-application comando

  2. Seleccione Groovy como lenguaje de script

  3. Seleccione JUnit Jupiter como marco de pruebas

  4. Dejar por defecto Project name

  5. Dejar por defecto Source package

Añadir la dependencia API Java WebSocket

Añada la siguiente dependencia al bloque dependencies del archivo app/build.gradle archivo:

implementation 'jakarta.websocket:jakarta.websocket-api:2.1.1'

Jakarta EE 9+ utiliza el espacio de nombres jakarta.websocket en lugar de javax.websockety Tomcat 10+ sigue esta convención.

Crear el punto final WebSocket

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

La anotación @ServerEndpoint se utiliza para decorar una clase y declararla como punto final WebSocket. La anotación toma un argumento de ruta que define dónde se podrá acceder al punto final.

Crea una nueva clase llamada WebSocketEndpoint dentro de la carpeta src/main/java/websocket/java/api y añade el siguiente código:

import jakarta.websocket.server.ServerEndpoint;
import jakarta.websocket.OnMessage;

@ServerEndpoint("/socket")
public class WebSocketEndpoint {
    @OnMessage
    public String handleTextMessage(String message) {
        System.out.println("New Text Message Received");
        return message;
    }

    @OnMessage(maxMessageSize = 1024000)
    public byte[] handleBinaryMessage(byte[] buffer) {
        System.out.println("New Binary Message Received");
        return buffer;
    }
}

La anotación @OnMessage vincula métodos Java a mensajes WebSocket de texto o binarios entrantes. La firma del método determina el tipo de mensaje que gestiona. Por ejemplo, String se utiliza para texto y byte[] es para binario.

En este ejemplo, estás creando un servidor echo que devuelve el mismo mensaje que recibe. El parámetro maxMessageSize en el manejador binario permite al servidor aceptar grandes cargas como archivos de imagen. Probarás esto usando un cliente basado en navegador más adelante en el tutorial.

Cree un cliente para probar su aplicación

Necesitarás crear un cliente para probar tu servidor WebSocket. Querrá probar el envío de mensajes de texto y binarios. Esto se puede lograr con una simple aplicación escrita en HTML y JavaScript.

Cree la carpeta webapp dentro de la carpeta src/main carpeta.

Añade lo siguiente a index.html dentro de la carpeta src/main/webapp 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>

Integrar y configurar Tomcat

A diferencia de Creación de un servidor WebSocket con Spring Booto Creación de un servidor WebSocket con Spark Frameworkinicialmente no hay un servidor incrustado para ejecutar su aplicación.

El Gretty para Gradle se puede utilizar para incrustar una variedad de contenedores.

En primer lugar, aplique el plugin Gretty a build.gradle añadiendo lo siguiente al bloque plugins bloque:

plugins {
    id 'org.gretty' version '4.1.7'
}

En segundo lugar, tendrá que configurar Gretty para utilizar Tomcat como contenedor de servlets, y establecer la ruta de contexto en / en aras de la simplicidad.

Añada el siguiente bloque a build.gradle:

gretty {
    servletContainer = 'tomcat10'
    contextPath = '/'
}

compatible con Gretty 3.0.5+ tomcat10 para compatibilidad con Jakarta EE 9+ (jakarta.* namespaces).

Ten en cuenta que, por defecto, Gretty utilizará Jetty como contenedor de servlets. Esta misma guía también se ejecutará en Jetty, pero ese es el mismo contenedor que incorporan tanto Spring Boot como el framework Spark y quería mostrar algo diferente.

Iniciar la aplicación

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

Asegúrese de que su JAVA_HOME está configurado en JDK 21 antes de ejecutar la aplicación:

echo $JAVA_HOME

Deje abierta la ventana del terminal.

Puede acceder a su solicitud abriendo http://localhost:8080 en el navegador.

Aparecerá la siguiente página:

Sample JavaScript-enabled client for testing the WebSocket serverSample JavaScript-enabled client for testing the WebSocket serverEl 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 back.Sample JavaScript-enabled client showing a text and binary message echoed back.

Conclusión

Ha creado con éxito un servidor WebSocket utilizando la API Java para WebSockets (JSR 356), lo ha incrustado en un contenedor Tomcat con Gretty y lo ha probado con un cliente sencillo HTML y JavaScript.

Esta configuración permite gestionar la comunicación bidireccional en tiempo real entre el servidor y los clientes, tanto con datos de texto como binarios.

Los siguientes pasos podrían incluir la adición de autenticación, el manejo de más tipos de mensajes o la integración con sus aplicaciones Java existentes.

¿Tienes alguna pregunta o algo que compartir? Únete a la conversación en Slack de la comunidad de Vonagey mantente actualizado con el Boletín para desarrolladoressíguenos en X (antes Twitter)suscríbete a nuestro canal de YouTube para ver tutoriales en video, y sigue la página de página para desarrolladores de Vonage en LinkedInun espacio para que los desarrolladores aprendan y se conecten con la comunidad. Mantente conectado, comparte tu progreso y entérate de las últimas noticias, consejos y eventos para desarrolladores.

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.