Mastering WebSocket with Spring Boot 3: From Handshake to Real‑Time Messaging
An in‑depth Spring Boot 3 tutorial explains WebSocket fundamentals, the HTTP upgrade handshake, core Spring APIs, configuration options, origin handling, and testing steps, enabling developers to build real‑time, bidirectional communication services for web applications.
WebSocket Introduction
WebSocket protocol RFC 6455 provides a standardized way to establish a full-duplex, bidirectional communication channel over a single TCP connection between client and server. It works over HTTP ports 80/443 and can reuse existing firewall rules.
The interaction starts with an HTTP request that includes an Upgrade header to switch to the WebSocket protocol. Example request:
<code>GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket // ①
Connection: Upgrade // ②
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080</code>① Upgrade header information ② Use Upgrade connection
A WebSocket‑supporting server responds with a 101 Switching Protocols status instead of the usual 200:
<code>HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp</code>After a successful handshake, the TCP socket remains open and both client and server can continue to send and receive messages.
If the WebSocket server sits behind a web server such as Nginx, additional configuration may be required to forward the Upgrade request.
HTTP vs. WebSocket
Although WebSocket starts with an HTTP request, its architecture and programming model differ greatly from traditional HTTP/REST. HTTP models multiple URLs with request‑response semantics, while WebSocket typically uses a single URL and a persistent, event‑driven, asynchronous message flow.
WebSocket is a transport protocol without built‑in message semantics; applications must agree on a higher‑level protocol (e.g., STOMP) via the Sec-WebSocket-Protocol header.
When to Use WebSocket
WebSocket adds dynamic, interactive capabilities to web pages, but for many scenarios Ajax, HTTP streaming, or long polling are sufficient. Real‑time collaboration, gaming, and financial applications benefit most from low latency, high‑frequency, high‑throughput communication.
Network proxies and firewalls may block Upgrade headers, making WebSocket more suitable for internal services than public‑facing ones.
Core WebSocket API in Spring
Spring provides a WebSocket API for building client and server applications.
WebSocketHandler
Implement WebSocketHandler or extend TextWebSocketHandler / BinaryWebSocketHandler . Example using TextWebSocketHandler :
<code>public class MessageHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
System.out.printf("SessionId: %s, Received: %s%n", session.getId(), message.getPayload());
try {
session.sendMessage(new TextMessage("Server received - " + message.getPayload()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.printf("Connection established, SessionId: %s, Attributes: %s%n", session.getId(), session.getAttributes());
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.printf("Connection closed, SessionId: %s, Status: %s%n", session.getId(),
status.getCode() + " - " + status.getReason());
}
}
</code>WebSocket configuration:
<code>@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(messageHandler(), "/message");
}
@Bean
public WebSocketHandler messageHandler() {
return new MessageHandler();
}
}
</code>To customize the handshake, implement a HandshakeInterceptor . Example:
<code>@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(messageHandler(), "/message")
.setHandshakeHandler(handshakeHandler())
.addInterceptors(new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
attributes.put("uid", uid);
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Exception exception) {
// post‑handshake logic
}
});
}
}
</code>Spring WebSocket integrates easily with Spring MVC; the DispatcherServlet can handle both HTTP requests and WebSocket handshakes. For JSR‑356 runtimes, specific RequestUpgradeStrategy implementations are required for servers such as Tomcat, Jetty, GlassFish, WebLogic, WebSphere, Undertow, and WildFly.
Each underlying WebSocket engine exposes configuration properties (e.g., message buffer size, idle timeout). Example for Tomcat/GlassFish:
<code>@Bean
public ServletServerContainerFactoryBean servletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
</code>Since Spring Framework 4.1.5, WebSocket and SockJS default to same‑origin requests. You can allow all origins with:
<code>@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(messageHandler(), "/message")
.setAllowedOriginPatterns("*");
}
}
</code>Testing
After configuring the environment, you can test the WebSocket endpoint with Postman. Successful connection, message sending, and server receipt are shown in the screenshots below.
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.