Backend Development 8 min read

Master Real-Time Push with Spring SseEmitter and Vue 3: A Step-by-Step Guide

This article introduces Spring's SseEmitter for server‑sent events, outlines its key features and use cases, and provides a complete end‑to‑end example—including Vue 3 front‑end setup, JavaScript client, and Spring Boot controller code—to enable real‑time message pushing between server and browser.

macrozheng
macrozheng
macrozheng
Master Real-Time Push with Spring SseEmitter and Vue 3: A Step-by-Step Guide

SseEmitter Overview

SseEmitter is a class in the Spring Framework that implements Server‑Sent Events (SSE), allowing the server to push data to the client over HTTP. Clients subscribe via an HTTP request, and the server continuously sends events through an SseEmitter instance.

Key Features

Unidirectional communication: only server‑to‑client.

Based on standard HTTP, no extra protocol needed.

Automatic reconnection by the browser if the connection drops.

Simple text‑based event format (data: … followed by two line breaks).

Typical Use Cases

Real‑time data streams such as stock price updates.

Instant notifications for e‑learning platforms, new courses, etc.

Chat applications for live message delivery.

Monitoring systems to push sensor data in IoT projects.

Basic Usage Steps

Create an SseEmitter instance in a controller and return it to the client.

Send events using the

send

method.

Handle connection closure and timeout with

onCompletion

and

onTimeout

.

Frontend Implementation (Vue 3)

Install Vue CLI and create a Vue 3 project:

<code>npm install -g @vue/cli
vue create my-vue3-app</code>

Start the development server:

<code>cd my-vue3-app
npm run serve</code>

Create

EventList.vue

to display incoming messages:

<code>&lt;template&gt;
  &lt;div&gt;
    &lt;h1&gt;Server-Sent Events&lt;/h1&gt;
    &lt;ul&gt;
      &lt;li v-for="message in messages" :key="message.id"&gt;{{ message.content }}&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { ref, onMounted, onUnmounted } from 'vue';
import { SseClient } from './SseClient';

const messages = ref([]);
const sseClient = new SseClient(event => {
  const data = JSON.parse(event.data);
  messages.value.push(data);
});

onMounted(() => sseClient.connect());
onUnmounted(() => sseClient.disconnect());
&lt;/script&gt;

&lt;style scoped&gt;
/* Add your styles here */
&lt;/style&gt;</code>

Implement

SseClient.js

to manage the EventSource:

<code>export class SseClient {
  constructor(onMessage) {
    this.onMessage = onMessage;
    this.eventSource = null;
  }
  connect() {
    this.eventSource = new EventSource('http://localhost:8089/events/54321');
    this.eventSource.onmessage = event => this.onMessage(event);
    this.eventSource.onerror = () => this.disconnect();
  }
  disconnect() {
    if (this.eventSource) {
      this.eventSource.close();
      this.eventSource = null;
    }
  }
}
</code>

Backend Implementation (Spring Boot)

Define a controller that stores SseEmitter instances and provides endpoints to stream, send messages, and close connections:

<code>@Controller
public class SseEmitterController {
    private static Map<String, SseEmitter> sseCache = new ConcurrentHashMap<>();

    @CrossOrigin(origins = "*")
    @GetMapping("/events/{userId}")
    public SseEmitter stream(@PathVariable String userId) throws IOException {
        sseCache.put(userId, new SseEmitter(10 * 60 * 1000L));
        SseEmitter emitter = sseCache.get(userId);
        Map<String, String> map = new HashMap<>();
        map.put("id", userId);
        map.put("content", "连接成功");
        emitter.send(map);
        return emitter;
    }

    @GetMapping("/sendMessage/{userId}")
    public String sendMessage(@PathVariable String userId,
                              @RequestParam(name = "message", required = false) String message) throws IOException {
        SseEmitter emitter = sseCache.get(userId);
        Map<String, String> map = new HashMap<>();
        map.put("id", userId);
        map.put("content", message);
        emitter.send(map);
        return "成功";
    }

    @GetMapping("/close/{userId}")
    public String close(@PathVariable String userId) throws IOException {
        SseEmitter emitter = sseCache.get(userId);
        emitter.complete();
        return "成功";
    }
}
</code>

After starting both front‑end and back‑end, the client connects, receives an initial success message, and can receive further messages sent via the

/sendMessage

endpoint.

These steps demonstrate a simple end‑to‑end solution for server‑initiated real‑time communication using Spring SseEmitter and Vue 3.

Backend DevelopmentSpring BootServer-Sent EventsReal-time PushVue 3SseEmitter
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.