Master Real-Time Updates with Spring Boot 3: SSE + fetch-event-source Tutorial
This article introduces a continuously updated Spring Boot 3 case collection and provides a step‑by‑step tutorial on implementing Server‑Sent Events using both the native EventSource API and the fetch‑event‑source library, covering backend controller code, frontend Vue integration, and practical code examples.
Spring Boot 3实战案例合集 now includes over 100 practical articles and a PDF e‑book that will be continuously updated for subscribers.
1. Introduction
SSE (Server‑Sent Events) is a lightweight HTTP‑based protocol for one‑way real‑time data push from server to browser. It works with the native EventSource API and offers simple handshake, automatic reconnection, and broad browser support, making it suitable for notifications, stock quotes, etc.
Simple protocol, no WebSocket handshake.
Built‑in reconnection.
Browser compatibility.
Ideal for one‑way push scenarios.
Limitations of the native EventSource API:
Only URL and withCredentials can be passed; no request body.
No custom request headers.
GET only.
Browser‑controlled retry strategy.
We introduce the open‑source fetch-event-source library, which adds full Fetch API capabilities to SSE requests.
2. Practical Example
2.1 Environment
Backend (Spring Boot 3.4.0) controller:
<code>@RestController
@RequestMapping("/api")
public class SseController {
private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();
@GetMapping(path = "/sse/{username}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handler(@PathVariable String username) throws Exception {
SseEmitter sse = new SseEmitter();
emitters.put(username, sse);
sse.send(new R(0, "Welcome," + username), MediaType.APPLICATION_JSON);
return sse;
}
@PostMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter handler(@RequestBody Map<String, Object> data) throws Exception {
System.err.printf("Received request data: %s%n", data);
SseEmitter sse = new SseEmitter();
String username = data.get("username").toString();
emitters.put(username, sse);
sse.send(new R(0, "Welcome," + username), MediaType.APPLICATION_JSON);
return sse;
}
@GetMapping("/send/{username}")
public void send(@PathVariable String username, String content) throws Exception {
SseEmitter sse = emitters.get(username);
if (sse != null) {
sse.send(new R(0, content), MediaType.APPLICATION_JSON);
}
}
public static record R(Integer code, Object data) {}
}
</code>Endpoints:
/sse/{username} – used by native EventSource.
/sse – used by fetch-event-source (POST with body).
/send/{username} – send a message to a specific user.
Frontend setup (Vue 3 + Element UI)
<code><el-row style="margin-bottom: 5px;" :gutter="5">
<el-col :span="4">
<el-input v-model="username" placeholder="用户名"/>
</el-col>
<el-col :span="8">
<el-button type="primary" @click="connectServer">连接服务器</el-button>
</el-col>
</el-row>
...
</code>Native EventSource usage:
<code>const sse = new EventSource(url);
sse.onmessage = ev => {
const ret = JSON.parse(ev.data);
content.value += ret.data + '\n';
};
</code>fetch-event-source usage:
<code>import { fetchEventSource } from '@microsoft/fetch-event-source';
fetchEventSource('/api/sse', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username.value }),
onmessage(ev) {
const ret = JSON.parse(ev.data);
content.value += ret.data + '\n';
}
});
</code>Both approaches deliver the same real‑time effect, but fetch-event-source allows custom headers, request bodies, and other Fetch API features.
Subscribe to the collection to receive the PDF e‑book and continuously updated source code.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.