java websocket 原生方式,代码编写

Posted season1992

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java websocket 原生方式,代码编写相关的知识,希望对你有一定的参考价值。

  最近啊,boss 跟我说,我们的系统需要有消息推送功能,他说可以使用 dwt 或者是我自己找一个框架进行推送,我因为之前的公司就是使用的 websocket,所以我选择了 websocket。

  websocket 是一种新的接口协议,请求的时候需要带上前缀 ws : ws://www.demo.com 他可以保证会话的长链接,比在 http 设置 keepAlive 效果能好一些,相比轮询、长连接能效率更高一些。

  废话不多说,开始上代码吧。

1. 我使用的 maven 进行代码管理,所以呢首先需要设置 jar 包依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>5.0.7.RELEASE</version>
</dependency>

2. 编写 java 代码

package com.goldenstone.stuapp_web.ws;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
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.ServerEndpoint;

import org.apache.log4j.Logger;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 *                 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint(value = "/websocket")
public class WebSocketTest {

    private static Logger logger = Logger.getLogger(WebSocketTest.class);
    
    // 线程安全的静态变量,表示在线连接数
    private static volatile int onlineCount = 0;    //    这个类不交由spring管理?

    // 用来存放每个客户端对应的WebSocketTest对象,适用于同时与多个客户端通信
    public static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
    
    // 若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    //    ConcurrentHashMap 线程安全,比 hashtable 效率高一些,用空间换时间
    public static ConcurrentHashMap<Session, Object> webSocketMap = new ConcurrentHashMap<Session, Object>();

    // 与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户)
    private Session session;

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this); // 加入set中
        webSocketMap.put(session, this); // 加入map中
        addOnlineCount(); // 在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session closeSession) {
        webSocketSet.remove(this); // 从set中删除
        webSocketMap.remove(closeSession); // 从map中删除
        subOnlineCount(); // 在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session mySession) throws Exception {

        logger.info("来自客户端的消息:" + message);
        // --------------群发消息(多用于聊天室场景)
        /*
         * for (WebSocketTest item : webSocketSet) { try { item.sendAllMessage(message);
         * } catch (IOException e) { e.printStackTrace(); continue; } }
         */

        // 推送给单个客户端
        for (Session session : webSocketMap.keySet()) {
            if (session.equals(mySession)) {
                WebSocketTest item = (WebSocketTest) webSocketMap.get(mySession);
                try {
                    String msg = "嗨,这是返回的信息";
                    item.sendMessage(mySession, msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

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

    // 给所有客户端发送信息
    public void sendAllMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    // 定向发送信息
    public void sendMessage(Session mySession, String message) throws IOException {
        synchronized (this) {
            try {
                if (mySession.isOpen()) {// 该session如果已被删除,则不执行发送请求,防止报错
                    // this.session.getBasicRemote().sendText(message);
                    mySession.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketTest.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketTest.onlineCount--;
    }

}

3. 编写前端代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- <meta http-equiv="refresh" content="1;url=http://www.taobao.com"> -->

<title>Insert title here</title>

<!-- url引用两种写法,都行,在这个html中css引用、js引用,使用了2钟写法 -->
<link rel="stylesheet" th:href="@{/layui/css/layui.css}" id="bscss"></link>
<script src="/stuapp_web/layui/layui.js" charset="utf-8"></script>
<script src="/stuapp_web/jquery-3.3.1.js" charset="utf-8"></script>

<script type="text/javascript">

//     $(function () { 
//         storeTempCode();
//     });
</script>

</head>


<body>
server地址 :  <input id ="serveraddress" type="text" value="10.10.18.179:8080/stuapp_web"/><br/>
您的用户id :  <input id ="userId" type="text" /><br/>
<button onclick="initSocket()">连接</button><br/>

=====================================================<br/>
消息 :  <input id ="message" type="text" /><br/>
<button onclick="send()">发送</button><br/>
=====================================================<br/>
连接状态 : <button onclick="clearConnectStatu()">清空</button><br/>
<div id="connectStatu"></div><br/>

=====================================================<br/>
收到消息 :<br/>
<div id="receivedMessage"></div><br/>
=====================================================<br/>
心跳 :<br/>
<div id="heartdiv"></div><br/>

</body>

<script src="<%=basePath%>/resources/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
    var heartflag = false;
    var webSocket = null;    //    websocket全局变量
    var tryTime = 0;
    $(function () {

//        initSocket();
        window.onbeforeunload = function () {

        };
    });

    /**
     * 初始化websocket,建立连接
     */
    function initSocket() {
        var serveraddress = $("#serveraddress").val();
        var userId = $("#userId").val();

        if (!window.WebSocket) {    //    判断浏览器是否支持 websocket
            $("#connectStatu").append(getNowFormatDate()+"  您的浏览器不支持ws<br/>");
            return false;
        }

        webSocket = new WebSocket("ws://"+serveraddress+"/websocket");
        
        // 收到服务端消息
        webSocket.onmessage = function (msg) {
            if(msg.data == "&"){

            }else{
                $("#receivedMessage").append(getNowFormatDate()+"  收到消息 : "+msg.data+"<br/>");
            }
        };

        // 异常
        webSocket.onerror = function (event) {
            heartflag = false;
            $("#connectStatu").append(getNowFormatDate()+"  异常<br/>");
        };

        // 建立连接
        webSocket.onopen = function (event) {
            heartflag = true;
            heart();
            $("#connectStatu").append(getNowFormatDate()+"  建立连接成功<br/>");
            tryTime = 0;
        };

        // 断线重连
        webSocket.onclose = function () {
            heartflag = false;
            // 重试10次,每次之间间隔10秒
            if (tryTime < 10) {
                setTimeout(function () {
                    webSocket = null;
                    tryTime++;
                    initSocket();
                    $("#connectStatu").append( getNowFormatDate()+""+tryTime+"次重连<br/>");
                }, 3*1000);
            } else {
                alert("重连失败.");
            }
        };

    }

    function send(){
        var message = $("#message").val();
        webSocket.send(message);
    }

    function clearConnectStatu(){
        $("#connectStatu").empty();
    }

    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;
    }

    function heart() {
        if (heartflag){
            webSocket.send("&");
            $("#heartdiv").append(getNowFormatDate()+"  心跳 <br/>");
        }
        setTimeout("heart()", 10*60*1000);

    }
</script>


</html>

4. 页面效果

技术分享图片

暂时就到这里了,然后我会慢慢修改的

就是靠这口吃饭的,我会一直更下去的


以上是关于java websocket 原生方式,代码编写的主要内容,如果未能解决你的问题,请参考以下文章

如何从 socket.io 获取原生事件数组?

Java WebSocket:如何在不编写客户端的情况下测试服务器 WebSocket 端点 [关闭]

java程序代码代写代写tree数据结构作业

是否可以在原生 Android 应用程序中使用 WebSockets 或类似的?

Java WebSocket:onMessage 未触发

java socket编写服务端