springboot使用websocket(Springboot uses websocket)

WebSocket概念

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

和http协议不同的就是一种长连接,http是无状态的连接,当请求回复后就会断开连接,是阻塞式连接,当服务端一直在处理时,客户端是接受

不到回复的,就会一直等待,发生阻塞,直到有回复。服务端不能主动联系客户端,只能客户端发起。

而WebSocket协议则是一种持久化通信协议,在第一次发起http请求后,请求头携带有关的WebSocket参数,服务器进行协议升级,HTTP->Websocket

建立持久连接,服务端会一直知道连接信息,直到客户端关闭请求。不用再多次发送http请求并且解析。

应用场景:如需要不断获取最新消息或数据,要求实时性的应用,此时就可以使用websocket来建立链接,解决数据传输。

使用

//springboot内置tomcat//添加依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>2.5.6</version>
        </dependency>

注入ServerEndpointExporte

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

 websocket的具体实现类

package com.bocom.fmp.common.websocket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
 
@ServerEndpoint(value = "/client/{userId}")
@Component
public class WarningPushSocket {
	
    private static Logger logger = LogManager.getLogger(WarningPushSocket.class.getName());
	
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
	  
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WarningPushSocket> wsClientMap = new CopyOnWriteArraySet<>();  
  
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    
    /**
     * 连接建立成功调用的方法
     * @param session 当前会话session
     */
    @OnOpen
    public void onOpen (@PathParam("userId")String userId,Session session){
        this.session = session;
        wsClientMap.add(this);
        addOnlineCount();
        logger.info(session.getId()+"有新链接加入,当前链接数为:" + wsClientMap.size());
    }
  
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose (){
    	wsClientMap.remove(this);  
        subOnlineCount();  
        logger.info("有一链接关闭,当前链接数为:" + wsClientMap.size());
    }
  
    /**
     * 收到客户端消息
     * @param message 客户端发送过来的消息
     * @param session 当前会话session
     * @throws IOException
     */
    @OnMessage
    public void onMessage (String message, Session session) throws IOException {
        logger.info("来终端的警情消息:" + message);
        sendMsgToAll(message); 
    }
    
    /**
     * 发生错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
    	logger.info("wsClientMap发生错误!");
        error.printStackTrace();
    }
    
    /**
     * 给所有客户端群发消息
     * @param message 消息内容
     * @throws IOException
     */
    public void sendMsgToAll(String message) throws IOException {
    	for ( WarningPushSocket item : wsClientMap ){  
            item.session.getBasicRemote().sendText(message);
    	}
    	logger.info("成功群送一条消息:" + wsClientMap.size());
    }
  
    public void sendMessage (String message) throws IOException {
        this.session.getBasicRemote().sendText(message);  
        logger.info("成功发送一条消息:" + message);
    }
  
    public static synchronized  int getOnlineCount (){
        return WarningPushSocket.onlineCount;  
    }
  
    public static synchronized void addOnlineCount (){
    	WarningPushSocket.onlineCount++;  
    }
  
    public static synchronized void subOnlineCount (){
    	WarningPushSocket.onlineCount--;  
    }
}

html

<!DOCTYPE HTML>
<html>
<head>
    <title>My WebSocket</title>
</head>
 
 
<body>
Welcome<br/>
<input id="text" type="text" /><button οnclick="send()">Send</button>    <button οnclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
 
 
<script type="text/javascript">
    var websocket = null;
 
 
    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
        websocket = new WebSocket("ws://localhost:9090/client");
    }
    else{
        alert('Not support websocket')
    }
 
 
    //连接发生错误的回调方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };
 
 
    //连接成功建立的回调方法
    websocket.onopen = function(event){
        setMessageInnerHTML("open");
    }
 
 
    //接收到消息的回调方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }
 
 
    //连接关闭的回调方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }
 
 
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.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>
</html>

搜索

复制

————————

WebSocket概念

< strong > websocket protocol < / strong > is a new network protocol based on < strong > TCP < / strong >. It realizes full duplex communication between the browser and the server – allowing the server to actively send information to the client.

