Integrating WebSocket in Spring Boot: A Complete Step‑by‑Step Guide with Code Samples
This article explains how to use Spring Boot to add WebSocket support, covering the protocol basics, Maven dependencies, configuration classes, a test controller, a simple HTML client page, and troubleshooting tips, all illustrated with complete Java and JavaScript code examples.
Introduction
During a recent project we needed to push messages from a Netty‑based backend to the frontend, so we chose WebSocket for its full‑duplex capabilities. This guide records the entire integration process using Spring Boot.
What is WebSocket?
WebSocket is a TCP‑based protocol that enables bidirectional communication between client and server, allowing the server to actively push data to the client—ideal for real‑time notifications and chat applications.
Step 1: Add Maven Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>Step 2: Enable WebSocket Support in Spring Boot
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @Auther: Ma Chaowei
* @Date: 2020/06/16
* @Description: Enable WebSocket support
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}Step 3: Core WebSocket Server Configuration
The WebSocketServer class is annotated with @ServerEndpoint to turn it into a WebSocket endpoint. It maintains a thread‑safe CopyOnWriteArraySet of active sessions, tracks online count, and provides methods for connection lifecycle events, message handling, and server‑initiated pushes.
package cc.mrbird.febs.external.webScoket;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/api/websocket/{sid}")
public class WebSocketServer {
private static int onlineCount = 0;
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
private Session session;
private String sid = "";
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
webSocketSet.add(this);
this.sid = sid;
addOnlineCount();
try { sendMessage("conn_success"); } catch (IOException e) { e.printStackTrace(); }
}
@OnClose
public void onClose() {
webSocketSet.remove(this);
subOnlineCount();
}
@OnMessage
public void onMessage(String message, Session session) {
for (WebSocketServer item : webSocketSet) {
try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); }
}
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
for (WebSocketServer item : webSocketSet) {
if (sid == null || item.sid.equals(sid)) {
item.sendMessage(message);
}
}
}
// synchronized counters omitted for brevity
}Step 4: Test Controller
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Controller("web_Scoket_system")
@RequestMapping("/api/socket")
public class SystemController {
@GetMapping("/index/{userId}")
public ModelAndView socket(@PathVariable String userId) {
ModelAndView mav = new ModelAndView("/socket1");
mav.addObject("userId", userId);
return mav;
}
@ResponseBody
@RequestMapping("/socket/push/{cid}")
public Map<String, Object> pushToWeb(@PathVariable String cid, String message) {
Map<String, Object> result = new HashMap<>();
try {
WebSocketServer.sendInfo(message, cid);
result.put("code", cid);
result.put("msg", message);
} catch (IOException e) { e.printStackTrace(); }
return result;
}
}Step 5: Simple HTML Client (index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Java Backend WebSocket Demo</title>
<script src="js/jquery.min.js"></script>
</head>
<body>
<div id="main" style="width:1200px;height:800px;"></div>
<input id="text" type="text"/>
<button onclick="send()">Send Message</button>
<hr/>
<button onclick="closeWebSocket()">Close WebSocket</button>
<hr/>
<div id="message"></div>
<script type="text/javascript">
var websocket = null;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://192.168.100.196:8082/api/websocket/100");
} else {
alert('Browser does not support WebSocket');
}
websocket.onerror = function() { setMessageInnerHTML('WebSocket error'); };
websocket.onopen = function() { setMessageInnerHTML('WebSocket opened'); };
websocket.onmessage = function(event) { console.log(event); setMessageInnerHTML(event.data); };
websocket.onclose = function() { setMessageInnerHTML('WebSocket closed'); };
window.onbeforeunload = function() { closeWebSocket(); };
function setMessageInnerHTML(msg) { document.getElementById('message').innerHTML += msg + '<br/>'; }
function closeWebSocket() { websocket.close(); }
function send() {
var message = document.getElementById('text').value;
websocket.send('{"msg":"' + message + '"}');
setMessageInnerHTML(message + ' ');
}
</script>
</body>
</html>Result Display
The backend console shows connection logs when a client connects, and the frontend page displays received messages in real time.
Conclusion
When the WebSocket server starts before the Spring container, injecting Spring services directly can cause NullPointerException. The fix is to obtain required beans statically or configure the server to start after the Spring context.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
