im即时通讯系统源码/如何搭建一个自己的im即时通讯呢?

news2024/10/5 18:29:58

​一,思路梳理

1,首先思考群聊的实现方式。

每当一个用户使用websocket建立连接时,都会存放一个连接对象(在connectMap集合存放,键为sessionId,值为该连接对象),每次当用户发送一条数据时,都会遍历connectMap中所有的连接对象,然后进行广播发送消息,接收消息也是,谁的消息都收,来之不拒,所以此为群聊。

 

​2,再来举一反三,思考单聊的实现方式。

单聊的话,要改变下面几个地方。

1,存放connectMap连接对象时,值要为userId(唯一标识)。

2,使用websocket建立连接时要把自己的userId(发送人)和对方的userId(接收人)传到后台,因为发消息时,根据userId得到连接对象,并使用连接对象发消息到对方的窗口和自己的窗口。

3,在js获取消息的地方要判断该消息的发送人userId是否和初始化时的接收人userId一致,如果一致的话则将消息添加到自己的窗口进行显示,如果不一致则不显示。

有一个地方需要提一下,比如要给A用户发送消息,就要根据A的userId得到连接对象,然后就会把消息发送给A用户。演示:ym.fzapp.top

二,代码分析

1,首先是用户聊天框的js代码(html忽略)

此为用户点击在线客服按钮进入聊天框页面就执行的js代码。

说明:下面接收人id写死了为超级管理员,我这里省事情了,因为超级管理员的账号(也就是唯一标识)就是超级管理员这五个字,当真正开发时就要动态获取唯一标识了!

<span style="color:#314659"><span style="background-color:#ffffff"><code class="language-javascript language-js"><script type=<span style="color:#c18401 !important">"text/javascript"</span>>
	<span style="color:#999999 !important"><em>//1,获取连接,new WebSocket()</em></span>
	<span style="color:#999999 !important"><em>//获取到路径url的参数(用户的手机号,这里将手机号作为了用户的唯一标识)</em></span>
    <span style="color:#4078f2 !important">var</span> accounta=<span style="color:#c18401 !important">window</span>.location.search;
    <span style="color:#4078f2 !important">var</span> account=accounta.<span style="color:#50a14f !important">slice</span>(<span style="color:#ae81ff !important">9</span>);
    <span style="color:#999999 !important"><em>//发送人id</em></span>
    <span style="color:#4078f2 !important">var</span> sb=account;
	<span style="color:#999999 !important"><em>//将发送人id参数传给服务端</em></span>
	<span style="color:#4078f2 !important">var</span> wsUrl=<span style="color:#c18401 !important">"ws://127.0.0.1:8082/charRoomServer"</span>;
	<span style="color:#4078f2 !important">var</span> allUrl=wsUrl+<span style="color:#c18401 !important">"/"</span>+sb;
	<span style="color:#999999 !important"><em>//接收人id</em></span>
	<span style="color:#4078f2 !important">var</span> jsrid=<span style="color:#c18401 !important">'超级管理员'</span>;
	<span style="color:#999999 !important"><em>//客户端与服务端建立连接,建立连接以后,它会发出一个ws.open事件</em></span>
	<span style="color:#4078f2 !important">var</span> ws=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">WebSocket</span>(allUrl);
	<span style="color:#999999 !important"><em>//连接成功后就将接收人id发送给服务端</em></span>
	ws.onopen=<span style="color:#4078f2 !important">function</span>(){
		ws.<span style="color:#50a14f !important">send</span>(jsrid);
	}
	<span style="color:#999999 !important"><em>//客户端收到服务端发送的消息</em></span>
	ws.onmessage=<span style="color:#4078f2 !important">function</span>(message){
	    <span style="color:#4078f2 !important">var</span> shenfen=<span style="color:#50a14f !important">JSON</span>.<span style="color:#50a14f !important">stringify</span>(message.data).<span style="color:#50a14f !important">toString</span>();
	    <span style="color:#4078f2 !important">var</span> shenfens=shenfen.<span style="color:#50a14f !important">slice</span>(shenfen.<span style="color:#50a14f !important">lastIndexOf</span>(<span style="color:#c18401 !important">"|"</span>)+<span style="color:#ae81ff !important">1</span>,-<span style="color:#ae81ff !important">1</span>);
     <span style="color:#999999 !important"><em>//这里通过很low的方式拿到了发送人id  [shenfens](后台拼接字符串并前台截取得到)   </em></span>
     <span style="color:#999999 !important"><em>//判断发送人id是否和页面初始化时的接收人id(jsrid)是否一致,相同则说明是对方回复的消息,并将该消息添加到自己的聊天框;如果收到的发送人id与“大白机器人”或者是和自己的id一致,也要将消息添加到自己的聊天框(自己发的消息嘛)</em></span>
        <span style="color:#4078f2 !important">if</span>(jsrid==shenfens||shenfens==<span style="color:#c18401 !important">"大白机器人:"</span>||shenfens==sb){
            <span style="color:#999999 !important"><em>//获取以后,在客户端显示</em></span>
            messages.innerHTML+=message.data;
        }<span style="color:#4078f2 !important">else</span>{
            <span style="color:#999999 !important"><em>//不做任何操作</em></span>
        }
	}
	<span style="color:#999999 !important"><em>//获取某个用户输入的聊天内容,并发送到服务端</em></span>
	 <span style="color:#4078f2 !important">function</span> <span style="color:#50a14f !important">getMessage</span>(){
		<span style="color:#4078f2 !important">var</span> inputMessage=<span style="color:#c18401 !important">document</span>.<span style="color:#50a14f !important">getElementById</span>(<span style="color:#c18401 !important">"inputMessage"</span>).value;
		<span style="color:#999999 !important"><em>//alert(inputMessage);</em></span>
		<span style="color:#999999 !important"><em>//获取消息以后,要发送给服务端,然后广播给所有用户</em></span>
		<span style="color:#4078f2 !important">if</span>(<span style="color:#50a14f !important">typeof</span>(inputMessage)==<span style="color:#c18401 !important">'undefined'</span>){
			<span style="color:#50a14f !important">alert</span>(<span style="color:#c18401 !important">"请输入您要发送的消息!"</span>);
		}<span style="color:#4078f2 !important">else</span>{
			ws.<span style="color:#50a14f !important">send</span>(inputMessage);
			<span style="color:#999999 !important"><em>//输入框消息清空</em></span>
			inputMessage.value=<span style="color:#c18401 !important">""</span>;
		}	
	} 
	<span style="color:#999999 !important"><em>//当关闭页面或者用户退出时,会执行一个ws.close()方法</em></span>
	<span style="color:#c18401 !important">window</span>.onbeforeunload=<span style="color:#4078f2 !important">function</span>(){
		ws.<span style="color:#50a14f !important">close</span>();
	}
	<span style="color:#999999 !important"><em>//按回车发送信息</em></span>
	<span style="color:#c18401 !important">document</span>.onkeyup=<span style="color:#4078f2 !important">function</span>(e){
		<span style="color:#4078f2 !important">if</span>(e.keyCode==<span style="color:#ae81ff !important">13</span>){
			<span style="color:#50a14f !important">getMessage</span>();
			inputMessage.value=<span style="color:#c18401 !important">""</span>;
		}
	}
