欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用websocket创建一个简单的即时通信工具

程序员文章站 2022-05-21 13:43:54
...

一、关于websocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。--百度百科
简单来说,就是服务器和客户端可以实现双向推送消息。http协议是只能由客户端发起请求,服务器作出响应。这样的效率是很低的。

特点:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。

(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

(3)数据格式比较轻量,性能开销小,通信高效。

(4)可以发送文本,也可以发送二进制数据。

(5)没有同源限制,客户端可以与任意服务器通信。

(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

二、前台代码实现

css

body{
    background-color: #efebdc;
}
#hz-main{
    width: 750px;
    height: 500px;
    /*background-color: red;*/
    margin: 0 auto;
    border-radius:5px;
    margin-top: 9%;
}

#hz-message{
    width: 500px;
    height: 500px;
    float: right;
    background-color: #ffffff;
    border-radius:0px 10px 10px 0;
}

#hz-message-body{
    width: 460px;
    height: 320px;
    background-color: #f9f9f9;
    /*background-color: #E0C4DA;*/
    padding: 10px 20px;
    overflow:auto;
    border-radius:0px 10px 0px 0;
}

#hz-message-input{
    width: 500px;
    height: 99px;
    background-color: white;
    overflow:auto;
    outline: none;
}

#hz-group{
    width: 200px;
    height: 500px;
    background-color: #c7d1ea;
    /*background-color: rosybrown;*/
    float: right;
    border-radius:0px 0px 0px 0px;
}


#hz-set{
    width: 50px;
    height: 500px;
    float: left;
    background-color: #2a2a2b;
    border-radius:10px 0px 0px 10px;
    color: #ebebeb;
}

.hz-message-list{
    min-height: 30px;
    margin: 10px 0;
}
.hz-message-list-text{
    padding: 7px 13px;
    border-radius: 15px;
    width: auto;
    max-width: 85%;
    display: inline-block;
}
.hz-message-list-time{
    padding: 7px 13px;
    text-align: center;
    font-size: 12px;
}


.hz-message-list-username{
    margin: 0;
}

.hz-group-body{
    overflow:auto;
}

.hz-group-list{
    padding: 10px;
    border-bottom:1px solid #ffffff;
}

.left{
    float: left;
    color: #595a5a;
    background-color: #ebebeb;
}
.right{
    float: right;
    color: #f7f8f8;
    background-color: #919292;
}
.hz-badge{
    width: 20px;
    height: 20px;
    background-color: #FF5722;
    border-radius: 50%;
    float: right;
    color: white;
    text-align: center;
    line-height: 20px;
    font-weight: bold;
    opacity: 0;
}

.img-head{
    margin: 5px;
    width: 35px;
    height: 35px;
    border-radius:50%
}
.img-logout{
    margin: 370px 15px;
    width: 20px;
    height: 20px;
    cursor: pointer;
}
.img-big{
    width: 20px;
    height: 20px;
    cursor: pointer;
    float: right;
}

html

<!--<!DOCTYPE>-->
<!--解决idea thymeleaf 表达式模板报红波浪线-->
<!--suppress ALL -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>聊天页面</title>
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <link th:href="@{/css/socketChart.css}" rel="stylesheet" type="text/css"/>
    <script type="text/javascript" src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js"></script>
</head>
<body style="background-image: url('/static/img/webchat.png');background-size: 100%">
<div id="hz-main">
    <div id="hz-message">
        <!-- 头部 -->
        <span id="toUserName"></span>
        <span id="toUserId" hidden></span>
