zoukankan      html  css  js  c++  java
  • WebSocket消息推送(群发和指定到个人)

    1.客户端:  HTML

    <!DOCTYPE html>
    <html>
    <head>
        <title>Java后端WebSocket的Tomcat实现</title>
    </head>
    <body>
        Welcome<br/><input id="text" type="text"/>
        <button onclick="send()">发送消息</button>
        <hr/>
        <!--userno:发送消息人的编号-->
        <div id="userno">1234</div>
        <button onclick="closeWebSocket()">关闭WebSocket连接</button>
        <hr/>
        <div id="message"></div>
    </body>
    
    <script type="text/javascript">
        var websocket = null;
        var userno=document.getElementById('userno').innerHTML;
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            websocket = new WebSocket("ws://localhost:8899/websocket/"+userno);
        }
        else {
            alert('当前浏览器 Not support websocket')
        }
    
        //连接发生错误的回调方法
        websocket.onerror = function () {
            setMessageInnerHTML("WebSocket连接发生错误");
        };
    
        //连接成功建立的回调方法
        websocket.onopen = function () {
            setMessageInnerHTML("WebSocket连接成功");
        }
    
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            setMessageInnerHTML(event.data);
        }
    
        //连接关闭的回调方法
        websocket.onclose = function () {
            setMessageInnerHTML("WebSocket连接关闭");
        }
    
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            closeWebSocket();
        }
    
        //将消息显示在网页上
        function setMessageInnerHTML(sendMessage) {
            document.getElementById('message').innerHTML += sendMessage + '<br/>';
        }
    
        //关闭WebSocket连接
        function closeWebSocket() {
            websocket.close();
        }
    
        //发送消息
        function send() {
            var message = document.getElementById('text').value;//要发送的消息内容
            var now=getNowFormatDate();//获取当前时间
            document.getElementById('message').innerHTML += (now+"发送人:"+userno+'<br/>'+"---"+message) + '<br/>';
            document.getElementById('message').style.color="red";
            var ToSendUserno="4567";//接收人编号:4567
            message=message+"|"+ToSendUserno//将要发送的信息和内容拼起来,以便于服务端知道消息要发给谁
            websocket.send(message);
        }
        //获取当前时间
        function getNowFormatDate() {
            var date = new Date();
            var seperator1 = "-";
            var seperator2 = ":";
            var month = date.getMonth() + 1;
            var strDate = date.getDate();
            if (month >= 1 && month <= 9) {
                month = "0" + month;
            }
            if (strDate >= 0 && strDate <= 9) {
                strDate = "0" + strDate;
            }
            var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
                    + " " + date.getHours() + seperator2 + date.getMinutes()
                    + seperator2 + date.getSeconds();
            return currentdate;
    } 
    </script>
    </html>

    2.服务端:

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.example.websocket</groupId>
    	<artifactId>websocketdemo</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>websocketdemo</name>
    	<description>Demo project for Spring Boot</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.8.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-messaging</artifactId>
    		</dependency>
    		<!--添加websocket依赖-->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-websocket</artifactId>
    			<version>1.3.5.RELEASE</version>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    
    </project>
    

     java实体类:

    WebSocketTest
    package com.example.websocket.websocketdemo;
    
    
    import org.springframework.stereotype.Component;
    
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
     * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
     * @ServerEndpoint 可以把当前类变成websocket服务类
     */
    @ServerEndpoint("/websocket/{userno}")
    @Component
    public class WebSocketTest {
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
        private static ConcurrentHashMap<String, WebSocketTest> webSocketSet = new ConcurrentHashMap<String, WebSocketTest>();
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
        //当前发消息的人员编号
        private String userno = "";
    
        /**
         * 连接建立成功调用的方法
         *
         * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         */
        @OnOpen
        public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) {
            System.out.println(param);
            userno = param;//接收到发送消息的人员编号
            this.session = session;
            webSocketSet.put(param, this);//加入map中
            addOnlineCount();           //在线数加1
            System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            if (!userno.equals("")) {
                webSocketSet.remove(userno);  //从set中删除
                subOnlineCount();           //在线数减1
                System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
            }
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         * @param session 可选的参数
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            System.out.println("来自客户端的消息:" + message);
    //        session.get
            //群发消息
            if (1 < 2) {
                sendAll(message);
            } else {
                //给指定的人发消息
                sendToUser(message);
            }
        }
    
        /**
         * 给指定的人发送消息
         * @param message
         */
        private void sendToUser(String message) {
            String sendUserno = message.split("[|]")[1];
            String sendMessage = message.split("[|]")[0];
            String now = getNowTime();
            try {
                if (webSocketSet.get(sendUserno) != null) {
                    webSocketSet.get(sendUserno).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + sendMessage);
                } else {
                    System.out.println("当前用户不在线");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 给所有人发消息
         * @param message
         */
        private void sendAll(String message) {
            String now = getNowTime();
            String sendMessage = message.split("[|]")[0];
            //遍历HashMap
            for (String key : webSocketSet.keySet()) {
                try {
                    //判断接收用户是否是当前发消息的用户
                    if (!userno.equals(key)) {
                        webSocketSet.get(key).sendMessage(now + "用户" + userno + "发来消息:" + " <br/> " + sendMessage);
                        System.out.println("key = " + key);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 获取当前时间
         *
         * @return
         */
        private String getNowTime() {
            Date date = new Date();
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = format.format(date);
            return time;
        }
        /**
         * 发生错误时调用
         *
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            System.out.println("发生错误");
            error.printStackTrace();
        }
    
        /**
         * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
         *
         * @param message
         * @throws IOException
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
            //this.session.getAsyncRemote().sendText(message);
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocketTest.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocketTest.onlineCount--;
        }
    
    
    }
    WebSocketConfig
    package com.example.websocket.websocketdemo;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }

    SpringBoot启动类:

    package com.example.websocket.websocketdemo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    
    @SpringBootApplication
    public class WebsocketdemoApplication extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer {
    
        public static void main(String[] args) {
            SpringApplication.run(WebsocketdemoApplication.class, args);
        }
    
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.setPort(8899);//设置服务端口为8899
        }
    
    }

    源码下载地址:http://download.csdn.net/download/zb18829224773/10121298(导入直接可以跑)

  • 相关阅读:
    POJ 1611 The Suspects
    POJ 2001 Shortest Prefixes(字典树)
    HDU 1251 统计难题(字典树 裸题 链表做法)
    G++ C++之区别
    PAT 乙级 1013. 数素数 (20)
    PAT 乙级 1012. 数字分类 (20)
    PAT 乙级 1009. 说反话 (20)
    PAT 乙级 1008. 数组元素循环右移问题 (20)
    HDU 6063 17多校3 RXD and math(暴力打表题)
    HDU 6066 17多校3 RXD's date(超水题)
  • 原文地址:https://www.cnblogs.com/zhang-bo/p/7844062.html
Copyright © 2011-2022 走看看