Websocket communication protocol was determined as standard RFC 6455 by IETF in 2011 and supplemented by rfc7936.

Different from HTTP protocol, HTTP is a long connection. HTTP is a stateless connection. When the request is replied, it will be disconnected. It is a blocking connection. When the server has been processing, the client accepts it

If there is no reply, it will wait and block until there is a reply. The server cannot actively contact the client, but can only be initiated by the client.

The websocket protocol is a < strong > persistent < / strong > communication protocol. After the first HTTP request is initiated, the request header carries the relevant websocket parameters, and the server upgrades the protocol, HTTP – & gt; Websocket

When a persistent connection is established, the server will always know the connection information until the client closes the request. You don’t have to send HTTP requests and parse them many times.

< strong > application scenario < / strong >: if you need to continuously obtain the latest news or data and require real-time applications, you can use websocket to establish links and solve data transmission.

use

//springboot内置tomcat//添加依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>2.5.6</version>
        </dependency>

注入ServerEndpointExporte

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

Specific implementation class of websocket

package com.bocom.fmp.common.websocket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
 
@ServerEndpoint(value = "/client/{userId}")
@Component
public class WarningPushSocket {
	
    private static Logger logger = LogManager.getLogger(WarningPushSocket.class.getName());
	
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
	  
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WarningPushSocket> wsClientMap = new CopyOnWriteArraySet<>();  
  
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    
    /**
     * 连接建立成功调用的方法
     * @param session 当前会话session
     */
    @OnOpen
    public void onOpen (@PathParam("userId")String userId,Session session){
        this.session = session;
        wsClientMap.add(this);
        addOnlineCount();
        logger.info(session.getId()+"有新链接加入,当前链接数为:" + wsClientMap.size());
    }
  
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose (){
    	wsClientMap.remove(this);  
        subOnlineCount();  
        logger.info("有一链接关闭,当前链接数为:" + wsClientMap.size());
    }
  
    /**
     * 收到客户端消息
     * @param message 客户端发送过来的消息
     * @param session 当前会话session
     * @throws IOException
     */
    @OnMessage
    public void onMessage (String message, Session session) throws IOException {
        logger.info("来终端的警情消息:" + message);
        sendMsgToAll(message); 
    }
    
    /**
     * 发生错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
    	logger.info("wsClientMap发生错误!");
        error.printStackTrace();
    }
    
    /**
     * 给所有客户端群发消息
     * @param message 消息内容
     * @throws IOException
     */
    public void sendMsgToAll(String message) throws IOException {
    	for ( WarningPushSocket item : wsClientMap ){  
            item.session.getBasicRemote().sendText(message);
    	}
    	logger.info("成功群送一条消息:" + wsClientMap.size());
    }
  
    public void sendMessage (String message) throws IOException {
        this.session.getBasicRemote().sendText(message);  
        logger.info("成功发送一条消息:" + message);
    }
  
    public static synchronized  int getOnlineCount (){
        return WarningPushSocket.onlineCount;  
    }
  
    public static synchronized void addOnlineCount (){
    	WarningPushSocket.onlineCount++;  
    }
  
    public static synchronized void subOnlineCount (){
    	WarningPushSocket.onlineCount--;  
    }
}

html

<!DOCTYPE HTML>
<html>
<head>
    <title>My WebSocket</title>
</head>
 
 
<body>
Welcome<br/>
<input id="text" type="text" /><button οnclick="send()">Send</button>    <button οnclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
 
 
<script type="text/javascript">
    var websocket = null;
 
 
    //判断当前浏览器是否支持WebSocket
    if('WebSocket' in window){
        websocket = new WebSocket("ws://localhost:9090/client");
    }
    else{
        alert('Not support websocket')
    }
 
 
    //连接发生错误的回调方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };
 
 
    //连接成功建立的回调方法
    websocket.onopen = function(event){
        setMessageInnerHTML("open");
    }
 
 
    //接收到消息的回调方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }
 
 
    //连接关闭的回调方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }
 
 
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.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>
</html>

search

copy