</script>
</code></span></span>

2,其次为后台系统客服聊天框的js代码

<span style="color:#314659"><span style="background-color:#ffffff"><code class="language-javascript language-js"><script>
        <span style="color:#4078f2 !important">var</span> name=<span style="color:#c18401 !important">""</span>;
        $(<span style="color:#4078f2 !important">function</span> () {
            $.<span style="color:#50a14f !important">post</span>(
                <span style="color:#c18401 !important">"/demo/getName"</span>,
                <span style="color:#4078f2 !important">function</span> (data) {
                    name=data.name;
                },
                <span style="color:#c18401 !important">"json"</span>
            );
 <span style="color:#999999 !important"><em>//得到未读消息并展示到列表中(当点击其中一个未读消息时会得到该消息的账号(前台用户的userId唯一标识))</em></span>
            $.<span style="color:#50a14f !important">post</span>(
                <span style="color:#c18401 !important">"/demo/getweidu"</span>,
                <span style="color:#4078f2 !important">function</span> (data) {
                    <span style="color:#4078f2 !important">var</span> temp=<span style="color:#c18401 !important">''</span>;
                    <span style="color:#4078f2 !important">var</span> count=<span style="color:#ae81ff !important">0</span>;
                    <span style="color:#4078f2 !important">var</span> account=<span style="color:#c18401 !important">''</span>;
                    <span style="color:#4078f2 !important">for</span>(<span style="color:#4078f2 !important">var</span> i=<span style="color:#ae81ff !important">0</span>;i<data.length;i++){
                        temp+=<span style="color:#c18401 !important">'<div class="yonghu" onclick="liaotian('</span>+data[i].account+<span style="color:#c18401 !important">')">\n'</span> +
                            <span style="color:#c18401 !important">'            <span id="lalala">'</span>+data[i].account+<span style="color:#c18401 !important">'</span>\n'</span> +
                            <span style="color:#c18401 !important">'            <div id="'</span>+data[i].account+<span style="color:#c18401 !important">'" class="weidu">'</span>+data[i].count+<span style="color:#c18401 !important">'</div>\n'</span> +
                            <span style="color:#c18401 !important">'        </div>'</span>;
                    }
                    $(<span style="color:#c18401 !important">"#nav"</span>).<span style="color:#50a14f !important">append</span>(temp);
                }
            );
        });

