SSM+WebSocket实现一个简易网页版通讯工具

编译环境:jdk1.8 , tomcat8.0+ , IDEA

这里主要讲一下websocket的信息传递,以如何实现多人实时在线聊天为例:

websocket主要的三个类

MyWebSocketConfig主要负责配置websocket的处理器和握手拦截器

MyHandShakeInterceptor 是websocket的拦截器

MyWebSocketHander是websocket的处理器

@Component
@EnableWebSocket
public class MyWebSocketConfig implements WebSocketConfigurer {

    @Autowired
    private MyWebSocketHander myWebSocketHander;

    private static final String LINK_URI = "websocket.do";
    //添加websocket处理器,添加握手拦截器  拦截器先执行 然后到处理器
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry.addHandler(myWebSocketHander,LINK_URI).addInterceptors(new MyHandShakeInterceptor());
    }
}
/*   private static Map<WebSocketSession,String> map = new HashMap<WebSocketSession, String>();
 * websocket握手拦截器
 * 拦截握手前,握手后的两个切面
 */
@Component
public class MyHandShakeInterceptor implements HandshakeInterceptor {


    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        if(serverHttpRequest instanceof ServletServerHttpRequest){
            HttpServletRequest servletRequest = ((ServletServerHttpRequest)serverHttpRequest).getServletRequest();
            User user = (User)servletRequest.getSession().getAttribute("user");
            //这里给map赋值 相当于websockethandler的afterConnectionEstablished方法里的WebSocketSession
            //key是session,value是变量
            map.put("ws_user", user);
          
        }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
      
    }
}

实时通信的具体流程:

前端

<% String path = request.getContextPath();%>
<html>
link rel="stylesheet" href="<%=path%>/static/css/bootstrap.min.css"
      type="text/css">
<script src="<%=path%>/static/js/jquery.min.js"></script>
<script src="<%=path%>/static/js/bootstrap.min.js"
        type="text/javascript"></script>
<body>

<div id="container" style="width:500px">

    <div id="header">
        <h1 id="title">chat-room</h1></div>
    <div class="middle">
        <div id="menu">
            <p id="tou">欢迎来到聊天室</p>
        </div>

        <div class="chatter" id="chatter">
            <p id="msg"></p>
        </div>
    </div>
    <div id="content">
        <textarea class="form-control" rows="3" placeholder="我想说....."
                  id="msgContent">
        </textarea>
    </div>

    <div style="background-color: #F8F8F8;">
        <div id="buttons">
            <button id="butSent" type="button" class="btn btn-default"
                    onclick="getConnection()">连接
            </button>
            <button type="button" class="btn btn-default"
                    onclick="sendMsgClose()">断开
            </button>
            <button type="button" class="btn btn-default" onclick="sendMsg()">
                发送
            </button>
        </div>
    </div>

    <div id="footer">
        Designed by Annie
    </div>
</div>
</body>
<script>
//打开链接
    function getConnection() {
        if (websocket == null) {
            websocket = new WebSocket(wsServer);
            websocket.onopen = function (evnt) {
                alert("链接服务器成功!");
            };
            //从后台接受数据的函数
            websocket.onmessage = function (evnt) {
                var onlineUser = $("#onlineUser");
                //将收到的数据转换成对象
                var message = eval("(" + evnt.data + ")");
                //显示在线人数及在线用户
                if (message.msgTyp === "notice") {
                    var htmlOnline;
                    $("#onlineNum").text(message.onlineNum);
                    htmlOnline = "<p> " + message.userName + " </p>";
                    //实时更新在线用户
                    onlineUser.html("");
                    $(onlineUser).append(htmlOnline);
                } else if (message.msgTyp === "msg") {
                    showChat(evnt);
                }
            };
            websocket.onerror = function (evnt) {
                alert("发生错误,与服务器断开了链接!")
            };
            websocket.onclose = function (evnt) {
                alert("与服务器断开了链接!")
            };
        } else {
            alert("连接已存在!")
        }
    }


    function showChat(evnt) {
        var message = eval("(" + evnt.data + ")");
        var msg = $("#msg");
        //msg.html是之前的聊天内容,空一行
        msg.html(msg.html() + "<br/>" + "用户: " + message.user + " 发送时间:" +             message.sendDate + "<br/>" + message.sendContent);
    }


  function sendMsg() {
        var msg = $("#msgContent");
        if (websocket == null) {
            alert("连接未开启!");
            return;
        }
        var message = msg.val();
        //输入完成后,清空输入区
        msg.val("");
        if (message == null || message === "") {
            alert("输入不能为空的哦");
            return;
        }
        //向后台MyWebSocketHandler中的handerMessage发送信息
        //这里将信息转成JSON格式发送
        websocket.send(JSON.stringify({
            message: message,
            type: "chatMsg"
        }));
    }

    /**
     * 关闭连接
     */
    function closeConnection() {
        if (websocket != null) {
            websocket.close();
            websocket = null;
            alert("已经关闭连接")
        } else {
            alert("未开启连接")
        }
    }
