springboot入门系列(十一)websocket实现倒计时100秒

梦想不抛弃苦心追求的人,只要不停止追求,你们会沐浴在梦想的光辉之中。再美好的梦想与目标,再完美的计划和方案,如果不能尽快在行动中落实,最终只能是纸上谈兵,空想一番。只要瞄准了大方向,坚持不懈地做下去,才能够扫除挡在梦想前面的障碍,实现美好的人生蓝图。springboot入门系列(十一)websocket实现倒计时100秒,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

背景

项目里难免需要长连接来观察状态的持续变化,这就需要用到websocket。本次用一个简单的倒计时小程序来进行介绍。本文借鉴自:
websocket入门

后端

pom

父项目:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>${springboot.version}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

子项目

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

只需要这一个依赖即可。

配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @author xutianze
 */
@Configuration
public class WebSocketConfig {

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

核心逻辑

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;

/**
 * @author xutianze
 */
@ServerEndpoint(value = "/client/{userId}")
@Component
public class WarningPushSocket {

    private static Logger logger = LogManager.getLogger(WarningPushSocket.class.getName());
    private static final String START = "start";

    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    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
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException, InterruptedException {
        logger.info("来终端的警情消息:" + message);
        if(START.equals(message)) {
            int x = 100;
            while (x > 0) {
                sendMessage(String.format("当前的值为:%d", x));
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    logger.error("倒计时错误");
                }
                --x;
            }
        } else {
            sendMessage(message);
        }
    }

    /**
     * 发生错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("wsClientMap发生错误!");
        error.printStackTrace();
    }

    /**
     * 给所有客户端群发消息
     *
     * @param message 消息内容
     */
    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>
		<script type="text/javascript">
			var websocket = null


			//判断当前浏览器是否支持WebSocket
			if ('WebSocket' in window) {
				websocket = new WebSocket("ws://localhost:8080/client/mio")
			} 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() {
				console.log('关闭链接')
				websocket.close()
			}


			//发送消息
			function send() {
				var message = document.getElementById('text').value
				websocket.send(message)
			}
		</script>
	</head>


	<body>
		Welcome<br />
		<input id="text" type="text" />
		<div>
			<button onclick="send()">send</button>
			<button onclick="closeWebSocket()">close</button>
		</div>
		<div id="message">
		</div>
	</body>
</html>

done

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153510.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!