https://a.storyblok.com/f/270183/614640/4642d493ac/websocket-server-spark.png

Criação de um servidor WebSocket com o Spark Framework

Publicado em May 3, 2021

Tempo de leitura: 4 minutos

WebSocket é um protocolo que permite a comunicação entre o servidor e o navegador. Ele apresenta uma vantagem em relação ao HTTP RESTful, pois as comunicações são bidirecionais e em tempo real. Isso permite que o servidor notifique o cliente a qualquer momento, em vez de o cliente verificar se há atualizações em intervalos regulares.

Nesta série de posts, vou mostrar a vocês três maneiras diferentes de criar um servidor WebSocket em Java usando Spring Boot, o Spark Frameworke a API Java para WebSockets.

Pré-requisitos

Você utilizará o Gradle para gerenciar suas dependências e executar seu aplicativo.

Além disso, você precisará verificar se tem uma cópia do JDK instalada. Vou usar o JDK 8 neste tutorial.

WebSockets com o Spark Framework

Spark é um microframework para a criação de aplicativos web em Java e Kotlin.

Criar o projeto

Você usará o Gradle para inicializar um novo aplicativo Java. É possível usar o comando a seguir para criar um diretório para o seu projeto, acessar esse diretório e inicializar o aplicativo:

mkdir websocket-spark-framework cd websocket-spark-framework gradle init --type=java-application

Adicionar a dependência do Spark

Adicione a seguinte dependência ao dependencies bloco de build.gradle:

compile 'com.sparkjava:spark-core:2.7.2'

Ao contrário de A criação de um servidor WebSocket com o Spring Boot, os WebSockets com o Spark só funcionam com o Jetty , e você precisará definir o caminho e o manipulador antes de quaisquer rotas HTTP.

Criar o manipulador WebSocket

As mensagens WebSocket podem ser tanto de texto quanto binárias. Você vai criar um manipulador capaz de lidar com ambos os tipos de mensagem.

Crie uma nova classe chamada WebSocketHandler e anote-a com @WebSocket:

import org.eclipse.jetty.websocket.api.annotations.WebSocket;

@WebSocket
public class WebSocketHandler {
    
}

Cada evento que o WebSocketHandler trata é definido por uma anotação. Você pode usar a @OnWebSocketMessage anotação para marcar métodos destinados a receber eventos binários ou de texto.

Para fins de demonstração, você vai criar um servidor de eco que irá reenviar a mensagem recebida de volta ao remetente.

Adicione os seguintes métodos:

@OnWebSocketMessage
public void handleTextMessage(Session session, String message) throws IOException {
    System.out.println("New Text Message Received");
    session.getRemote().sendString(message);
}

@OnWebSocketMessage
public void handleBinaryMessage(Session session, byte[] buffer, int offset, int length) throws IOException {
    System.out.println("New Binary Message Received");
    session.getRemote().sendBytes(ByteBuffer.wrap(buffer));
}

Observe que a assinatura do método determina qual tipo de mensagem o método irá processar. Consulte a OnWebSocketMessage documentação sobre anotações para obter uma lista das assinaturas de método suportadas.

Registrar o manipulador de WebSocket

Para utilizar o WebSocketHandler, é necessário registrá-lo.

Abra a App classe que o Gradle criou para você. Exclua o getGreeting método e o conteúdo do main método, já que você não precisará de nenhum dos dois.

Dentro do método principal, adicione o seguinte para registrar o WebSocketHandler no /socket caminho:

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    webSocket("/socket", WebSocketHandler.class);
}

Crie um cliente para testar seu aplicativo

Você precisará criar um cliente para testar seu servidor WebSocket. É recomendável testar o envio tanto de mensagens de texto quanto de mensagens binárias. Isso pode ser feito com JavaScript.

Crie a resources pasta dentro da src/main pasta. Dentro da resources pasta, crie a static pasta.

Adicione o seguinte ao index.html dentro da src/main/resources/static pasta:

<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>

Agora você precisará configurar o Spark para localizar seu index.html e para inicializar o servidor quando o aplicativo for executado. Você também pode definir a porta na qual o servidor ficará à espera de conexões.

No interior do main método da App classe, adicione o seguinte abaixo webSocket:

staticFileLocation("static");
port(8080)
init();

Iniciar o aplicativo

Seu servidor WebSocket já está pronto. Inicie seu aplicativo usando o gradle run comando dentro do diretório do aplicativo.

Você pode acessar sua inscrição em http://localhost:8080 onde você será direcionado para a seguinte página:

Sample JavaScript-enabled client for testing the WebSocket server.Connected

A mensagem “conectado” indica que o cliente JavaScript conseguiu estabelecer uma conexão.

Tente enviar uma mensagem de texto digitando no campo de entrada e clicando no botão “Enviar”. Tente também fazer o upload de uma imagem. Em ambos os casos, você deverá ver a mesma mensagem e a mesma imagem exibidas de volta.

Sample JavaScript-enabled client showing a text and binary message echoed back.Connected Check

Conclusão

Neste tutorial, você aprendeu a criar um servidor WebSocket usando o Spark, capaz de receber mensagens tanto binárias quanto de texto. O código final deste tutorial pode ser encontrado em nexmo-community/websocket-spark-framework .

Quer implementar WebSockets em seu Spring ? Talvez você queira aprender sobre Criar um servidor WebSocket com o Spring Boot?

Não tem frameworks? Tudo bem! Fique ligado no próximo tutorial, onde vou mostrar como criar um servidor WebSocket usando a API Java para WebSockets.

Você sabia que é possível usar o WebSocket como um ponto de extremidade em um Objeto Nexmo Call Control? Veja este exemplo sobre Transmissão de chamadas para um navegador com Voice WebSockets.

Quer ver um uso interessante dos WebSockets? Dê uma olhada no nexmo-community/dtmf-snake para ver um código que permite jogar o jogo da cobra usando sinais de multifrequência de dois tons.

Compartilhar:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Steve CrowEx-funcionários da Vonage

Steve se autodenomina “Mathlete” e “Rei da Ironia”. Ele também é apaixonado por galgos, quebra-cabeças de torção e jogos de tabuleiro europeus. Quando não está falando de matemática para quem não entende de matemática, nem de Java para quem não entende de Java, ele pode ser encontrado tomando café e programando.