<!--        <hr style="margin: 0px;"/>-->
        <!-- 主体 -->
        <div id="hz-message-body">
        </div>
        <!-- 功能条 -->
        <div id="">
            <button>表情</button>
            <button id="upload-img">图片</button>
           <button>文件</button>
            <button id="jietu">截图</button>
            <button onclick="send()" style="float: right;cursor: pointer;">发送(Ctrl+Enter)</button>
        </div>
        <input type="file" id="btn_file" style="display:none">
        <!-- 输入框 -->
        <div contenteditable="true" id="hz-message-input">
        </div>
    </div>
    <div id="hz-group">
        <div id="hz-group-body"> </div>
    </div>
    <div id="hz-set">
        <img class="img-head" src="/img/login.png" alt="头像"/>
        <span id="talks" th:text="${username}" style="text-align: center;display:block;">请登录</span><span id="talksid" th:text="${userid}" hidden></span>
        <br/>
        <span id="onlineCount" hidden>0</span>
        <img class="img-logout" src="/static/img/tuichuimg.png" title="退出" id="img-logout" onclick="logout()"/> <!--onclick="logout()"-->
<!--        <button style="color: #ffffff;background-color: #2a2a2b;margin: 350px 5px;border:none;cursor: default;" onclick="tuichu()">退出</button>-->
    </div>