<span style="color:#999999 !important"><em>//这是点击对应的未读消息之后将未读消息展示到客服的聊天框</em></span>
        <span style="color:#4078f2 !important">var</span> sb=<span style="color:#ae81ff !important">null</span>;
        <span style="color:#4078f2 !important">function</span> <span style="color:#50a14f !important">liaotian</span>(v) {  <span style="color:#999999 !important"><em>//下面的websocket内容在这个方法里面,执行这个点击事件之后触发websocket连接</em></span>
            sb=v;
            $(<span style="color:#c18401 !important">"#content"</span>).<span style="color:#50a14f !important">empty</span>();
            $(<span style="color:#c18401 !important">"#"</span>+v).<span style="color:#50a14f !important">hide</span>();
            $.<span style="color:#50a14f !important">post</span>(
                <span style="color:#c18401 !important">"/demo/getxiaoxi"</span>,
                {<span style="color:#f74449 !important">account</span>:v},
                <span style="color:#4078f2 !important">function</span> (data) {
                    <span style="color:#999999 !important"><em>// alert(JSON.stringify(data));</em></span>
                    <span style="color:#4078f2 !important">var</span> str=<span style="color:#c18401 !important">''</span>;
                    <span style="color:#4078f2 !important">for</span>(<span style="color:#4078f2 !important">var</span> i=<span style="color:#ae81ff !important">0</span>;i<data.length;i++){
                        <span style="color:#4078f2 !important">var</span> time=data[i].addtime.<span style="color:#50a14f !important">slice</span>(<span style="color:#ae81ff !important">0</span>,<span style="color:#ae81ff !important">10</span>);
                        str+=<span style="color:#c18401 !important">' <div class="message"><span>'</span>+data[i].account+<span style="color:#c18401 !important">'</span>用户:<span>'</span>+time+<span style="color:#c18401 !important">'</span>'</span>+data[i].message+<span style="color:#c18401 !important">'</div>'</span>;
                    }
                    $(<span style="color:#c18401 !important">"#content"</span>).<span style="color:#50a14f !important">append</span>(str);
                },
                <span style="color:#c18401 !important">"json"</span>
            );
            <span style="color:#999999 !important"><em>//将点击后的未读消息改为已读消息</em></span>
            $.<span style="color:#50a14f !important">post</span>(
                <span style="color:#c18401 !important">"/demo/changeYD"</span>,
                {<span style="color:#f74449 !important">account</span>:v},
                <span style="color:#4078f2 !important">function</span> (data) {
                    <span style="color:#c18401 !important">console</span>.<span style="color:#50a14f !important">log</span>(data);
                }
            );
            <span style="color:#999999 !important"><em>//发送人id(超级管理员写死的,上面说过了)</em></span>
            <span style="color:#4078f2 !important">var</span> wsUrl=<span style="color:#c18401 !important">"ws://127.0.0.1:8082/charRoomServer"</span>;
            <span style="color:#4078f2 !important">var</span> allUrl=wsUrl+<span style="color:#c18401 !important">"/"</span>+<span style="color:#c18401 !important">"超级管理员"</span>;
            <span style="color:#999999 !important"><em>//客户端与服务端建立连接,建立连接以后,它会发出一个ws.open事件</em></span>
            <span style="color:#4078f2 !important">var</span> ws=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">WebSocket</span>(allUrl);
            <span style="color:#999999 !important"><em>//接收人userId</em></span>
            <span style="color:#4078f2 !important">var</span> jsrid=sb;
            <span style="color:#999999 !important"><em>//连接成功后,提示浏览器客户端输入名称</em></span>
            ws.onopen=<span style="color:#4078f2 !important">function</span>(){
                ws.<span style="color:#50a14f !important">send</span>(jsrid);
            }
            <span style="color:#999999 !important"><em>//客户端收到服务端发送的消息</em></span>
            ws.onmessage=<span style="color:#4078f2 !important">function</span>(message){
                <span style="color:#999999 !important"><em>//截取到普通用户的手机号</em></span>
                <span style="color:#4078f2 !important">var</span> shenfen=<span style="color:#50a14f !important">JSON</span>.<span style="color:#50a14f !important">stringify</span>(message.data).<span style="color:#50a14f !important">toString</span>();
                <span style="color:#4078f2 !important">var</span> shenfens=shenfen.<span style="color:#50a14f !important">slice</span>(shenfen.<span style="color:#50a14f !important">lastIndexOf</span>(<span style="color:#c18401 !important">"|"</span>)+<span style="color:#ae81ff !important">1</span>,-<span style="color:#ae81ff !important">1</span>);
                 <span style="color:#c18401 !important">console</span>.<span style="color:#50a14f !important">log</span>(<span style="color:#c18401 !important">"身份:"</span>+shenfens);
                <span style="color:#999999 !important"><em>// //判断发送人id是否和页面初始化时的接收人id(jsrid)是否一致,相同则说明是对方回复的消息</em></span>
                <span style="color:#4078f2 !important">if</span>(jsrid==shenfens||<span style="color:#c18401 !important">"超级管理员"</span>==shenfens){
                    <span style="color:#999999 !important"><em>//获取以后,在客户端显示</em></span>
                    content.innerHTML+=message.data;
                }<span style="color:#4078f2 !important">else</span>{
                    <span style="color:#999999 !important"><em>//不做任何操作</em></span>
                }
            }
            <span style="color:#999999 !important"><em>//获取某个用户输入的聊天内容,并发送到服务端</em></span>
            <span style="color:#4078f2 !important">function</span> <span style="color:#50a14f !important">getMessage</span>(){
                <span style="color:#4078f2 !important">var</span> inputMessage=<span style="color:#c18401 !important">document</span>.<span style="color:#50a14f !important">getElementById</span>(<span style="color:#c18401 !important">"inputMessage"</span>).value;
                <span style="color:#999999 !important"><em>//alert(inputMessage);</em></span>
                <span style="color:#999999 !important"><em>//获取消息以后,要发送给服务端,然后广播给所有用户</em></span>
                <span style="color:#4078f2 !important">if</span>(<span style="color:#50a14f !important">typeof</span>(inputMessage)==<span style="color:#c18401 !important">'undefined'</span>){
                    <span style="color:#50a14f !important">alert</span>(<span style="color:#c18401 !important">"请输入您要发送的消息!"</span>);
                }<span style="color:#4078f2 !important">else</span>{
                    ws.<span style="color:#50a14f !important">send</span>(inputMessage);
                    <span style="color:#999999 !important"><em>//输入框消息清空</em></span>
                    inputMessage.value=<span style="color:#c18401 !important">""</span>;
                }
            }
            <span style="color:#999999 !important"><em>//当关闭页面或者用户退出时,会执行一个ws.close()方法</em></span>
             <span style="color:#c18401 !important">window</span>.onbeforeunload=<span style="color:#4078f2 !important">function</span>(){
                 ws.<span style="color:#50a14f !important">close</span>();
             }
            <span style="color:#999999 !important"><em>//按回车发送信息</em></span>
            <span style="color:#c18401 !important">document</span>.onkeyup=<span style="color:#4078f2 !important">function</span>(e){
                <span style="color:#4078f2 !important">if</span>(e.keyCode==<span style="color:#ae81ff !important">13</span>){
                    <span style="color:#50a14f !important">getMessage</span>();
                    inputMessage.value=<span style="color:#c18401 !important">""</span>;
                }
            }
        }
    </script>
