brief introduction
Introduction to WebSocket
WebSocket protocol was born in 2008 and became an international standard in 2011. At present, mainstream browsers have good support.
WebSocket makes the data exchange between the client and the server easier, and allows the server to actively push data to the client. In the WebSocket API, the browser and server only need to complete a handshake, and they can directly create a persistent connection and conduct two-way data transmission.
WebSocket features
- Based on TCP protocol, the server-side implementation is relatively easy
- It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the HTTP protocol is used in the handshake stage. Therefore, it is not easy to shield the handshake and can pass through various HTTP proxy servers
- The data format is light, the performance overhead is small, and the communication is efficient
- You can send text or binary data
- There is no homology restriction, and the client can communicate with any server
- The protocol identifier is ws (wss if encrypted) and the server URL is the URL.
Integration instance
preparation in advance
1. Add dependency in pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency>
2. Configure the port for page access in the SpringBoot configuration file
server: port: 8888
3. Create WebSocket configuration file
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
Send yourself a message
1. Create index.html in the templates directory
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My WebSocket</title> </head> <body> Message content:<input id="text" type="text" /> <button onclick="send()">send out</button> <button onclick="closeWebSocket()">Close connection</button> <div id="message"></div> <script type="text/javascript"> var websocket=null; if("WebSocket" in window){ websocket=new WebSocket("ws://localhost:8888/websocket/one"); }else { alert('I won't support it WebSocket'); } websocket.onerror=function () { setMessageInnerHTML('websocket Connection error!'); }; websocket.onopen=function (event) { setMessageInnerHTML('websocket Connection established successfully!'); }; websocket.onmessage=function (event) { var message=event.data; setMessageInnerHTML(message); }; websocket.onclose=function () { setMessageInnerHTML('websocket Connection closed!'); }; websocket.onbeforeunload=function () { websocket.close(); }; function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML+=innerHTML+'<br/>'; } function closeWebSocket() { websocket.close(); } function send(){ var message=document.getElementById('text').value; websocket.send(message); } </script> </body> </html>
2. Create a server. The @ ServerEndpoint annotation is the key to the interaction between the server and the client. Its value (/ websocket/one) should correspond to the request path in the index page
@Slf4j @ServerEndpoint(value = "/websocket/one") @Component public class OneWebSocket { //Current number of online connections private static AtomicInteger onlineCount=new AtomicInteger(0); @OnOpen public void onOpen(Session session){ onlineCount.incrementAndGet(); //Number of lines + 1 log.info("Add connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); } @OnClose public void onClose(Session session){ onlineCount.decrementAndGet(); //Online number - 1 log.info("Close connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); } @OnMessage public void onMessage(String message,Session session){ log.info("Server receives client[{}]Message:{}",session.getId(),message); sendMessage("Hello, "+message,session); } @OnError public void onError(Session session,Throwable error){ log.error("Send error!"); error.printStackTrace(); } private void sendMessage(String message,Session toSession){ try { log.info("Server to client[{}]send message{}",toSession.getId(),message); toSession.getBasicRemote().sendText(message); } catch (IOException e) { log.error("The server failed to send a message to the client:{}",e); } } }
3. Visit the index page. When entering the page, the connection between the server and the client will be established. After entering the content to be sent in the text box, click send to see the following effect
Mass messaging
1. Modify the connection address of index.html
websocket=new WebSocket("ws://localhost:8888/websocket/oneToMany");
2. Create server
@Slf4j @ServerEndpoint(value = "/websocket/oneToMany") @Component public class OneToManyWebSocket { //Current number of online connections private static AtomicInteger onlineCount=new AtomicInteger(0); //Currently online clients private static Map<String, Session> clients=new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session){ onlineCount.incrementAndGet(); //Number of lines + 1 clients.put(session.getId(),session); log.info("Add connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); } @OnClose public void onClose(Session session){ onlineCount.decrementAndGet(); //Online number - 1 clients.remove(session.getId()); log.info("Close connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); } @OnMessage public void onMessage(String message,Session session){ log.info("Server receives client[{}]Message:{}",session.getId(),message); sendMessage("Hello, "+message,session); } @OnError public void onError(Session session,Throwable error){ log.error("Send error!"); error.printStackTrace(); } private void sendMessage(String message,Session fromSession){ for (Map.Entry<String,Session> sessionEntry:clients.entrySet()){ Session toSession=sessionEntry.getValue(); if (!fromSession.getId().equals(toSession.getId())){ log.info("Server to client[{}]send message{}",toSession.getId(),message); toSession.getAsyncRemote().sendText(message); } } } }
3. Open multiple pages in the browser and select a page to send a message
One to one chat room
1. Modify the code of index.html page
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My WebSocket</title> </head> <body> <div> ID:<span id="id"></span> </div> Message content:<input id="text" type="text" /> target ID: <input id="toId" type="text" /> <button onclick="send()">send out</button> <button onclick="closeWebSocket()">Close connection</button> <div id="message"></div> <script type="text/javascript"> var websocket=null; if("WebSocket" in window){ websocket=new WebSocket("ws://localhost:8888/websocket/oneToOne"); }else { alert('I won't support it WebSocket'); } websocket.onerror=function () { setMessageInnerHTML('websocket Connection error!'); }; websocket.onopen=function (event) { setMessageInnerHTML('websocket Connection established successfully!'); }; websocket.onmessage=function (event) { var message=event.data; if (message.length>11 && message.substring(0,12)=="send userId:"){ document.getElementById('id').innerText=message.substring(12,message.length); }else{ setMessageInnerHTML(message); } }; websocket.onclose=function () { setMessageInnerHTML('websocket Connection closed!'); }; websocket.onbeforeunload=function () { websocket.close(); }; function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML+=innerHTML+'<br/>'; } function closeWebSocket() { websocket.close(); } function send(){ var id=document.getElementById('toId').value; var message=document.getElementById('text').value; var sendMsg="{\"userId\":"+id+",\"message\":\""+message+"\"}"; websocket.send(sendMsg); } </script> </body> </html>
2. Create server and MyMessage classes
@Slf4j @ServerEndpoint(value = "/websocket/oneToOne") @Component public class OneToOneWebSocket { //Current number of online connections private static AtomicInteger onlineCount=new AtomicInteger(0); //Currently online clients private static Map<String, Session> clients=new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session){ onlineCount.incrementAndGet(); //Number of lines + 1 clients.put(session.getId(),session); log.info("Add connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); sendMessage("send userId:"+session.getId(),session); } @OnClose public void onClose(Session session){ onlineCount.decrementAndGet(); //Online number - 1 clients.remove(session.getId()); log.info("Close connection:{},Number of people currently online:{}",session.getId(),onlineCount.get()); } @OnMessage public void onMessage(String message,Session session){ log.info("Server receives client[{}]Message:{}",session.getId(),message); try{ MyMessage myMessage= JSON.parseObject(message, MyMessage.class); if (myMessage!=null){ Session toSession=clients.get(myMessage.getUserId()); if (toSession!=null){ sendMessage(session.getId()+": "+myMessage.getMessage(),toSession); } sendMessage(session.getId()+": "+myMessage.getMessage(),session); } }catch (Exception e){ log.error("Parsing failed:{}",e); } } @OnError public void onError(Session session,Throwable error){ log.error("Send error!"); error.printStackTrace(); } private void sendMessage(String message,Session toSession){ try { log.info("Server to client[{}]send message{}",toSession.getId(),message); toSession.getBasicRemote().sendText(message); } catch (Exception e) { log.error("The server failed to send a message to the client:{}",e); } } }
@Data @NoArgsConstructor public class MyMessage { private String userId; private String message; }
3. Open two pages in the browser