美文网首页
Java 原生 WebSocket 仅H5支持

Java 原生 WebSocket 仅H5支持

作者: 酷酷的小k | 来源:发表于2018-03-22 20:54 被阅读0次

    简述:支持发送公告、发送指定用户及异地登录。

    所需jar包:
    javaee-api.jar
    gson.jar

    定义收发消息实体类:

    package com.test.springWebsocket;
    
    public class WebMessage {
    
        /**
         * 用户id
         */
        private Long userId;
    
        /**
         * 用户名
         */
        private String username;
    
        /**
         * 客户端标记
         */
        private String clientMark;
    
        /**
         * 内容
         */
        private String contents;
    
        /**
         * 消息类型,1.公告,2.点对点发消息,3.检查异地登录
         */
        private String type;
    
        public Long getUserId() {
            return userId;
        }
    
        public void setUserId(Long userId) {
            this.userId = userId;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getClientMark() {
            return clientMark;
        }
    
        public void setClientMark(String clientMark) {
            this.clientMark = clientMark;
        }
    
        public String getContents() {
            return contents;
        }
    
        public void setContents(String contents) {
            this.contents = contents;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    }
    

    定义WebSocketServlet类:

    package com.test.nativeWebsocket;
    
    import com.google.gson.Gson;
    import com.test.springWebsocket.WebMessage;
    
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    
    /**
     * 所需jar包:javaee-api.jar
     * 客户端连接的url
     */
    @ServerEndpoint("/native-socket-endpoint/{userId}/{username}/{clientMark}")
    public class CustomWebSocketServlet {
    
        private Long userId;
    
        private String username;
    
        private String clientMark;
    
        private Session session;
    
        public Long getUserId() {
            return userId;
        }
    
        public String getUsername() {
            return username;
        }
    
        public String getClientMark() {
            return clientMark;
        }
    
        public Session getSession() {
            return session;
        }
    
        /**
         * 连接建立成功调用的方法
         *
         * @param session    可选的参数.session为与某个客户端的连接会话,需要通过它来给客户端发送数据
         * @param userId     userId
         * @param username   username
         * @param clientMark clientMark
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("userId") Long userId, @PathParam("username") String username, @PathParam("clientMark") String clientMark) {
            WebMessage webMsg = new WebMessage();
            webMsg.setUserId(userId);
            webMsg.setUsername(username);
            webMsg.setClientMark(clientMark);
            webMsg.setType("3");
            CustomWebSocketHandler.sendToUserMsg(webMsg);
            this.session = session;
            this.userId = userId;
            this.username = username;
            this.clientMark = clientMark;
            CustomWebSocketHandler.addWebSocketServlet(this);
            System.out.println(String.format("用户<%s>打开WebSocket连接...", username));
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            CustomWebSocketHandler.removeWebSocketServlet(this);
            System.out.println(String.format("用户<%s>关闭WebSocket连接...", username));
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param msg     客户端发送过来的消息
         * @param session 可选的参数
         */
        @OnMessage
        public void onMessage(String msg, Session session) {
            WebMessage webMsg = new Gson().fromJson(msg, WebMessage.class);
            if (webMsg.getUserId() == null) {
                CustomWebSocketHandler.sendToAllMsg(webMsg);
            } else {
                CustomWebSocketHandler.sendToUserMsg(webMsg);
            }
        }
    
        /**
         * 发生错误时调用
         *
         * @param session Session
         * @param error   Throwable
         */
        @OnError
        public void onError(Session session, Throwable error) {
            error.printStackTrace();
        }
    }
    

    定义WebSocketHandler类:

    package com.test.nativeWebsocket;
    
    import com.google.gson.Gson;
    import com.test.springWebsocket.WebMessage;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class CustomWebSocketHandler {
    
        private static List<CustomWebSocketServlet> userSocketList = new ArrayList<>();
    
        public static synchronized void addWebSocketServlet(CustomWebSocketServlet webSocketServlet) {
            userSocketList.add(webSocketServlet);
        }
    
        public static synchronized void removeWebSocketServlet(CustomWebSocketServlet webSocketServlet) {
            userSocketList.remove(webSocketServlet);
        }
    
        /**
         * 将消息发送给所有用户
         *
         * @param webMsg WebMessage
         */
        public static void sendToAllMsg(WebMessage webMsg) {
            String jsonStr = new Gson().toJson(webMsg);
            for (CustomWebSocketServlet webSocketServlet : userSocketList) {
                try {
                    //webSocketServlet.getSession().getBasicRemote().sendText(jsonStr);
                    webSocketServlet.getSession().getAsyncRemote().sendText(jsonStr);
                } catch (Exception e) {
                    System.out.println(String.format("用户<%s>发送消息失败|消息体<%s>", webSocketServlet.getUsername(), jsonStr));
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 将消息发送给指定用户
         *
         * @param webMsg WebMessage
         */
        public static void sendToUserMsg(WebMessage webMsg) {
            String jsonStr = new Gson().toJson(webMsg);
            for (CustomWebSocketServlet webSocketServlet : userSocketList) {
                if (webSocketServlet.getUserId().equals(webMsg.getUserId())) {
                    try {
                        //webSocketServlet.getSession().getBasicRemote().sendText(jsonStr);
                        webSocketServlet.getSession().getAsyncRemote().sendText(jsonStr);
                    } catch (Exception e) {
                        System.out.println(String.format("用户<%s>发送消息失败|消息体<%s>", webSocketServlet.getUsername(), jsonStr));
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    定义jsp页面RequestMapping:

    /**
         * 原生 WebSocket 页面
         *
         * @param request HttpServletRequest
         * @return String
         */
        @RequestMapping("/native-websocket.xhtm")
        public String nativeWebsocket(HttpServletRequest request) {
            String clientMark = (String) request.getSession().getAttribute("clientMark");
            if (clientMark == null) {
                clientMark = GenerateUtil.getUUID();
                request.getSession().setAttribute("clientMark", clientMark);
            }
            Admin admin = (Admin) request.getSession().getAttribute("admin");
            request.setAttribute("userId", admin.getId());
            request.setAttribute("username", admin.getAdmin());
            request.setAttribute("clientMark", clientMark);
            return "nativeWebsocket/nativeWebsocket";
        }
    

    定义jsp页面:

    <!DOCTYPE html>
    
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    
    <%
        String rootPath = request.getContextPath();
        String wsBasePath = "ws://" + request.getServerName() + ":" + request.getServerPort() + rootPath + "/";
    %>
    
    <html>
        <head>
            <title>Native WebSocket</title>
            <meta http-equiv="Expires" content="0"/>
            <meta http-equiv="Cache" content="no-cache"/>
            <meta http-equiv="Pragma" content="no-cache"/>
            <meta http-equiv="Cache-Control" content="no-cache"/>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <script type="text/javascript" src="../../../static/js/plugins/jquery/jquery-1.9.1.min.js"></script>
            <script type="text/javascript">
                var userId = "${userId}";
                var username = "${username}";
                var clientMark = "${clientMark}";
                var wsBasePath = "<%=wsBasePath%>";
            </script>
            <style>
                .c_box {
                    width: 800px;
                    height: 300px;
                    border: 1px solid;
                    overflow: auto;
                }
            </style>
        </head>
        <body>
            <div>用户id:${userId}</div>
            <div>用户名:${username}</div>
            <div>
                <span>公告:</span>
                <input type="text" id="notice"/>
                <input type="button" id="sendNotice" value="发送"/>
            </div>
            <div>
                <span>用户id:</span>
                <input type="text" id="toUserId"/>
                <span>消息:</span>
                <input type="text" id="toUserMsg"/>
                <input type="button" id="sendToUser" value="发送"/>
            </div>
            <div>公告列表:</div>
            <div id="noticeList" class="c_box"></div>
            <div>消息列表:</div>
            <div id="msgList" class="c_box"></div>
            <script type="text/javascript" src="../../../static/js/nativeWebsocket/nativeWebsocket.js"></script>
        </body>
    </html>
    

    定义JavaScript脚本:

    var ws = null;
    
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        ws = new WebSocket(wsBasePath + "native-socket-endpoint/" + userId + "/" + username + "/" + clientMark);
        //连接发生错误的回调方法
        ws.onerror = function () {
            console.log("WebSocket连接错误");
        };
        //连接成功建立的回调方法
        ws.onopen = function () {
            console.log("WebSocket连接成功");
        };
        //接收到消息的回调方法
        ws.onmessage = function (event) {
            showMsg(JSON.parse(event.data));
        };
        //连接关闭的回调方法
        ws.onclose = function () {
            console.log("WebSocket连接关闭");
        };
    } else {
        alert('当前浏览器 Not support WebSocket');
    }
    
    function closeSocket() {
        if (ws == null || ws.readyState == 2 || ws.readyState == 3) {
            return true;
        }
        ws.close();
    }
    
    function showMsg(webMsg) {
        switch (webMsg['type']) {
            //公告
            case '1': {
                var noticeHtm = '<div>' + webMsg['contents'] + '</div>';
                $('#noticeList').append(noticeHtm);
                $("#noticeList").scrollTop($("#noticeList")[0].scrollHeight);
                break;
            }
            //点对点发消息
            case '2': {
                var msgHtm = '<div>' + webMsg['contents'] + '</div>';
                $('#msgList').append(msgHtm);
                $("#msgList").scrollTop($("#msgList")[0].scrollHeight);
                break;
            }
            //检查异地登录
            case '3': {
                if (webMsg['clientMark'] != clientMark) {
                    closeSocket();
                    alert('您的账号在另一处登录');
                }
                break;
            }
            default: {
                alert("WebSocket接收到未知消息...");
                break;
            }
        }
    }
    
    //监听窗口关闭事件,当窗口关闭时,主动去关闭WebSocket连接,防止连接还没断开就关闭窗口,server端会抛异常.
    window.onbeforeunload = function () {
        closeSocket();
    };
    
    $("#sendNotice").on("click", function () {
        if (ws == null) {
            alert('WebSocket连接未打开');
            return true;
        }
        if (ws.readyState == 0) {
            alert('WebSocket正在连接中,请稍后再发送消息');
            return true;
        }
        if (ws.readyState == 2) {
            alert('WebSocket连接正在关闭中,无法发送消息');
            return true;
        }
        if (ws.readyState == 3) {
            alert('WebSocket连接已关闭,无法发送消息');
            return true;
        }
        var notice = $("#notice").val();
        if (notice.length > 0) {
            var webMsg = {
                'contents': notice,
                'type': '1'
            };
            ws.send(JSON.stringify(webMsg));
        }
    });
    
    $("#sendToUser").on("click", function () {
        if (ws == null) {
            alert('WebSocket连接未打开');
            return true;
        }
        if (ws.readyState == 0) {
            alert('WebSocket正在连接中,请稍后再发送消息');
            return true;
        }
        if (ws.readyState == 2) {
            alert('WebSocket连接正在关闭中,无法发送消息');
            return true;
        }
        if (ws.readyState == 3) {
            alert('WebSocket连接已关闭,无法发送消息');
            return true;
        }
        var toUserId = $("#toUserId").val();
        var toUserMsg = $("#toUserMsg").val();
        if (toUserId.length > 0 && toUserMsg.length > 0) {
            var webMsg = {
                'userId': toUserId,
                'username': username,
                'contents': toUserMsg,
                'type': '2'
            };
            ws.send(JSON.stringify(webMsg));
        }
    });
    

    相关文章

      网友评论

          本文标题:Java 原生 WebSocket 仅H5支持

          本文链接:https://www.haomeiwen.com/subject/ssszqftx.html