</script>

</html>

后台MyWebSocketHander接受数据


@Component
public class MyWebSocketHander implements WebSocketHandler {
   
    private final static List<WebSocketSession> USERS = new ArrayList<>();
    private final static List<User> USER_ONLINE = new ArrayList<>();

    /*
    *在链接创建完后就在前端显示在线用户
    */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
       USERS.add(webSocketSession);
        //每次有新的连接,就加入到user集合中
        User user = (User) webSocketSession.getAttributes().get("ws_user");
        USER_ONLINE.add(user);

        List<String> userNamelist = new ArrayList<>();
        for (User u : USER_ONLINE) {
            String userName = u.getUserName();
            userNamelist.add(userName);
        }

        //String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。
        //这里传到前端的应该是JSON格式
        String messageFormat = "{onlineNum:\"%d\",userName:\"%s\" , msgTyp " +
                ":\"%s\"}";
        String msg = String.format(messageFormat, USERS.size(), userNamelist,
                "notice");

        TextMessage testMsg = new TextMessage(msg + "");
        //确保每个用户信息都能同步到
        for (WebSocketSession wss : USERS) {
            wss.sendMessage(testMsg);
        }
    }

    /**
     * 客户端发送服务器的消息时的处理函数,在这里收到消息之后可以分发消息
     */
    @Autowired
    private ChatService chatService;

    @Override
    public void handleMessage(WebSocketSession webSocketSession,
                              WebSocketMessage<?> webSocketMessage) throws Exception {

        String messageFormat = null;

        //发送消息的时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String sentMsgDate = dateFormat.format(new Date());

        User user = (User) webSocketSession.getAttributes().get("ws_user");

        String msgContent = webSocketMessage.getPayload() + "";

        JSONObject chat = JSON.parseObject(msgContent);
        //消息的内容
        String msgJSON = chat.get("message").toString();
        //消息的样式
        String msgJSONType = chat.get("type").toString();

        String chatMsg = "chatMsg";
 
        if (msgJSONType.equals(chatMsg)) {
            //将消息保存到数据库
            ChatMsg chatMessage = new ChatMsg(user.getId(), sentMsgDate,
                    msgJSON);
            chatService.addMessage(chatMessage);

            messageFormat = "{user:\"%s\",sendDate:\"%s\" ," +
                    "sendContent:\"%s\" , msgTyp :\"%s\"}";
            String message = String.format(messageFormat, user.getUserName(),
                    sentMsgDate, msgJSON , "msg");
            TextMessage toMsg = new TextMessage(message + "");
            //遍历所有的用户,发信息,这个要注意哦,要不然不能做到多人同时聊天
            for (WebSocketSession wss : USERS) {
                wss.sendMessage(toMsg);
            }
        }
    }


    @Override
    public void handleTransportError(WebSocketSession webSocketSession,
                                     Throwable throwable) throws Exception {
        USERS.remove(webSocketSession);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession,
                                      CloseStatus closeStatus) throws Exception {
        User userRemove = (User) webSocketSession.getAttributes().get(
                "ws_user");
        USER_ONLINE.remove(userRemove);
        USERS.remove(webSocketSession);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}

所以websocket消息传送流程大致是

websocket.onopen打开链接 --> websocket.send()发送数据 -->后台的MyWebSocketHander接收数据-->WebSocketSession.sendMessage将消息发送给前端 --> 前端websocket.onmessage()接收数据并显示。

github地址:https://github.com/androidlearner2017/simple-chatroom.git

很简单的一个demon,里面有些功能还没有完全实现,继续修改中 ing

  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值