当前位置: 代码网 > it编程>编程语言>Java > springboot+websocket客服聊天

springboot+websocket客服聊天

2024年08月06日 Java 我要评论
springboot聊天

续:spring boot 完整后端接口案例_cc&的博客-csdn博客

后台代码

1.在pom.xml中添加spring-boot-starter-

      <!--websocket-->
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-websocket</artifactid>
        </dependency>

 2. 添加配置,先在src\main\resources\application.yml中添加:

server:
  max-http-header-size: 8192

 如果不加的话可能导致无法进行访问。 

3.新建一个配置类,主要一个bean,用来启动服务是也启动websocket服务

 

package com.cc.springserver.config;

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.socket.server.standard.serverendpointexporter;

@configuration
public class websocketconfig {
    //websocket
    @bean
    public serverendpointexporter serverendpointexporter() {
        return new serverendpointexporter();
    }

}

 注意:这个类必须有@configuration注解

4.新建一个model来封装进行对话的对象

 

package com.cc.springserver.entity;

import javax.websocket.session;

public class socketuserinfo {
    //用户sessionid
    private string sessionid;

    //用户session
    private session session;

    //目标用户sessionid
    private string targetsessionid;

    //用户角色
    private string userrole;

    public string getuserrole() {
        return userrole;
    }

    public void setuserrole(string userrole) {
        this.userrole = userrole;
    }

    public string getsessionid() {
        return sessionid;
    }

    public void setsessionid(string sessionid) {
        this.sessionid = sessionid;
    }

    public session getsession() {
        return session;
    }

    public void setsession(session session) {
        this.session = session;
    }

    public string gettargetsessionid() {
        return targetsessionid;
    }

    public void settargetsessionid(string targetsessionid) {
        this.targetsessionid = targetsessionid;
    }
}

 5.新建一个controller类来管理socket会话,它主要完成如下场景业务:

package com.cc.springserver.controller;

import com.alibaba.fastjson.json;
import com.cc.springserver.entity.socketuserinfo;
import org.springframework.stereotype.component;

import javax.websocket.*;
import javax.websocket.server.pathparam;
import javax.websocket.server.serverendpoint;
import java.io.ioexception;
import java.util.hashmap;
import java.util.map;
import java.util.concurrent.concurrenthashmap;

//参数role判断用户角色0是客服,1是用户
@serverendpoint(value = "/websocket/{role}")
@component
public class websocketcontroller {

    //用本地线程保存session
    private static threadlocal<session> sessions = new threadlocal<session>();
    //保存所有连接上的用户的session
    private static map<string, socketuserinfo> usersessionmap = new concurrenthashmap<>();
    //保存在线客服的session
    private static map<string, socketuserinfo> serversessionmap = new concurrenthashmap<>();

    //连接
    @onopen
    public void onopen(session session, @pathparam(value="role") integer role) {

        //默认返回错误状态
        map<string, string> resultmap = new hashmap<>();
        resultmap.put("state", "error");

        //保证各个线程里的变量相对独立于其他线程内的变量
        sessions.set(session);

        //客服上线
        if (role.equals(0)) {

            //创建一个在线客服信息
            socketuserinfo serverinfo = new socketuserinfo();
            serverinfo.setsessionid(session.getid());
            serverinfo.setsession(session);
            serverinfo.setuserrole("客服");

            //告诉客服连接成功
            resultmap.put("state", "success");

            //去查询是否有排队中的用户
            //如果存在排队的用户,就将用户和客服绑定
            if (findlineuser() != null){
                socketuserinfo userinfo = usersessionmap.get(findlineuser());
                //将用户绑定到客服
                serverinfo.settargetsessionid(userinfo.getsessionid());
                //将客服绑定到用户
                userinfo.settargetsessionid(serverinfo.getsessionid());
                usersessionmap.put(userinfo.getsessionid(), userinfo);
                system.out.println("客户"+ serverinfo.getsessionid() + "正在为用户" + userinfo.getsessionid()+"服务");

                map<string, string> result = new hashmap<>();
                //客服显示用户信息
                result.put("msg", "正在为用户"+userinfo.getsessionid()+"服务!");
                sendmsg(serverinfo.getsession(), json.tojsonstring(result));
                //告诉用户有客服为他服务
                result.put("msg", "客服"+serverinfo.getsessionid()+"正在为您服务!");
                sendmsg(userinfo.getsession(), json.tojsonstring(result));
            }

            //将在线客服信息保存到map中
            serversessionmap.put(session.getid(), serverinfo);
            system.out.println("客服:" + serverinfo.getsessionid() + "连接上服务器,当前在线客服共计:" + serversessionmap.size());
        }
        if (role.equals(1)) {

            //创建一个在线用户信息
            socketuserinfo userinfo = new socketuserinfo();
            userinfo.setsessionid(session.getid());
            userinfo.setsession(session);
            userinfo.setuserrole("用户");

            //告诉用户连接成功
            resultmap.put("state", "success");

            //去查询是否有在线的客服
            //有空闲客服就将用户和客服绑定
            if (findfreeserver() != null){
                socketuserinfo serverinfo = serversessionmap.get(findfreeserver());
                //将用户绑定到客服
                serverinfo.settargetsessionid(userinfo.getsessionid());
                serversessionmap.put(serverinfo.getsessionid(), serverinfo);
                //将客服绑定到用户
                userinfo.settargetsessionid(serverinfo.getsessionid());
                system.out.println("客户"+ serverinfo.getsessionid() + "正在为" + userinfo.getsessionid()+"服务");

                map<string, string> result = new hashmap<>();
                //客服显示用户信息
                result.put("msg", "正在为用户"+userinfo.getsessionid()+"服务!");
                sendmsg(serverinfo.getsession(), json.tojsonstring(result));
                result.put("msg", "客服"+serverinfo.getsessionid()+"正在为您服务!");
                sendmsg(userinfo.getsession(), json.tojsonstring(result));
            } else {
                //告诉用户系统繁忙
                resultmap.put("msg", "系统繁忙!");
            }

            //将在线用户信息保存到map中
            usersessionmap.put(session.getid(), userinfo);
            system.out.println("用户编号:" + userinfo.getsessionid() + "连接上服务器,当前在线用户共计:" + usersessionmap.size());
        }
        //返回连接信息
        string result = json.tojsonstring(resultmap);
        system.out.println(result);
        sendmsg(session, result);
    }