</code></span></span>

3,最后为服务端的websocket实例

<span style="color:#314659"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#4078f2 !important">package</span> com.qianlong.controller;

<span style="color:#4078f2 !important">import</span> com.qianlong.service.SelectService;
<span style="color:#4078f2 !important">import</span> org.springframework.beans.factory.annotation.Autowired;
<span style="color:#4078f2 !important">import</span> org.springframework.stereotype.Component;

<span style="color:#4078f2 !important">import</span> java.io.IOException;
<span style="color:#4078f2 !important">import</span> java.text.SimpleDateFormat;
<span style="color:#4078f2 !important">import</span> java.util.Date;
<span style="color:#4078f2 !important">import</span> java.util.HashMap;
<span style="color:#4078f2 !important">import</span> java.util.Map;
<span style="color:#4078f2 !important">import</span> javax.websocket.OnClose;
<span style="color:#4078f2 !important">import</span> javax.websocket.OnMessage;
<span style="color:#4078f2 !important">import</span> javax.websocket.OnOpen;
<span style="color:#4078f2 !important">import</span> javax.websocket.Session;
<span style="color:#4078f2 !important">import</span> javax.websocket.server.PathParam;
<span style="color:#4078f2 !important">import</span> javax.websocket.server.ServerEndpoint;
<span style="color:#999999 !important"><em>/**
 * 聊天室的服务端程序
 * <span style="color:#c678dd">@author</span> Administrator
 *
 */</em></span>
