The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Usando WebSockets

Este guia explica como seu aplicativo Quarkus pode utilizar web sockets para criar aplicativos web interativas. Por ser a aplicação canônica de web socket, vamos criar um aplicativo de bate-papo simples.

Pré-requisitos

Para concluir este guia, você precisa:

  • Cerca de 15 minutos

  • Um IDE

  • JDK 17+ installed with JAVA_HOME configured appropriately

  • Apache Maven 3.9.9

  • Opcionalmente, o Quarkus CLI se você quiser usá-lo

  • Opcionalmente, Mandrel ou GraalVM instalado e configurado apropriadamente se você quiser criar um executável nativo (ou Docker se você usar uma compilação de contêiner nativo)

Arquitetura

Neste guia, criamos um aplicativo de bate-papo simples usando soquetes da Web para receber e enviar mensagens a outros usuários conectados.

Architecture

Solução

Recomendamos que você siga as instruções nas próximas seções e crie o aplicativo passo a passo. No entanto, você pode pular diretamente para o exemplo completo.

Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git, ou baixe um arquivo.

A solução está localizada no websockets-quickstart diretório.

Criar o projeto Maven

Primeiro, precisamos de um novo projeto. Crie um novo projeto com o seguinte comando:

CLI
quarkus create app org.acme:websockets-quickstart \
    --extension='websockets' \
    --no-code
cd websockets-quickstart

Para criar um projeto Gradle, adicione a opção --gradle ou --gradle-kotlin-dsl.

Para obter mais informações sobre como instalar e usar a CLI do Quarkus, consulte o guia Quarkus CLI.

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.16.3:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=websockets-quickstart \
    -Dextensions='websockets' \
    -DnoCode
cd websockets-quickstart

Para criar um projeto Gradle, adicione a opção '-DbuildTool=gradle' ou '-DbuildTool=gradle-kotlin-dsl'.

Para usuários do Windows:

  • Se estiver usando cmd, (não use barra invertida '\' e coloque tudo na mesma linha)

  • Se estiver usando o Powershell, envolva os parâmetros '-D' entre aspas duplas, por exemplo, '"-DprojectArtifactId=websockets-quickstart"'

Esse comando gera o projeto (sem nenhuma classe) e importa a extensão websockets .

Se você já configurou seu projeto Quarkus, pode adicionar a extensão websockets ao seu projeto executando o seguinte comando no diretório base do seu projeto:

CLI
quarkus extension add websockets
Maven
./mvnw quarkus:add-extension -Dextensions='websockets'
Gradle
./gradlew addExtension --extensions='websockets'

Isto irá adicionar o seguinte trecho no seu arquivo de build:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-websockets</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-websockets")
Se você deseja utilizar apenas o cliente WebSocket, você deve incluir quarkus-websockets-client.

Manuseio de web sockets

Nosso aplicativo contém uma única classe que lida com os Web Sockets. Crie a classe org.acme.websockets.ChatSocket no diretório src/main/java . Copie o seguinte conteúdo para o arquivo criado:

package org.acme.websockets;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import jakarta.websocket.Session;

@ServerEndpoint("/chat/{username}")         (1)
@ApplicationScoped
public class ChatSocket {

    Map<String, Session> sessions = new ConcurrentHashMap<>(); (2)

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        broadcast("User " + username + " joined");
        sessions.put(username, session);
    }

    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessions.remove(username);
        broadcast("User " + username + " left");
    }

    @OnError
    public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
        sessions.remove(username);
        broadcast("User " + username + " left on error: " + throwable);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        broadcast(">> " + username + ": " + message);
    }

    private void broadcast(String message) {
        sessions.values().forEach(s -> {
            s.getAsyncRemote().sendObject(message, result ->  {
                if (result.getException() != null) {
                    System.out.println("Unable to send message: " + result.getException());
                }
            });
        });
    }

}
1 Configure a URL do Web Socket
2 Armazena os web sockets atualmente abertos

Um frontend da Web sofisticado

Todos os aplicativos de bate-papo precisam de uma boa interface de usuário. Bem, este pode não ser tão bom, mas funciona. O Quarkus automaticamente serve os recursos estáticos contidos no diretório META-INF/resources . Crie o diretório src/main/resources/META-INF/resources e copie esse arquivo index.html para ele.

Executar o aplicativo

Agora, vamos ver nosso aplicativo em ação. Execute-o com:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

Em seguida, abra as duas janelas do navegador em http://localhost:8080/:

  1. Digite um nome na área de texto superior (use dois nomes diferentes).

  2. Clique em conectar

  3. Enviar e receber mensagens

Application

Como de costume, a aplicação pode ser empacotada utilizando:

CLI
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

E executada com java -jar target/quarkus-app/quarkus-run.jar.

Você também pode criar o executável nativo usando:

CLI
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

Você também pode testar seus aplicativos de soquete da Web usando a abordagem detalhada aqui .

Clientes WebSocket

O Quarkus também contém um cliente WebSocket. Você pode chamar ContainerProvider.getWebSocketContainer().connectToServer para criar uma conexão WebSocket. Por padrão, o artefato quarkus-websockets inclui suporte tanto para cliente quanto para servidor. No entanto, se você deseja apenas o cliente, pode incluir quarkus-websockets-client.

Ao se conectar ao servidor, o usuário pode passar a classe do endpoint do cliente anotado que deseja usar ou uma instância de jakarta.websocket.Endpoint . Se estiver usando o endpoint anotado, o usuário poderá usar exatamente as mesmas anotações que pode usar no servidor, exceto que ele deve ser anotado com @ClientEndpoint em vez de @ServerEndpoint .

O exemplo abaixo mostra o client sendo usado para testar o endpoint de bate-papo acima.

package org.acme.websockets;

import java.net.URI;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

import jakarta.websocket.ClientEndpoint;
import jakarta.websocket.ContainerProvider;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class ChatTest {

    private static final LinkedBlockingDeque<String> MESSAGES = new LinkedBlockingDeque<>();

    @TestHTTPResource("/chat/stu")
    URI uri;

    @Test
    public void testWebsocketChat() throws Exception {
        try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
            Assertions.assertEquals("CONNECT", MESSAGES.poll(10, TimeUnit.SECONDS));
            Assertions.assertEquals("User stu joined", MESSAGES.poll(10, TimeUnit.SECONDS));
            session.getAsyncRemote().sendText("hello world");
            Assertions.assertEquals(">> stu: hello world", MESSAGES.poll(10, TimeUnit.SECONDS));
        }
    }

    @ClientEndpoint
    public static class Client {

        @OnOpen
        public void open(Session session) {
            MESSAGES.add("CONNECT");
            // Send a message to indicate that we are ready,
            // as the message handler may not be registered immediately after this callback.
            session.getAsyncRemote().sendText("_ready_");
        }

        @OnMessage
        void message(String msg) {
            MESSAGES.add(msg);
        }

    }

}

Mais informações sobre o WebSocket

A implementação do Quarkus WebSocket é uma implementação do Jakarta Websockets .

Conteúdo Relacionado