WebSocket前后端实现

Posted lovollll

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebSocket前后端实现相关的知识,希望对你有一定的参考价值。


websocket.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@include file="/common/common-uplan.jsp"%>
<script>
var wsUri ="ws://localhost:8080/xbnet-product-web/websocket?username=${user.name}&userId=${user.operatorId}"; 

//判断浏览器是否支持websocket
if(window.WebSocket){
    //创建websocket连接
    websocket = new WebSocket(wsUri);
    console.log(‘This browser supports WebSocket‘);
}else{
    console.log(‘This browser does not supports WebSocket‘);
}

//连接成功建立的回调方法
websocket.onopen = function() { 
    writeToScreen("webSocket连接成功"); 
}; 

//连接关闭的回调方法
 websocket.onclose = function() { 
     writeToScreen("webSocket连接关闭");
 }; 
    
//接收到消息的回调方法
websocket.onmessage = function(event) { 
    writeToScreen(event.data);
}; 

//连接发生错误的回调方法
websocket.onerror = function() { 
    writeToScreen("WebSocket连接发生错误");
}; 
  
//关闭WebSocket连接
function closeWebSocket() {
    websocket.close();
}  

function doSend() { 
    var text = $("#text") .val();
    var users = $(‘input:checkbox:checked‘);
    var touser = "";
    if (users.length  == 0){
        alert("请选择发送人!");
        return;
    } else{
        for (var i = 0; i < users.length; i++){
            touser += users[i].value + "|";
        }
    }
    if (text != "" && text != undefined && text != null){
        var obj = null;
        obj = {
                toUser:touser,  
                fromUser:"${user.operatorId}",  
                msg:text
        };
        obj = JSON.stringify(obj);
        websocket.send(obj);
        $("#text") .val("");
    }
}  

function writeToScreen(message) { 
    var output = document.getElementById(‘output‘);
    var pre = document.createElement("p"); 
    pre.style.wordWrap = "break-word"; 
    pre.innerHTML = message; 
    output.appendChild(pre); 
}  

//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
    closeWebSocket();
}

</script>
<div id="main">
    <div id="left" style="width: 350px;height: 280px;float: left;">
        <!-- 消息显示栏 -->
        <div id="output" style="width: 350px;height: 240px"></div><hr/>
        
        <!-- 消息发送栏 -->
        <input id="text" type="text"/>
        <button onclick="doSend()">发送消息</button>
    </div>
    
    
    <!-- 用户列表 -->
    <div class="up-form-group up-col-sm-24" style="width: 100px;height: 280px;float: right;border-left:1px solid gray">
         <c:forEach items="${operator }" var="rowdata" varStatus="status">
             <div class="up-col-sm-24">
                 <label class="u_check">
                     <input id="" value="${rowdata.operatorId }" type="checkbox">
                     <i class="up-text-primary icon-u-check-empty"></i>${rowdata.name }
                 </label>
             </div>
         </c:forEach>
    </div>
</div>  


WebSocket.java


package com.eshore.security.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

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 com.alibaba.fastjson.JSON;

/**
 * webSocket
 * @author renb
 * @creatDate 2018年2月22日
 */
 // @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 //               注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
@ServerEndpoint("/websocket")
public class WebSocket {
    // 静态变量,用来记录当前在线连接数。
    private static int onlineCount = 0;

    // concurrent包的线程安全Map,用来存放每个客户端对应的回话信息。
    private static ConcurrentMap<String, Session> webSocketMap = 
            new ConcurrentHashMap<String, Session>();
    private String userName; //当前用户
    private String userId; //当前用户id,作为webSocketMap科key
    /**
     * 连接建立成功调用的方法
     * 
     * @param session
     *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session) {
        String str = session.getQueryString(); //可以得到ws://路径?后面的所有字符串  
        userName = str.split("&")[0].split("=")[1]; 
        userId = str.split("&")[1].split("=")[1];
        try {
            userName = URLDecoder.decode(userName, "utf-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        webSocketMap.put(userId, session); // 加入map中
        addOnlineCount(); // 在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }

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

    /**
     * 收到客户端消息后调用的方法
     * 
     * @param message
     *            客户端发送过来的消息
     * @param session
     *            可选的参数
     */
    @SuppressWarnings("rawtypes")
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(userName + ":" + message);
        Map maps = (Map) JSON.parse(message);
        Map<String, String> resultMap = new HashMap<String, String>();
        for (Object map : maps.entrySet()) {  
            String  key = (String) ((Map.Entry) map).getKey();
            String value = (String) ((Map.Entry) map).getValue();
            resultMap.put(key, value);
        } 
        String msg = userName + ":" + resultMap.get("msg");
        String toUsers = resultMap.get("toUser");
        String fromUser = resultMap.get("fromUser");
        String[] users = toUsers.split("\|");
        try {
            webSocketMap.get(fromUser).getBasicRemote().sendText(msg);
            Set<String> set = webSocketMap.keySet();
            List<String> userList = new ArrayList<String>();
            for (String str : set) {
                userList.add(str);
            }
            if (users.length > 0) {
                for (int i = 0; i < users.length; i++) {
                    if (userList.contains(users[i])) {
                        webSocketMap.get(users[i]).getBasicRemote().sendText(msg);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生错误时调用
     * 
     * @param session 会话
     * @param error 异常
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }   public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 
     * @creatUser renb
     * @creatDate 2018年2月22日
     *
     */
    public static synchronized void addOnlineCount() {
        WebSocket.onlineCount++;
    }

    /**
     * 
     * @creatUser renb
     * @creatDate 2018年2月22日
     *
     */
    public static synchronized void subOnlineCount() {
        WebSocket.onlineCount--;
    }

    
}


以上是关于WebSocket前后端实现的主要内容,如果未能解决你的问题,请参考以下文章

springboot2实现Websocket前后端通信

关于前后端通过websocket实现消息推送的总结

前后端如何互联?---websocket

前后端常用通讯方式-- ajax websocket

前后端使用利用WebSocket进行通信

前后端使用利用WebSocket进行通信