WebSocket Integration in Spring Boot: Javax, WebMVC, WebFlux, Java-WebSocket, SocketIO, and Netty
This article provides a comprehensive guide to integrating WebSocket in Spring Boot, covering Javax, WebMVC, WebFlux implementations with detailed server and client configurations, as well as brief introductions to Java‑WebSocket, SocketIO, and Netty libraries, including full code examples.
The author, a senior architect, explores various ways to integrate WebSocket in Java, focusing on the three mainstream Spring Boot approaches (Javax, WebMVC, WebFlux) and briefly introduces three additional libraries (Java‑WebSocket, SocketIO, Netty).
Javax
In the javax.websocket package the server endpoint is defined with @ServerEndpoint and lifecycle callbacks such as @OnOpen , @OnClose , @OnMessage , and @OnError .
@Component
@ServerEndpoint("/websocket/{type}")
public class JavaxWebSocketServerEndpoint {
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam(value = "type") String type) {
// connection opened
}
@OnClose
public void onClose(Session session, CloseReason reason) {
// connection closed
}
@OnMessage
public void onMessage(Session session, String message) {
// receive text message
}
@OnMessage
public void onMessage(Session session, PongMessage message) {
// receive pong message
}
@OnMessage
public void onMessage(Session session, ByteBuffer message) {
// receive binary message
}
@OnError
public void onError(Session session, Throwable e) {
// error handling
}
}Configuration requires adding the spring-boot-starter-websocket dependency and exposing a ServerEndpointExporter bean.
implementation 'org.springframework.boot:spring-boot-starter-websocket'
@Configuration(proxyBeanMethods = false)
public class JavaxWebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}Notes: javax.websocket defines PongMessage but not PingMessage ; ping/pong can be sent via session.getAsyncRemote().sendPing(ByteBuffer) and sendPong(ByteBuffer) .
// send ping
session.getAsyncRemote().sendPing(ByteBuffer buffer);
// send pong
session.getAsyncRemote().sendPong(ByteBuffer buffer);WebMVC
WebSocket support is enabled with spring-boot-starter-websocket and a WebSocketHandler implementation.
public class ServletWebSocketServerHandler implements WebSocketHandler {
@Override
public void afterConnectionEstablished(@NonNull WebSocketSession session) throws Exception {
// connection established
}
@Override
public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage
message) throws Exception {
// handle message
}
@Override
public void handleTransportError(@NonNull WebSocketSession session, @NonNull Throwable exception) throws Exception {
// error handling
}
@Override
public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus closeStatus) throws Exception {
// connection closed
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}The handler is registered via a WebSocketConfigurer , and a HandshakeInterceptor can be added for custom handshake logic.
@Configuration
@EnableWebSocket
public class ServletWebSocketServerConfigurer implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(@NonNull WebSocketHandlerRegistry registry) {
registry.addHandler(new ServletWebSocketServerHandler(), "/websocket")
.addInterceptors(new ServletWebSocketHandshakeInterceptor())
.setAllowedOrigins("*");
}
public static class ServletWebSocketHandshakeInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map
attributes) throws Exception {
// before handshake
return false; // or true to continue
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
// after handshake
}
}
}Limitation: the default path mapping does not support Ant‑style wildcards; a custom UrlPathHelper can be used to achieve pattern matching.
if (registry instanceof ServletWebSocketHandlerRegistry) {
((ServletWebSocketHandlerRegistry) registry).setUrlPathHelper(new PrefixUrlPathHelper("/websocket"));
}
registry.addHandler(new ServletWebSocketServerHandler(), "/websocket/**").setAllowedOrigins("*");
public class PrefixUrlPathHelper extends UrlPathHelper {
private String prefix;
@Override
public String resolveAndCacheLookupPath(HttpServletRequest request) {
String path = super.resolveAndCacheLookupPath(request);
if (path.startsWith(prefix)) {
return prefix + "/**";
}
return path;
}
}WebFlux
WebFlux provides a reactive WebSocket API that does not require additional dependencies.
public class ReactiveWebSocketServerHandler implements WebSocketHandler {
@NonNull
@Override
public Mono
handle(WebSocketSession session) {
Mono
send = session.send(Flux.create(sink -> {
// send messages via sink
})).doOnError(it -> {
// error handling
});
Mono
receive = session.receive()
.doOnNext(it -> {
// receive message
})
.doOnError(it -> {
// error handling
})
.then();
Disposable disposable = session.closeStatus()
.doOnError(it -> {
// error handling
})
.subscribe(it -> {
// connection closed
});
return Mono.zip(send, receive).then();
}
}The client uses a WebSocketClient such as ReactorNettyWebSocketClient and executes the handler.
WebSocketClient client = new ReactorNettyWebSocketClient();
WebSocketHandler handler = new ReactiveWebSocketClientHandler();
client.execute(uri, handler).subscribe();Other libraries
Java‑WebSocket is a pure‑Java third‑party library for WebSocket with extensive documentation on GitHub.
SocketIO implements a custom protocol that supports multiple languages; it is suited for real‑time chat scenarios and requires its own server and client classes.
Netty is a widely used asynchronous network framework that also provides robust WebSocket support.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.