<span style="color:#999999 !important"><em>//声明websocket某个服务端的地址</em></span>
<span style="color:#fd971f !important">@ServerEndpoint(value = "/charRoomServer/{param}")</span>
<span style="color:#fd971f !important">@Component</span>
<span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">class</span> <span style="color:#50a14f !important">ChatRoomServer</span> {
    <span style="color:#fd971f !important">@Autowired</span>
    <span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">static</span> SelectService selectService;
    <span style="color:#4078f2 !important">private</span> <span style="color:#c18401 !important">boolean</span> firstFlag=<span style="color:#ae81ff !important">true</span>;
    <span style="color:#4078f2 !important">private</span> Session session;
    <span style="color:#4078f2 !important">private</span> String userName;

    <span style="color:#999999 !important"><em>//发送人id</em></span>
    <span style="color:#4078f2 !important">private</span> String userId;
    <span style="color:#999999 !important"><em>//key代表此次客户端的userId,value代表此次连接对象</em></span>
    <span style="color:#4078f2 !important">private</span> <span style="color:#4078f2 !important">static</span> <span style="color:#4078f2 !important">final</span> HashMap<String, Object> connectMap=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">HashMap</span><String, Object>();
    <span style="color:#999999 !important"><em>//保存所有用户昵称信息</em></span>
    <span style="color:#999999 !important"><em>//key是session的id,value是用户昵称</em></span>
    <span style="color:#4078f2 !important">private</span> <span style="color:#4078f2 !important">static</span> <span style="color:#4078f2 !important">final</span> HashMap<String, String> userMap=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">HashMap</span><String, String>();
    <span style="color:#999999 !important"><em>//服务端收到客户端的连接请求,连接成功后会执行此方法</em></span>
    <span style="color:#fd971f !important">@OnOpen</span>
    <span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">void</span> <span style="color:#50a14f !important">start</span>(<span style="color:#fd971f !important">@PathParam(value = "param")</span> String param, Session session) {
        <span style="color:#50a14f !important">this</span>.session=session;
        <span style="color:#50a14f !important">this</span>.userId=param; <span style="color:#999999 !important"><em>//接收参数</em></span>
        connectMap.put(param,<span style="color:#50a14f !important">this</span>);
    }

    <span style="color:#999999 !important"><em>//客户端发来的信息,服务端接收</em></span>
    <span style="color:#fd971f !important">@OnMessage</span>              <span style="color:#999999 !important"><em>//接收人userId</em></span>
    <span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">void</span> <span style="color:#50a14f !important">chat</span>(String clientMessage,Session session) {
        <span style="color:#999999 !important"><em>//firstFlag为true是第一次进入,第二次进入之后设为false</em></span>
        ChatRoomServer client=<span style="color:#ae81ff !important">null</span>;
        <span style="color:#4078f2 !important">if</span>(firstFlag) {
            <span style="color:#50a14f !important">this</span>.userName=clientMessage;
            <span style="color:#999999 !important"><em>//将新进来的用户保存到用户map</em></span>
            userMap.put(session.getId(), userName);

            <span style="color:#4078f2 !important">try</span> {
               <span style="color:#4078f2 !important">if</span>(<span style="color:#c18401 !important">"超级管理员"</span>.equals(userId)){

               }<span style="color:#4078f2 !important">else</span>{
                   <span style="color:#999999 !important"><em>//构造发送给客户端的提示信息</em></span>
                   String message=htmlMessage(<span style="color:#c18401 !important">"大白机器人:"</span>,<span style="color:#c18401 !important">"亲爱的"</span>+userId+<span style="color:#c18401 !important">",您想了解点儿啥?"</span>);
                   client=(ChatRoomServer) connectMap.get(userId);
                   <span style="color:#999999 !important"><em>//给对应的web端发送一个文本信息</em></span>
                   client.session.getBasicRemote().sendText(message);
               }
            } <span style="color:#4078f2 !important">catch</span> (IOException e) {
                e.printStackTrace();
            }
            firstFlag=<span style="color:#ae81ff !important">false</span>;
        }<span style="color:#4078f2 !important">else</span> {
            System.err.println(<span style="color:#c18401 !important">"clientMessage:"</span>+userName);
            <span style="color:#999999 !important"><em>//给对方发消息</em></span>
            String message1=htmlMessage(userId,clientMessage);
            client  = (ChatRoomServer) connectMap.get(userName);
           <span style="color:#4078f2 !important">if</span>(client!=<span style="color:#ae81ff !important">null</span>){
               <span style="color:#4078f2 !important">try</span> {
                   client.session.getBasicRemote().sendText(message1);
               } <span style="color:#4078f2 !important">catch</span> (IOException e) {
                   e.printStackTrace();
               }
           }
            <span style="color:#999999 !important"><em>//给自己窗口发消息</em></span>
            String message2=htmlMessage(userId,clientMessage);
            client  = (ChatRoomServer) connectMap.get(userId);
            <span style="color:#4078f2 !important">try</span> {
                client.session.getBasicRemote().sendText(message2);
            } <span style="color:#4078f2 !important">catch</span> (IOException e) {
                e.printStackTrace();
            }
           
            <span style="color:#999999 !important"><em>//这是将前台用户发送的消息存数据库并标记为未读,和上面通信没关系</em></span>
            <span style="color:#4078f2 !important">if</span>(<span style="color:#c18401 !important">"超级管理员"</span>.equals(userId)){

            }<span style="color:#4078f2 !important">else</span>{
                Map map=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">HashMap</span>();
                map.put(<span style="color:#c18401 !important">"account"</span>,userId);
                map.put(<span style="color:#c18401 !important">"message"</span>,clientMessage);
                map.put(<span style="color:#c18401 !important">"addtime"</span>,<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">Date</span>());
                <span style="color:#c18401 !important">int</span> <span style="color:#c18401 !important">i</span> <span style="color:#ab5656">=</span> selectService.chatInsert(map);
                System.out.println(i);
            }
        }
        }
    
    <span style="color:#999999 !important"><em>/**
     * 前台js的ws.close事件,会触发后台的标注onClose的方法
     */</em></span>
    <span style="color:#fd971f !important">@OnClose</span>
    <span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">void</span> <span style="color:#50a14f !important">close</span>() {
        userMap.remove(session.getId());
        connectMap.remove(userId);
    }
    <span style="color:#999999 !important"><em>/**
     * 渲染页面,把信息构造好标签再发送
     */</em></span>
    <span style="color:#4078f2 !important">public</span> String <span style="color:#50a14f !important">htmlMessage</span>(String userName,String message) {
        StringBuffer stringBuffer=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">StringBuffer</span>();
        SimpleDateFormat sf=<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">SimpleDateFormat</span>(<span style="color:#c18401 !important">"yyyy-MM-dd HH:mm:ss"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<article>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<span>"</span>+sf.format(<span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">Date</span>())+<span style="color:#c18401 !important">"</span>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<div class='avatar'>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<h3>"</span>+userName+<span style="color:#c18401 !important">"</h3>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"</div>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<div class='msg'>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<div class='tri'></div>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"<div class='msg_inner'>"</span>+message+<span style="color:#c18401 !important">"</div>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"</div>"</span>);
        stringBuffer.append(<span style="color:#c18401 !important">"</article>"</span>);
        <span style="color:#999999 !important"><em>//这里拼接了消息发送人的userId,在前台进行截取字符串接收发送人的userId</em></span>
        stringBuffer.append(<span style="color:#c18401 !important">"|"</span>+userName);
        <span style="color:#4078f2 !important">return</span> stringBuffer.toString();
    }
}
</code></span></span>

