In a project development, the Netty network application framework and MQTT were used to send and receive message data, which requires the background to actively push the obtained messages to the front end. Therefore, MQTT was used, which is hereby recorded.
1, What is websocket?
WebSocket protocol is a new network protocol based on TCP. It realizes the full duplex communication between the client and the server. Everyone who has studied computer network knows that since it is full duplex, it shows that the server can actively send information to the client.
This coincides with our push technology or the function of multiplayer online chat.
Why not use HTTP protocol?
This is because HTTP is simplex communication. Communication can only be initiated by the client. The client requests it and the server handles it, which is too troublesome. So websocket came into being.
Let's start the integration directly with Springboot. The following cases have been tested successfully on my own computer. You can modify them according to your own functions.
My project structure is as follows:
2, Use steps
1. Add dependency
Maven dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
2. Enable Springboot support for WebSocket
Enabling WebSocket support is also very simple. A few words of code are done:
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/14:35 * @ Description: Enable WebSocket support */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
This is recommended for the latest Spring Boot tutorial: https://github.com/javastacks/spring-boot-best-practice
3. Core configuration: WebSocketServer
Because WebSocket is similar to the form of client and server (using ws protocol), the WebSocket server here is actually equivalent to a Controller of ws protocol
- @ServerEndpoint annotation is a class level annotation. Its main function is to define the current class as a websocket server. The value of the annotation will be used to listen for the access URL address of the terminal connected by the user. The client can connect to the websocket server through this URL
- Create a new ConcurrentHashMap webSocketMap, which is used to receive the WebSocket of the current userId to facilitate the push message of userId between transfers.
The following is the specific business code:
package cc.mrbird.febs.external.webScoket; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.time.LocalDateTime; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; /** * Created with IntelliJ IDEA. * @ Auther: Ma Chaowei * @ Date: 2020/06/16/14:35 * @ Description: * @ ServerEndpoint Annotation is a class level annotation. Its main function is to define the current class as a websocket server, * The value of the annotation will be used to monitor the access URL address of the terminal connected by the user. The client can connect to the WebSocket server through this URL */ @Component @Slf4j @Service @ServerEndpoint("/api/websocket/{sid}") public class WebSocketServer { //Static variable, used to record the current number of online connections. It should be designed to be thread safe. private static int onlineCount = 0; //The thread safe Set of concurrent package is used to store the MyWebSocket object corresponding to each client. private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //The connection session with a client needs to send data to the client through it private Session session; //Receive sid private String sid = ""; /** * Method successfully called after connection establishment */ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { this.session = session; webSocketSet.add(this); //Add to set this.sid = sid; addOnlineCount(); //Online number plus 1 try { sendMessage("conn_success"); log.info("A new window starts listening:" + sid + ",The number of people currently online is:" + getOnlineCount()); } catch (IOException e) { log.error("websocket IO Exception"); } } /** * Method called by connection closure */ @OnClose public void onClose() { webSocketSet.remove(this); //Delete from set subOnlineCount(); //Online number minus 1 //When disconnected, update the motherboard occupancy to release log.info("Released sid For:"+sid); //Here is the business to be handled when you release log.info("One connection is closed! The number of people currently online is" + getOnlineCount()); } /** * Method of calling after receiving client message * @ Param message Messages sent by clients */ @OnMessage public void onMessage(String message, Session session) { log.info("Received from window" + sid + "Information:" + message); //Mass messaging for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * @ Param session * @ Param error */ @OnError public void onError(Session session, Throwable error) { log.error("An error occurred"); error.printStackTrace(); } /** * Realize server active push */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * Mass customization message */ public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException { log.info("Push message to window" + sid + ",Push content:" + message); for (WebSocketServer item : webSocketSet) { try { //Here, you can set to push only to this sid. If it is null, all will be pushed if (sid == null) { // item.sendMessage(message); } else if (item.sid.equals(sid)) { item.sendMessage(message); } } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() { return webSocketSet; } }
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; /** * Created with IntelliJ IDEA. * * @ Auther: Ma Chaowei * @ Date: 2020/06/16/14:38 * @ Description: */ @Controller("web_Scoket_system") @RequestMapping("/api/socket") public class SystemController { //Page request @GetMapping("/index/{userId}") public ModelAndView socket(@PathVariable String userId) { ModelAndView mav = new ModelAndView("/socket1"); mav.addObject("userId", userId); return mav; } //Push data interface @ResponseBody @RequestMapping("/socket/push/{cid}") public Map 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; } }
5. Test page index html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Java back-end WebSocket of Tomcat realization</title> <script type="text/javascript" src="js/jquery.min.js"></script> </head> <body> <div id="main" style="width: 1200px;height:800px;"></div> Welcome<br/><input id="text" type="text" /> <button onclick="send()">send message</button> <hr/> <button onclick="closeWebSocket()">close WebSocket connect</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; //Judge whether the current browser supports WebSocket if('WebSocket' in window) { //Change to your address websocket = new WebSocket("ws://192.168.100.196:8082/api/websocket/100"); } else { alert('Current browser Not support websocket') } //Callback method with connection error websocket.onerror = function() { setMessageInnerHTML("WebSocket Connection error"); }; //Callback method for successful connection establishment websocket.onopen = function() { setMessageInnerHTML("WebSocket Connection successful"); } var U01data, Uidata, Usdata //Callback method for receiving message websocket.onmessage = function(event) { console.log(event); setMessageInnerHTML(event); setechart() } //Callback method for connection closure websocket.onclose = function() { setMessageInnerHTML("WebSocket Connection closed"); } //Listen for window closing events. When the window is closed, take the initiative to close the websocket connection to prevent closing the window before the connection is disconnected, and the server side will throw exceptions. window.onbeforeunload = function() { closeWebSocket(); } //Display messages on Web pages function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //Close WebSocket connection function closeWebSocket() { websocket.close(); } //send message function send() { var message = document.getElementById('text').value; websocket.send('{"msg":"' + message + '"}'); setMessageInnerHTML(message + " "); } </script> </html>
6. Result display
backstage:
If there is a connection request
Foreground display:
summary
In this case, I encountered a problem, that is, when WebSocket starts up, it takes precedence over the spring container, which leads to calling Service in WebSocketServer and reporting null pointer exceptions.
Therefore, you need to statically initialize the required service s in WebSocketServer:
As shown in the figure:
The following configuration is also required:
Original link: https://blog.csdn.net/MacWx/article/details/111319558
Copyright notice: This is Mr. Dashu, the blogger of CSDN The original article follows CC 4.0 BY-SA copyright agreement. Please attach the source link of the original text and this statement for reprint.
Recent hot article recommendations:
1.600 + Java interview questions and answers (2021 latest edition)
2.Finally got the IntelliJ IDEA activation code through the open source project. It's really fragrant!
3.Ali Mock tools are officially open source and kill all Mock tools on the market!
4.Spring Cloud 2020.0.0 is officially released, a new and subversive version!
5.Java development manual (Songshan version) is the latest release. Download it quickly!
Feel good, don't forget to like + forward!