    //关闭连接
    @onclose
    public void onclose(session session) {
        socketuserinfo serverinfo = serversessionmap.get(session.getid());
        //客服下线
        if (serverinfo != null) {
            //将客户从map中移除
            serversessionmap.remove(session.getid());

            //查看是否有服务服务对象
            if (null != serverinfo.gettargetsessionid()){
                //给用户说系统错误
                map<string, string> result = new hashmap<>();
                result.put("msg", "系统错误,请刷新重试!");
                sendmsg(usersessionmap.get(serverinfo.gettargetsessionid()).getsession(), json.tojsonstring(result));
            }
            system.out.println("客服编号:" + serverinfo.getsessionid() + "退出了连接,当前在线客服共计:" + serversessionmap.size());
        } else {//用户下线
            //将用户从map中移除
            usersessionmap.remove(session.getid());

            //从客服中解绑
            for (socketuserinfo serversocketinfo: serversessionmap.values()) {
                //查找绑定的客服,即客服绑定的用户不为空,并且绑定的用户id和现在下线的用户id一样
                if (serversocketinfo.gettargetsessionid() != null && serversocketinfo.gettargetsessionid().equals(session.getid())){
                    //解绑
                    serversocketinfo.settargetsessionid(null);
                    serversessionmap.put(serversocketinfo.getsessionid(), serversocketinfo);
                    system.out.println("用户编号:" + session.getid() + "断开了与客服" + serversocketinfo.getsessionid() + "的连接");

                    //客服解绑以后,可能还会有在线排队的用户,就让这个客服去
                    string lineuser = findlineuser();
                    if (lineuser != null){
                        //将用户绑定到客服
                        serversocketinfo.settargetsessionid(lineuser);
                        serversessionmap.put(serversocketinfo.getsessionid(), serversocketinfo);
                        //将客服绑定到用户
                        usersessionmap.get(lineuser).settargetsessionid(serversocketinfo.getsessionid());
                        system.out.println("客户"+ serversocketinfo.getsessionid() + "正在为" + lineuser+"服务");

                        map<string, string> result = new hashmap<>();
                        //客服显示用户信息
                        result.put("msg", "正在为用户"+lineuser+"服务!");
                        sendmsg(serversocketinfo.getsession(), json.tojsonstring(result));
                        //用户显示客户信息
                        result.put("msg", "客服"+serversocketinfo.getsessionid()+"正在为您服务!");
                        sendmsg(usersessionmap.get(lineuser).getsession(), json.tojsonstring(result));
                    }
                }
            }
            system.out.println("用户编号:" + session.getid() + "退出了连接,当前在线用户共计:" + usersessionmap.size());
        }
    }

    //用户和客户端互相传递消息
    @onmessage
    public void onmessage(string message, session session) {
        //消息
        map<string, string> result = new hashmap<>();

        socketuserinfo serverinfo = serversessionmap.get(session.getid());
        //客服消息
        if (serverinfo != null) {
            system.out.println("客服"+ session.getid()+"发送消息:\""+ message +"\"给用户"+serversessionmap.get(session.getid()).gettargetsessionid());
            result.put("msg", "客服"+session.getid()+":"+message);
            //将消息发送给用户
            //要判断是否绑定到有用户如果有就将消息传递到用户
            if (null != serversessionmap.get(session.getid()).gettargetsessionid()){
                sendmsg(usersessionmap.get(serversessionmap.get(session.getid()).gettargetsessionid()).getsession(), json.tojsonstring(result));
            } else {//如果没有就将消息给自己,嘻嘻嘻
                sendmsg(session, json.tojsonstring(result));
            }

        } else {//用户消息
            system.out.println("用户"+ session.getid()+"发送消息:\""+ message +"\"给客户"+usersessionmap.get(session.getid()).gettargetsessionid());
            result.put("msg", "用户"+session.getid()+":"+message);
            //将消息发送给客服
            //判断是否绑定了客服,如果有就发送消息
            if (null != usersessionmap.get(session.getid()).gettargetsessionid()){
                sendmsg(serversessionmap.get(usersessionmap.get(session.getid()).gettargetsessionid()).getsession(), json.tojsonstring(result));
            } else{//同上
                sendmsg(session,json.tojsonstring(result));
            }
        }
    }

