java websocket 原生方式,代码编写

2021-06-15 18:03

阅读:559

标签:监听   定义   通信   zed   sockets   需要   apache   eth   throwable   

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

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

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

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

dependency>
    groupId>org.springframeworkgroupId>
    artifactId>spring-websocketartifactId>
    version>5.0.7.RELEASEversion>
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 webSocketSet = new CopyOnWriteArraySet();
    
    // 若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    //    ConcurrentHashMap 线程安全,比 hashtable 效率高一些,用空间换时间
    public static ConcurrentHashMap webSocketMap = new ConcurrentHashMap();

    // 与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户)
    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">


title>Insert title heretitle>


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="/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
"); return false; } webSocket = new WebSocket("ws://"+serveraddress+"/websocket"); // 收到服务端消息 webSocket.onmessage = function (msg) { if(msg.data == "&"){ }else{ $("#receivedMessage").append(getNowFormatDate()+" 收到消息 : "+msg.data+"
"); } }; // 异常 webSocket.onerror = function (event) { heartflag = false; $("#connectStatu").append(getNowFormatDate()+" 异常
"); }; // 建立连接 webSocket.onopen = function (event) { heartflag = true; heart(); $("#connectStatu").append(getNowFormatDate()+" 建立连接成功
"); tryTime = 0; }; // 断线重连 webSocket.onclose = function () { heartflag = false; // 重试10次,每次之间间隔10秒 if (tryTime 10) { setTimeout(function () { webSocket = null; tryTime++; initSocket(); $("#connectStatu").append( getNowFormatDate()+""+tryTime+"次重连
"); }, 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()+" 心跳
"); } setTimeout("heart()", 10*60*1000); } script> html>

4. 页面效果

技术分享图片

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

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

java websocket 原生方式,代码编写

标签:监听   定义   通信   zed   sockets   需要   apache   eth   throwable   

原文地址:https://www.cnblogs.com/season1992/p/9729507.html


评论


亲,登录后才可以留言!