三,依赖注入

websocket中进行依赖注入service并调用service方法进行数据库存储,如果按常规的方式是走不通的。

解决方式:

在该springboot项目中添加一个WebsocketConfig配置类,对service进行配置。

<span style="color:#314659"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#fd971f !important">@Configuration</span>
<span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">class</span> <span style="color:#50a14f !important">WebSocketConfig</span> {
    <span style="color:#999999 !important"><em>/**
     * ServerEndpointExporter 用于扫描和注册所有携带 ServerEndPoint 注解的实例,
     * 若部署到外部容器 则无需提供此类。
     */</em></span>
    <span style="color:#fd971f !important">@Bean</span>
    <span style="color:#4078f2 !important">public</span> ServerEndpointExporter <span style="color:#50a14f !important">serverEndpointExporter</span>() {
        <span style="color:#4078f2 !important">return</span> <span style="color:#4078f2 !important">new</span> <span style="color:#50a14f !important">ServerEndpointExporter</span>();
    }

    <span style="color:#999999 !important"><em>/**
     * 因 SpringBoot WebSocket 对每个客户端连接都会创建一个 WebSocketServer(<span style="color:#c678dd">@ServerEndpoint</span> 注解对应的对象,Bean 注入操作会被直接略过,因而手动注入一个全局变量
     */</em></span>
    <span style="color:#fd971f !important">@Autowired</span>
    <span style="color:#4078f2 !important">public</span> <span style="color:#4078f2 !important">void</span> <span style="color:#50a14f !important">setSelectService</span>(SelectService selectService) {
        ChatRoomServer.selectService = selectService;
    }
}
</code></span></span>

