Iniciando o Server-Sent Events

Inicie o Server-Sent Events (SSE) para enviar e receber dados de um servidor e de clientes com um serviço de bate-papo.

Antes de Começar

O SSE faz parte do HTML5. Para iniciar o SSE, use um cliente Java™ , como Java API for RESTful Web Services (JAX-RS) 2,1 ou JavaScript.

Sobre esta Tarefa

O SSE foi introduzido pela primeira vez no HTML5. Um cliente, como um navegador, cria uma conexão HTTP com um servidor e envia uma solicitação inicial. No entanto, em vez de fechar a conexão, o cliente e o servidor mantêm a conexão aberta e o servidor envia dados para o cliente, conforme necessário. Em seguida, o cliente processa os dados como eventos. O servidor ou o cliente pode fechar a conexão, porém, se dois clientes permanecerem conectados, eles poderão ver eventos que o servidor envia.

Procedimento

  1. Inicie o SSE com o JAX-RS 2.1.

    O código do servidor a seguir mostra um recurso que dispara o SSE e envia dados de volta para um cliente específico. A conexão com o servidor permanece aberta para que o servidor possa enviar informações a qualquer momento. Este serviço RESTful de exemplo fornece informações de rádio para música. Crie o arquivo RadioInfoService.java no aplicativo da web.

        @GET
        @Path("/songDataStream")
        @Produces(MediaType.SERVER_SENT_EVENTS)
        public void songDataStream(@Context SseEventSink eventSink, @Context Sse sse) {
        Runnable r = new Runnable() {
          @Override
          public void run() {
            Song song = RadioService.getCurrentSong();
            while (song != null) {
              OutboundSseEvent event = sse.newEventBuilder()
                                          .mediaType(MediaType.APPLICATION_JSON_TYPE)
                                          .data(Song.class, song)
                                          .build();
              eventSink.send(event);
              try {
                Thread.currentThread().sleep(song.timeRemaining());
              } catch (InterruptedException ex) {
                // ...
              }
            }  
          }
        }
        new Thread(r).start();
      }
  2. Criar um cliente JAX-RS em um arquivo .java .
    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://localhost/RadioSvc/rest/songDataStream");
    try (SseEventSource source = SseEventSource.target(target).build()) {
      source.register(new Consumer<InboundSseEvent>(){
    
        @Override
        public void accept(InboundSseEvent event) {
          // called when we receive a new event
          Song song = event.readData(Song.class);
          System.out.println("Now playing " + song.title() + " by " + song.artist());
        }}, new Consumer<Throwable>(){
    
          @Override
          public void accept(Throwable t) {
            // called when something went wrong
            t.printStackTrace();
          }}, new Runnable() {
    
            @Override
            public void run() {
              // called when our connection is closed
              System.out.println("All done for now!");                            
            }});
    
      source.open();
      Thread.sleep(3600000);      // Consume song events for one hour
    
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  3. Opcional: Se não for possível converter os interceptores JSON de volta em objetos Java, inclua um MessageBodyReader e um provedor MessageBodyWriter .
  4. Crie uma página da web que chame seu método SSE. O arquivo HTML de exemplo a seguir cria uma página da web simples que exibe a musica que ele reproduz:
    <!DOCTYPE html>
    <html>
    <head>
      <title>SSE Radio - Now Playing</title>
    </head>
    <body>
      <h2>Now Playing:</h2>
      <div id="song">Song: </div>
      <div id="artist">Artist: </div>
      <script>
        var source = new EventSource('rest/songDataStream');
    
        source.onmessage = function(e) {
            var song = JSON.parse(e.data);
            document.getElementById("song").innerHTML = 'Song: ' + song.title;
            document.getElementById("artist").innerHTML = 'Artist: ' + song.artist;
          };
      </script>
    </body>
    </html>
  5. Empacote a página HTML com seu aplicativo da web.
  6. Navegue para o seu aplicativo da web. O aplicativo recebe eventos de música do servidor e atualiza automaticamente a página da web sem exigir que você atualize.
    Se múltiplos clientes chamarem o método de recurso songDataStream ou outro método, cada chamada de método criará um encadeamento separado que envia dados para esse usuário específico. A mensagem enviada cria um evento SSE de saída e a mensagem é enviada para todos os clientes.
  7. Para assegurar-se de que todos os clientes vejam os mesmos dados e enviem uma mensagem para todos os clientes ao mesmo tempo, use o método de transmissão. Ambos os exemplos anteriores do cliente JAX-RS e JavaScript trabalham com este exemplo de radiodifusão. Mude apenas a URL.
    1. Como um transmissor, envie mensagens para todos os clientes registrados.
      Neste exemplo, sempre que você chama o método de recurso playSong, todos os clientes inscritos recebem o evento com os dados da música selecionada.
    2. Como um cliente, registre-se para eventos e permaneça conectado.
      Nesse exemplo, múltiplos clientes podem se inscrever na estação de rádio chamando o método de recurso SSE listen.
        @Context
        private Sse sse;
    
        private static SseBroadcaster broadcaster;
    
        private synchronized static SseBroadcaster getBroadcaster(Sse sse) {
            if (broadcaster == null) {
                broadcaster = sse.newBroadcaster();
            }
            return broadcaster;
        }
    
        @GET
        @Path("listen")
        @Produces(MediaType.SERVER_SENT_EVENTS)
        public void listen(@Context SseEventSink sink, @Context Sse sse) {
            SseBroadcaster b = getBroadcaster(this.sse);
            b.register(sink);
        }
    
      @PUT
      @Path("playSong")
      public Response playSong(@PathParam("songId") String songId) {
        Song song = RadioService.getSong(songId);
        SseBroadcaster b = getBroadcaster(this.sse);
        OutboundSseEvent event = sse.newEventBuilder()
                                    .mediaType(MediaType.APPLICATION_JSON_TYPE)
                                    .data(Song.class, song)
                                    .build();
            b.broadcast(event);
      }

Resultados

O aplicativo da web recebe os eventos do servidor e atualiza automaticamente a página da web.