</div>
</body>
<script type="text/javascript" th:inline="javascript">
    //项目路径
    ctx = [[${#httpServletRequest.getContextPath()}]];

    //登录名
    var username = /*[[${username}]]*/'';
    var userid = /*[[${userid}]]*/'';
</script>
<script th:src="@{/js/socketChart.js}"></script>
</html>

js

//消息对象数组
var msgObjArr = new Array();

var websocket = null;

//判断当前浏览器是否支持WebSocket, springboot是项目名
if ('WebSocket' in window) {
    websocket = new WebSocket("ws://"+window.location.hostname+":10092/websocket/"+userid+"//"+username);
} else {
    console.error("不支持WebSocket");
}

//连接发生错误的回调方法
websocket.onerror = function (e) {
    console.error("WebSocket连接发生错误");
};

//连接成功建立的回调方法
websocket.onopen = function () {
    //获取所有在线用户
    $.ajax({
        type: 'post',
        url: ctx + "/websocket/getOnlineList",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        data: {username:username},
        success: function (data) {
            var onlineCount = 0;
            if (data.length) {
                //列表
                for (var i = 0; i < data.length; i++) {
                    var user = eval(data[i]);
                    var userName = user.userName;
                    var userId = user.id;
                    var userString1 = user.string1;
                    if(userString1=="在线"){
                        onlineCount++;
                    }
                    $("#hz-group-body").append("<div class=\"hz-group-list\"><span hidden class='hz-group-list-userid'>" + userId + "</span><span class='hz-group-list-username'>" + userName + "</span><span id=\"" + userName + "-status\" >["+userString1+"]</span><div id=\"hz-badge-" + userName + "\" class='hz-badge'>0</div></div>");
                }

                //在线人数
                $("#onlineCount").text(onlineCount);
                // $("#onlineCount").text(data.length);
            }
        },
        error: function (xhr, status, error) {
            console.log("ajax错误!");
        }
    });
}

//接收到消息的回调方法
websocket.onmessage = function (event) {
    var messageJson = eval("(" + event.data + ")");

    //普通消息(私聊)
    if (messageJson.type == "1") {
        //来源用户
        var srcUser = messageJson.srcUser;
        //目标用户
        var tarUser = messageJson.tarUser;
        //消息
        var message = messageJson.message;

        //增加聊天数据
        setMessageInnerHTML(srcUser.username,srcUser.username, message);
    }

    //普通消息(群聊)
    if (messageJson.type == "2"){
        //来源用户
        var srcUser = messageJson.srcUser;
        //目标用户
        var tarUser = messageJson.tarUser;
        //消息
        var message = messageJson.message;

        //增加聊天数据
        setMessageInnerHTML(username,tarUser.username, message);
    }

    //对方不在线
    if (messageJson.type == "0"){
        //消息
        var message = messageJson.message;

        $("#hz-message-body").append(
            "<div class=\"hz-message-list\" style='text-align: center;'>" +
            "<div class=\"hz-message-list-text\">" +
            "<span>" + message + "</span>" +
            "</div>" +
            "</div>");
    }

    //在线人数
    if (messageJson.type == "onlineCount") {
        // getOnLineList();

            //取出username
            var onlineCount = messageJson.onlineCount;
            var userName = messageJson.username;
            var userId = messageJson.userid;
            var oldOnlineCount = $("#onlineCount").text();

            //新旧在线人数对比
            if (oldOnlineCount < onlineCount) {
                if($("#" + userName + "-status").length > 0){
                    $("#" + userName + "-status").text("[在线]");
                }else{
                    $("#hz-group-body").append("<div class=\"hz-group-list\"><span hidden class='hz-group-list-userid'>" + userId + "</span><span class='hz-group-list-username'>" + userName + "</span><span id=\"" + userName + "-status\">[在线]</span><div id=\"hz-badge-" + userName + "\" class='hz-badge'>0</div></div>");
                }
            } else {
                //有人下线
                $("#" + userName + "-status").text("[离线]");
            }
            $("#onlineCount").text(onlineCount);
    }
}

//连接关闭的回调方法
websocket.onclose = function () {
    //alert("WebSocket连接关闭");
}
function getOnLineList(){
    $("#hz-group-body").empty();
    $.ajax({
        type: 'post',
        url: ctx + "/websocket/getOnlineList",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        data: {username:username},
        success: function (data) {
            var onlineCount = 0;
            if (data.length) {
                //列表
                for (var i = 0; i < data.length; i++) {
                    var user = eval(data[i]);
                    var userName = user.userName;
                    var userId = user.id;
                    var userString1 = user.string1;
                    if(userString1=="在线"){
                        onlineCount++;
                    }
                    $("#hz-group-body").append("<div class=\"hz-group-list\"><span hidden class='hz-group-list-userid'>" + userId + "</span><span class='hz-group-list-username'>" + userName + "</span><span id=\"" + userName + "-status\" >["+userString1+"]</span><div id=\"hz-badge-" + userName + "\" class='hz-badge'>0</div></div>");
                }

                //在线人数
                $("#onlineCount").text(onlineCount);
                // $("#onlineCount").text(data.length);
            }
        },
        error: function (xhr, status, error) {
            console.log("ajax错误!");
        }
    });
}
//将消息显示在对应聊天窗口    对于接收消息来说这里的toUserName就是来源用户,对于发送来说则相反
function setMessageInnerHTML(srcUserName,msgUserName, message) {
    console.log("setMessageInnerHTML");
    //判断
    var childrens = $("#hz-group-body").children(".hz-group-list");
    var isExist = false;
    for (var i = 0; i < childrens.length; i++) {
        var text = $(childrens[i]).find(".hz-group-list-username").text();
        if (text == srcUserName) {
            isExist = true;
            break;
        }
    }
    if (!isExist) {
        $("#hz-group-body").append("<div class=\"hz-group-list\"><span class='hz-group-list-username'>" + srcUserName + "</span><span hidden class='hz-group-list-userid'>" + srcUserName + "</span><span id=\"" + srcUserName + "-status\">[在线]</span><div id=\"hz-badge-" + srcUserName + "\" class='hz-badge'>0</div></div>");
    } else {
    }

    // 对于接收消息来说这里的toUserName就是来源用户,对于发送来说则相反
    var username = $("#toUserName").text();

    //刚好打开的是对应的聊天页面
    if (srcUserName == username) {
        $("#hz-message-body").append(
            "<div class=\"hz-message-list\">" +
            "<p class='hz-message-list-username'>"+msgUserName+":</p>" +
            "<div class=\"hz-message-list-text left\">" +
            "<span>" + message + "</span>" +
            "</div>" +
            "<div style=\" clear: both; \"></div>" +
            "</div>");
    } else {
        //小圆点++
        var conut = $("#hz-badge-" + srcUserName).text();
        $("#hz-badge-" + srcUserName).text(parseInt(conut) + 1);
        $("#hz-badge-" + srcUserName).css("opacity", "1");
    }
    endScroll();
}

//发送消息
function send() {
    //消息
    var message = $("#hz-message-input").html().replace("<div><br></div>/g,",'');
    if(null==message||message==""){
        alert("发送消息不能为空")
        return;
    }
    //目标用户名
    var tarUserName = $("#toUserName").text();
    var tarUserId = $("#toUserId").text();
    if(null==tarUserName||tarUserName==""){
        alert("请选择用户")
        return;
    }
    //登录用户名
    var srcUserName = $("#talks").text();
    var srcUserId = $("#talksid").text();
    websocket.send(JSON.stringify({
        "type": "1",
        "tarUser": {"username": tarUserName,"userid": tarUserId},
        "srcUser": {"username": srcUserName,"userid": srcUserId},
        "message": message
    }));
    $("#hz-message-body").append(
        "<div class=\"hz-message-list\">" +
        "<div class=\"hz-message-list-text right\">" +
        "<span>" + message + "</span>" +
        "</div>" +
        "</div>");
    $("#hz-message-input").html("");
    endScroll();
}

//监听点击用户
$("body").on("click", ".hz-group-list", function () {
    $(".hz-group-list").css("background-color", "");
    $(this).css("background-color", "whitesmoke");
    $("#toUserName").text($(this).find(".hz-group-list-username").text());
    $("#toUserId").text($(this).find(".hz-group-list-userid").text());

    //清空旧数据,从对象中取出并追加
    $("#hz-message-body").empty();
    $("#hz-badge-" + $("#toUserName").text()).text("0");
    $("#hz-badge-" + $("#toUserName").text()).css("opacity", "0");

    var toUserId = $("#toUserId").text();
    var toUserName = $("#toUserName").text();
    //查询聊天记录
    $.ajax({
        type: 'get',
        url: ctx + "/websocket/getMessageList",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        data: {fromId:userid,toId:toUserId},
        success: function (data) {
            if (data.length) {
                console.log("messageList============="+data)
                //遍历data,放入msgObjArr中
                var messageArr = new Array();
                for (let i = 0; i < data.length; i++) {
                    var message = eval(data[i]);
                    messageArr.push({
                        toUserName: toUserName,
                        message: [{username: message.fromName, message: message.message, date: message.sendTime}]
                    });
                }
                for (let i = 0; i < messageArr.length; i++) {
                    var messageChannelList = messageArr[i].message;
                    if(messageChannelList.length>0){
                        for (var j = 0; j < messageChannelList.length; j++) {
                            var msgObj = messageChannelList[j];
                            var leftOrRight = "right";
                            var message = msgObj.message;
                            var msgUserName = msgObj.username;
                            var date = msgObj.date;
                            var toUserName = $("#toUserName").text();
                            if (msgUserName == toUserName) {
                                leftOrRight = "left";
                            }
                            if (username == toUserName && msgUserName != toUserName) {
                                leftOrRight = "left";
                            }

                            if (username == toUserName && msgUserName == toUserName) {
                                leftOrRight = "right";
                            }

                            var magUserName = leftOrRight == "left" ? "<p class='hz-message-list-username'>"+msgUserName+":</p>" : "";

                            $("#hz-message-body").append(

                                "<div class=\"hz-message-list\">" +
                                "<div class=\"hz-message-list-time\">" +
                                "<span>" + date + "</span>" +
                                "</div>" +
                                magUserName+
                                "<div class=\"hz-message-list-text " + leftOrRight + "\">" +
                                "<span>" + message + "</span>" +
                                "</div>" +
                                "<div style=\" clear: both; \"></div>" +
                                "</div>");
                        }
                    }
                }
            }
            endScroll();
        },
        error: function (xhr, status, error) {
            console.log("ajax错误!");
        }
    });
});
document.onkeydown=function(event){
    if(event.ctrlKey && event.keyCode == 13){
        send();
    }
};
/**
 * 聊天显示区域自动到底
 */
function endScroll() {
    var area = $("#hz-message-body")[0];
    area.scrollTop = area.scrollHeight;
}

/**
 * 退出登录
 */
function logout() {
    $.ajax({
        type: 'post',
        url: ctx + "/logout",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        data: {username:username},
        success: function (data) {
            // console.log()
            window.location.href=ctx+"/login";
        },
        error: function (xhr, status, error) {
            console.log("ajax错误!");
        }
    });
}

$("#upload-img").on("click",function () {
    document.getElementById("btn_file").click();
})

$("#btn_file").on("change",function () {
    var $file = $(this);
    var fileObj = $file[0];
    var windowURL = window.URL || window.webkitURL;
    var dataURL;
    var imgObj = document.createElement("img");
    if (fileObj && fileObj.files && fileObj.files[0]) {
        dataURL = windowURL.createObjectURL(fileObj.files[0]);
        imgObj.src= dataURL;
    } else {
        dataURL = $file.val();
        imgObj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
        imgObj.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = dataURL;
    }
    $("#hz-message-input").html(imgObj);
});


$("#jietu").on("click",function () {
    html2canvas($(".img-head"), {
    // html2canvas($("#hz-message-body"), {
        allowTaint: true,
        taintTest: false,
        onrendered: function(canvas) {
            canvas.id = "mycanvas";
            //document.body.appendChild(canvas);
            //生成base64图片数据
            var dataUrl = canvas.toDataURL();
            var newImg = document.createElement("img");
            newImg.src = dataUrl;
            newImg.className = 'img';
            $("#hz-message-input").html(newImg);
            // $(".product").before(newImg);
        }
    });
});
$("#img-big").on("click",function () {

});

三、后台代码实现

/**
 * WebSocket服务
 */
@RestController
@RequestMapping("/websocket")
@ServerEndpoint(value = "/websocket/{userid}/{username}", configurator = MyEndpointConfigure.class)
public class WebSocketServer {

    /**
     * 在线人数
     */
    private static int onlineCount = 0;

    /**
     * 在线用户的Map集合,key:用户名,value:Session对象
     */
    private static Map<User, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 注入其他类(换成自己想注入的对象)
     */
//    @Resource
//    private MessageService messageService;
    @Resource
    private UserService userService;


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userid") int userid, @PathParam("username") String username) {
        //在webSocketMap新增上线用户
        User user = new User();
        user.setId(userid);
        user.setUserName(username);
        sessionMap.put(user, session);

        //在线人数加加
        WebSocketServer.onlineCount++;

        //通知除了自己之外的所有人
        sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + username+"'}");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        //下线用户名
        String logoutUserName = "";

        //从webSocketMap删除下线用户
        for (Entry<User, Session> entry : sessionMap.entrySet()) {
            if (entry.getValue() == session) {
                sessionMap.remove(entry.getKey());
                logoutUserName = entry.getKey().getUserName();
                break;
            }
        }
        //在线人数减减
        WebSocketServer.onlineCount--;

        //通知除了自己之外的所有人
        sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + logoutUserName + "'}");
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            //JSON字符串转 HashMap
            HashMap hashMap = new ObjectMapper().readValue(message, HashMap.class);

            //消息类型
            String type = (String) hashMap.get("type");

            //来源用户
            Map srcUser = (Map) hashMap.get("srcUser");

            //目标用户
            Map tarUser = (Map) hashMap.get("tarUser");


            //如果点击的是自己,那就是群聊
            if (srcUser.get("username").equals(tarUser.get("username"))) {
                //群聊
                groupChat(session,hashMap);
            } else {
                //私聊
                privateChat(session, tarUser, hashMap);
            }

            //后期要做消息持久化
            Message mess = new Message();
            mess.setFromId(Integer.parseInt((String) srcUser.get("userid")));
            mess.setFromName((String) srcUser.get("username"));
            mess.setToId(Integer.parseInt((String) tarUser.get("userid")));
            mess.setToName((String) tarUser.get("username"));
            mess.setMessage((String) hashMap.get("message"));
//            messageService.insertMessage(mess);
            userService.insertMessage(mess);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

    /**
     * 通知除了自己之外的所有人
     */
    private void sendOnlineCount(Session session, String message) {
        for (Entry<User, Session> entry : sessionMap.entrySet()) {
            try {
                if (entry.getValue() != session) {
                    entry.getValue().getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 私聊
     */
    private void privateChat(Session session, Map tarUser, HashMap hashMap) throws IOException {
        //获取目标用户的session
        boolean boo = false;
        Session tarUserSession = null;
        for (User key : sessionMap.keySet()) {
            if(key.getUserName().equals((String)tarUser.get("username"))){
                boo=true;
                tarUserSession=sessionMap.get(key);
            }
            }
        //如果不在线则发送“对方不在线”回来源用户
        if (!boo) {
            session.getBasicRemote().sendText("{\"type\":\"0\",\"message\":\"对方不在线\"}");
        } else {
            hashMap.put("type", "1");
            tarUserSession.getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
        }
    }

    /**
     * 群聊
     */
    private void groupChat(Session session,HashMap hashMap) throws IOException {
        for (Entry<User, Session> entry : sessionMap.entrySet()) {
            //自己就不用再发送消息了
            if (entry.getValue() != session) {
                hashMap.put("type", "2");
                entry.getValue().getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
            }
        }
    }

    /**
     * 登录
     */
    @RequestMapping("/login/{username}")
    public ModelAndView login(HttpServletRequest request, @PathVariable String username) {
        //插入用户表
        User user = new User();
        user.setUserName(username);
        user.setPassWord("123456");
        int userid = userService.insertUser(user);

        ModelAndView mav = new ModelAndView("socketChart");
        mav.addObject("username",username);
        mav.addObject("userid",userid);
        return mav;
    }

    /**
     * 登出
     */
    @RequestMapping("/logout/{username}")
    public String loginOut(HttpServletRequest request, @PathVariable String username) {
        return "退出成功!";
    }

    /**
     * 获取在线用户
     */
    @RequestMapping("/getOnlineList")
    private List<User> getOnlineList(String username) {
        List<User> allUserList = userService.searchAllUser();
        for (int i = 0; i < allUserList.size(); i++) {
            User user = allUserList.get(i);
            //判断用户是否在线
            boolean boo = false;
            for (Entry<User, Session> entry : WebSocketServer.sessionMap.entrySet()) {
                if (entry.getKey().getUserName().equals(user.getUserName())) {
                    user.setString1("在线");
                    boo=true;
                    break;
                }
            }
            if(!boo){
                user.setString1("离线");
            }
        }
        return allUserList;
    }
    /**
     * 查询聊天记录
     */
    @RequestMapping("/getMessageList")
    private List<Message> getMessageList(int fromId, int toId) {
        List<Message> list = userService.searchMessage(fromId, toId);
        return list;
    }

}

package com.lianxu.websocket;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.websocket.server.ServerEndpointConfig;

/**
 * 解决注入其他类的问题,详情参考这篇帖子:webSocket无法注入其他类:https://blog.csdn.net/tornadojava/article/details/78781474
 */
public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {

    private static volatile BeanFactory context;

    @Override
    public <T> T getEndpointInstance(Class<T> clazz){
        return context.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyEndpointConfigure.context = applicationContext;
    }
}

package com.lianxu.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocket配置
 */
@Configuration
public class WebSocketConfig {


    /**
     * 用途:扫描并注册所有携带@ServerEndpoint注解的实例。 @ServerEndpoint("/websocket")
     * PS:如果使用外部容器 则无需提供ServerEndpointExporter。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    /**
     * 支持注入其他类
     */
    @Bean
    public MyEndpointConfigure  newMyEndpointConfigure (){
        return new MyEndpointConfigure ();
    }
}

四、最终效果实现

使用websocket创建一个简单的即时通信工具
使用websocket创建一个简单的即时通信工具
使用websocket创建一个简单的即时通信工具
点击自己是群聊 点击其他人是私聊

五、问题总结

1.截图,发送文件
2.聊天界面放大缩小
3.添加好友分组
4.设置头像

参考:https://www.cnblogs.com/huanzi-qch/p/10821246.html