然后在websocket中注入service

在这里插入图片描述

在这里插入图片描述

四,效果展示

进到聊天框中(左下角的用户名忽略,因为上面通过截取字符串得到的发送人userId,所以这里多了一个userId)

登录之后会提示未读消息的信息。

点击客服管理,进入客服聊天平台,并显示消息未读数。

这是给123456用户发送的消息,其他用户也是收不到的。

查看123456用户的聊天框内容,可以收到客服的消息,然后该用户可以和客服实现在线单聊。

本次websocket讲解到此结束,谢谢观赏!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1076795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

js Learn(异步JavaScript)

在这个模块中&#xff0c;我们来看看异步JavaScript&#xff0c;为什么它很重要&#xff0c;以及如何使用它来有效地处理潜在的阻塞操作&#xff0c;比如从服务器获取资源。 指南 异步JavaScript介绍 在本文中&#xff0c;我们将学习同步&#xff08;synchronous&#xff09…

TLR4-IN-C34-C2-COO,一种结合了TLR4抑制剂TLR4-IN-C34的连接器

TLR4-IN-C34-C2-COO是一种结合了TLR4抑制剂TLR4-IN-C34的连接器&#xff0c;在免疫调节中发挥重要作用&#xff0c;它通过抑制TLR4信号通路的传导&#xff0c;从而达到降低炎症反应的目的。TLR4是Toll样受体家族中的一员&#xff0c;它主要识别来自细菌和病毒的保守模式&#x…

零碳联盟:改变世界,实现绿色能源的共同梦想

如今&#xff0c;全球气候变暖已然成为我们面对的头等大事。温室气体的排放不断升高&#xff0c;导致地球温度上升&#xff0c;带来了严重的极端气候、冰川消融和海平面上升等问题。这一切都源于人类活动&#xff0c;特别是大规模使用化石燃料&#xff0c;如煤炭发电、供暖以及…

AIGC | LLM 提示工程 -- 如何向ChatGPT提问

当前生成式人工智能已经成为革命性的驱动源&#xff0c;正在迅速地重塑世界&#xff0c;将会改变我们生活方式和思考模式。LLM像一个学会了全部人类知识的通才&#xff0c;但这不意味每个人可以轻松驾驭这个通才。我们只有通过学习面向LLM的提示工程&#xff0c;才可以更好的让…

2023中考满分多少 中考总分数展示

中考总分根据地区而不同&#xff0c;以下是各地区总分数展示&#xff1a; 大部分地区的中考总分为750分&#xff0c;包括语文150分、数学150分、英语150分&#xff08;其中听力测试30分&#xff09;、思想品德与历史合卷共150分&#xff0c;物理与化学合卷共150分。 安徽中考…

计算机视觉--距离变换算法

计算机视觉 文章目录 计算机视觉前言距离变换 总结 前言 计算机视觉CV是人工智能一个非常重要的领域。 在本次的距离变换任务中&#xff0c;我们将使用D4距离度量方法来对图像进行处理。通过这次实验&#xff0c;我们可以更好地理解距离度量在计算机视觉中的应用。希望大家对计…

flutter sdk提供完整页面的ui

1.完整ui页面 可以借鉴一些使用案例&#xff1a; return Placeholder();/// A widget that draws a box that represents where other widgets will one day /// be added. /// /// This widget is useful during development to indicate that the interface is /// not yet…

总结四:数据库(MySQL)面经

文章目录 一、SQL1、介绍一下数据库分页2、介绍一下SQL中的聚合函数3、表跟表是怎么关联的?4、说一说你对外连接的了解&#xff1f;5、说一说数据库的左连接和右连接&#xff1f;6、SQL中怎么将行转成列&#xff1f;7、谈谈你对SQL注入的理解&#xff1f;8、将一张表的部分数据…