    //异常
    @onerror
    public void onerror(session session, throwable throwable) {
        system.out.println("发生异常!");
        throwable.printstacktrace();
    }



    //统一的发送消息方法
    private synchronized void sendmsg(session session, string msg) {
        try {
            session.getbasicremote().sendtext(msg);
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }

    //查询排队用户
    private synchronized string findlineuser(){
        //判断是否有用户
        if (usersessionmap.size() > 0){
            //遍历所有用户,查找一个排队的用户
            for (socketuserinfo userinfo: usersessionmap.values()) {
                if (null == userinfo.gettargetsessionid()){
                    return userinfo.getsessionid();
                }
            }
        }
        return null;
    }

    //查询在线空闲客服
    private  synchronized string findfreeserver(){
        //判断是否有客服
        if (serversessionmap.size() > 0){
            //遍历所有客服,查找一个空闲的客服
            for (socketuserinfo serverinfo: serversessionmap.values()) {
                if (null == serverinfo.gettargetsessionid()){
                    return serverinfo.getsessionid();
                }
            }
        }
        return null;
    }
}

后台代码到这来就完成了。


前端代码

1) 客户端


<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>辕门-在线咨询</title>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
	<p id="message"></p>
	<form id="clientchat">
		<input type="text" style="display: none;" id="username"  />
		<input type="text" style="display: none;" id="targetusername" />
		<input type="text" id="sendmsg"></input>
		<button type="button" onclick="send()">发送</button>
	</form>
</body>
<script>
var websocket = null;

var userid = null;

//判断当前浏览器是否支持websocket
if('websocket' in window){
    websocket = new websocket("ws://127.0.0.1:9999/websocket/1");
} else {
    alert("don't support websocket!")
}

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

//连接成功建立的回调方法
websocket.onopen = function(event){
    setmessageinnerhtml("连接已建立!");
}

//接收到消息的回调方法
websocket.onmessage = function(event){
	var result = event.data
	var ob = json.parse(result)
	//判断用户状态
	if(ob.state != undefined && ob.state != "success"){
		setmessageinnerhtml("非法连接!");
		websocket.close();
	}
	
	//判断是否有消息
	if(ob.msg != undefined){
		setmessageinnerhtml(ob.msg);
	}
}

//连接关闭的回调方法
websocket.onclose = function(){
    setmessageinnerhtml("close");
}

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

//将消息显示在网页上
function setmessageinnerhtml(innerhtml){
    document.getelementbyid('message').innerhtml += innerhtml + '<br/>';
}

//关闭连接
function closewebsocket(){
    websocket.close();
}

//发送消息
function send(){
	var sendmsg = $("#sendmsg").val();
	setmessageinnerhtml("我 :" + sendmsg)
    websocket.send(sendmsg);
    $("#sendmsg").val("");
}
</script>
</html>

 

2)服务端

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<title>辕门-im</title>
	<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
	<p id="message"></p>
	<form id="clientchat">
		<input type="text" style="display: none;" id="username"  />
		<input type="text" style="display: none;" id="targetusername" />
		<input type="text" id="sendmsg"></input>
		<button type="button" onclick="send()">发送</button>
	</form>
</body>
<script>
var websocket = null;

var userid = null;

//判断当前浏览器是否支持websocket
if('websocket' in window){
    websocket = new websocket("ws://127.0.0.1:9999/websocket/0");
} else {
    alert("don't support websocket!")
}

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

//连接成功建立的回调方法
websocket.onopen = function(event){
    setmessageinnerhtml("连接已建立!");
}

//接收到消息的回调方法
websocket.onmessage = function(event){
	var result = event.data
	var ob = json.parse(result)
	//判断用户状态
	if(ob.state != undefined && ob.state != "success"){
		setmessageinnerhtml("非法连接!");
		websocket.close();
	}
	
	//判断是否有消息
	if(ob.msg != undefined){
		setmessageinnerhtml(ob.msg);
	}
}

//连接关闭的回调方法
websocket.onclose = function(){
    setmessageinnerhtml("close");
}

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

//将消息显示在网页上
function setmessageinnerhtml(innerhtml){
    document.getelementbyid('message').innerhtml += innerhtml + '<br/>';
}

//关闭连接
function closewebsocket(){
    websocket.close();
}

//发送消息
function send(){
	var sendmsg = $("#sendmsg").val();
	setmessageinnerhtml("我 :" + sendmsg)
    websocket.send(sendmsg);
    $("#sendmsg").val("");
}
</script>
</html>

 

 

 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com