车载激光雷达标定板在无人驾驶中的作用

在自动驾驶领域&#xff0c;激光雷达的作用主要是通过扫描周围环境&#xff0c;获取车辆行驶过程中路况和障碍物的位置和形状&#xff0c;并将数据和信号传递给自动驾驶系统&#xff0c;帮助其做出相应的驾驶决策。 激光雷达使其成为自动驾驶中不可或缺的组成部分。激光雷达可以…

Dremio:新一代数据湖仓引擎

Dremio数据湖引擎 1、什么是Dremio2、什么是数据湖仓2.1、数据湖仓的历史和演变 3、Dremio查询引擎&#xff08;Dremio Sonar&#xff09;3、Dremio特点1、唯一具有自助式SQL分析功能的数据湖仓2、数据完全开放&#xff0c;无锁定3、亚秒级性能&#xff0c;云数据仓库成本的1/1…

前后端分离计算机毕设项目之基于springboot+vue的房屋租赁系统《内含源码+文档+部署教程》

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

47 从前序与中序遍历序列构造二叉树

从前序与中序遍历序列构造二叉树 先序无法确定子树大小&#xff0c;中序找不到根&#xff1b;所以用先序找根&#xff0c;用中序找大小题解1 递归题解2 迭代 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同…

世界各国家地区3d地形图

1、GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图高级培训班 2、全流程R语言Meta分析核心技术 3、最新CMIP6数据处理及在气候变化、水文、生态等领域中的实践技术应用 4、WOFOST模型与PCSE模型实践技术应用 5、Biome-BGC生态系统模型与Python融合技术实践应用 6、基于…

Sqlserver查看表的主键,删除主键,修改主键

1.查看表的结构 EXEC sp_help 表名; 查询使用 sp_help 存储过程&#xff0c;它将返回有关表的详细信息&#xff0c;包括列名、数据类型、约束等。你可以在结果中查找带有 “PK” 标记的列&#xff0c;它们表示主键约束。 2.查看表的主键信息 EXEC sp_pkeys 表名; 查询使用 sp_…

直线导轨精度等级在设备中有什么影响?

直线导轨的精度选择是直线导轨应用中的重要环节&#xff0c;需要根据具体的应用场景和设备要求来选择合适的精度等级&#xff08;常见分3个等级&#xff1a;N/H/P&#xff09;。下面我们来详细了解一下直线导轨的精度选择。 1、精度等级的概念&#xff1a;直线导轨的精度等级是…

linux查看系统信息命令

1.查看linux内核版本 [rootmaster ~]# uname -r 3.10.0-123.el7.x86_64 [rootmaster ~]# uname -a Linux master 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux2.查看文件系统的磁盘大小和剩余空间大小 [rootmaster ~]# df -h …

手机没电用日语怎么说?你会吗?柯桥常用日语学习

手机没电在日语里可以表达为: 1. スマホの電池が切れた。 直接使用“電池が切れる”来表示电池没有电了。 2. スマホのバッテリーが空に15857575376なった。 “バッテリーが空になる”也是表示电量耗尽的常用表达。 3. 充電が必要だ。 “充電が必要”意思是需要充电。 4…

使用 Splashtop 驾驭未来媒体和娱乐

在当今时代&#xff0c;数字转型不再是可选项&#xff0c;而是必选项。如今&#xff0c;媒体与娱乐业处于关键时刻&#xff0c;正在错综复杂的创意、技术和远程协作迷宫之中摸索前进。过去几年发生的全球事件影响了我们的日常生活&#xff0c;不可逆转地改变了行业的运作方式&a…

Fuzz测试 发现软件中的隐患和漏洞的秘密武器

0x01 什么是模糊测试 模糊测试&#xff08;Fuzz Testing&#xff09;是一种广泛用于软件安全和质量测试的自动化测试方法。它的基本思想是向输入参数或数据中注入随机、不规则或异常的数据&#xff0c;以检测目标程序或系统在处理不合法、不正常或边缘情况下的行为。模糊测试通…

ctDNA助力难治性RAS野生型mCRC抗EGFR单抗再挑战优势人群筛选

ctDNA检测方便快捷、安全性好、可反复取样&#xff0c;在CRC精准治疗领域具有广阔的应用前景。动态ctDNA检测有望指导患者抗EGFR单抗治疗的“再挑战”&#xff0c;为患者带来更多希望。但最佳抗EGFR单抗再挑战策略、对比标准三线治疗的疗效差异及ctDNA检测在其中扮演的角色尚无…